Small width layout Medium width layout Maximum width layout Small text Medium text Large text
     Search
Downloads Downloads Directory Directory Forums Forums Forge Forge Blogs Blogs        Marketplace Marketplace Careers Program Careers
Products › Development › Forge › Component - WebControls Register  |  

 

dnn_ct_webcontrols_170x64.gif

 

  Quick Links  
 


  Team Leadership  

Jon Henning

jonhenning.jpg

 


  DotNetNuke Projects  
The DotNetNuke Projects are a special category of platform extensions which are developed by volunteers to conform to the high professional standards mandated by DotNetNuke Corporation. The DotNetNuke Projects are distributed as a standard part of the DotNetNuke core application release offerings.

 


  Ads  
WebHostForAsp.net
 


  Sponsors  

Meet Our Sponsors

.: CounterSoft :.
telerik
ExactTarget email software solutions
Merak Mail Server
FCKeditor Project
Salaro -- Skins and more
 


DotNetNuke® Project :: WebControls

The primary purpose of the DotNetNuke WebControls project is to allow developers to utilize feature-rich controls in their applications without the associated cost or distribution restrictions associated with commercial controls. All controls utilize the ClientAPI, and therefore support a rich client side object model, work cross-browser, and utilize AJAX functionality.

The DotNetNuke TreeView control is an open-source ASP.NET WebControl that has a rich client-side object model and supports advanced featuresets like populate on demand and keyboard navigation.
The DotNetNuke Menu control is an open-source ASP.NET WebControl that has a rich client-side object model and supports advanced featuresets like populate on demand and keyboard navigation (soon).
The DotNetNuke Label Edit control is an open-source ASP.NET WebControl that allows any label to be editable on the client where it uses a client-callback to persist the changes. Simply specify a client-side event like onclick to allow the user to edit. It supports RichText and MultiLine editing.
The DotNetNuke Text Suggest control is an open-source ASP.NET WebControl that allows any textbox to suggest the results the user is looking for by dynamically populating a menu of matched items.
The DotNetNuke Tab Strip control is an open-source ASP.NET WebControl that allows a page to be displayed in a tabular manner. It supports 3 rendering modes, including AJAX on-demand loading to allow for optimal performance.
The DotNetNuke ToolBar control is an open-source ASP.NET WebControl that allows a toolbar to be attached to any control.
 


WebControls Project Blog
Feb 12

Posted by: Jon Henning
2/12/2007

With my plate relatively clear, I have decided to spend some time investigating the released version of Microsoft AJAX Extensions for ASP.NET 2.0 (formarly Atlas and from now on I will call it MS AJAX).  Specifically, I want to see what advantages and disadvantages I would have by utilizing this framework instead of (or addition to) the ClientAPI.  One of the first things that I looked for was the ability to make "callbacks".  I had heard about Atlas' ability to invoke webservices for some time now and have been on a project that was IE specific and therefore was able to use the WebService behavior to accomplish the same thing.  While this functionality is cool, people who know me, know that my real passion is for writing reusable webcontrols.  Writing a webcontrol that needs to communicate with the server

  1. Should not require the end user to expose a webservice. 
  2. Communication to the server should allow the control be able to raise events in the context of the current page. 

In my opinion, these two requirements are vital to writing webcontrols. 

My initial look through the documentation I found little that would assist me in the answer (eventually I found this last sample).  Searching google yielded some promising results.  Apparently, there is this concept called PageMethods that appeared to be able to make a callback from the client to the server without the need for a separate webservice.  After digging through several sites explaining their use and lack of documentation I soon learned that through the various releases of this feature, quite a few changes were made.  Two of these changes are the need to also decorate your method with a ScriptMethod attribute (though when I try it, this does not seem necessary any more), and the fact that in the later betas these methods are now required to be static!
 

It appears that PageMethods will satisfy my first requirement (not needing external webservices), however, the second is not met.  For we need the context of the current page to be useful.  To understand what I mean, lets take the DNNLabelEdit control.  A developer can place this on any page or module (for DNN), handle an event (UpdateLabel) and successfully have access to all it needs to update the database (ModuleId for example).  If we don't have the context of the page, we will need the information posted to the server through the callback.  The control cannot make assumptions on what should and shouldn't be posted, so this leaves it up to the developer.


One of the reasons for the change in requiring static/shared methods is stated here
"They reason the AJAX team decided to make these methods static was so you could avoid page-lifecycle issues and subtleties, such as the inability to modify or access page state"

ASP.NET 2.0 out of the box supports callbacks.  These same issues are present, yet they still support the feature!  I know, for I have researched and documented them when dealing with the DNNTabStrip control.  I suppose I am not as upset as I could be, especialy if I had tried to adopt Atlas earlier and had developed solutions requiring this functionality like others have commented in the blogs listed above. It is looking like I will be continuing the use of the ClientAPI's callback functionality.  Note:  I could choose to use the ASP.NET 2.0 callback functionality, but I don't think it worth moving, since my callback implementation has a few more enhancments included.

Some people have questioned why even bother with PageMethods if they have to be static.  They argue they are just like webservices.  The fact that they appear to satisfy my first requirement makes them different. 

Two final notes before moving on. 

First, I am readily admitting that I just started researching MS AJAX, and therefore may not have all my facts straight.  If someone knows another way that MS AJAX solves my requirements above, please comment or send me an email.

Finally, I see many people who decide to use PageMethods do so by setting the ScriptManager's EnablePageMethods property to true.  I would highly recommend against this.  While it makes your invoking of the method simple, it generates a large amount of payload sent down to the client.  To see what I mean, I am listing the output generated within the page for only two simple methods (Add and Add2)


var PageMethods = function() {
PageMethods.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
PageMethods.prototype = {
Add:function(x,y,succeededCallback, failedCallback, userContext) {
return this._invoke(PageMethods.get_path(), 'Add',false,{x:x,y:y},succeededCallback,failedCallback,userContext); },
Add2:function(x,y,succeededCallback, failedCallback, userContext) {
return this._invoke(PageMethods.get_path(), 'Add2',false,{x:x,y:y},succeededCallback,failedCallback,userContext); }}
PageMethods.registerClass('PageMethods',Sys.Net.WebServiceProxy);
PageMethods._staticInstance = new PageMethods();
PageMethods.set_path = function(value) {
var e = Function._validateParams(arguments, [{name: 'path', type: String}]); if (e) throw e; PageMethods._staticInstance._path = value; }
PageMethods.get_path = function() { return PageMethods._staticInstance._path; }
PageMethods.set_timeout = function(value) { var e = Function._validateParams(arguments, [{name: 'timeout', type: Number}]); if (e) throw e;

if (value < 0) { throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout); }
PageMethods._staticInstance._timeout = value; }
PageMethods.get_timeout = function() {
return PageMethods._staticInstance._timeout; }
PageMethods.set_defaultUserContext = function(value) {
PageMethods._staticInstance._userContext = value; }
PageMethods.get_defaultUserContext = function() {
return PageMethods._staticInstance._userContext; }
PageMethods.set_defaultSucceededCallback = function(value) {
var e = Function._validateParams(arguments, [{name: 'defaultSucceededCallback', type: Function}]); if (e) throw e;

PageMethods._staticInstance._succeeded = value; }
PageMethods.get_defaultSucceededCallback = function() {
return PageMethods._staticInstance._succeeded; }
PageMethods.set_defaultFailedCallback = function(value) {
var e = Function._validateParams(arguments, [{name: 'defaultFailedCallback', type: Function}]); if (e) throw e;

PageMethods._staticInstance._failed = value; }
PageMethods.get_defaultFailedCallback = function() {
return PageMethods._staticInstance._failed; }
PageMethods.set_path("/MSAjax10/PageMethods.aspx");
PageMethods.Add= function(x,y,onSuccess,onFailed,userContext) {PageMethods._staticInstance.Add(x,y,onSuccess,onFailed,userContext); }
PageMethods.Add2= function(x,y,onSuccess,onFailed,userContext) {PageMethods._staticInstance.Add2(x,y,onSuccess,onFailed,userContext); }


While it is nice to be able to invoke these methods like

PageMethods.Add(1,2, methodComplete, methodError);

The amount of overhead for each page request is not worth it IMO.

Instead I recommend calling the method like this

Sys.Net.WebServiceProxy.invoke('/MSAjax10/PageMethods.aspx', 'Add', false, { x:1, y:2 }, methodComplete, methodError);

Tags:

Re: Researching MS AJAX: PageMethods

Your insight is impressive and very useful. Keep up your great postings.
Thanks ArntK

By ArntK on   2/13/2007

Re: Researching MS AJAX: PageMethods

Hi Jon,

I haven't checked yet, but isn't the bulk of the pagemethod payload created in the cached .js file, and not on the page itself? The dynamic portion of the code you listed reduces to:

PageMethods.Add= function(x,y,onSuccess,onFailed,userContext) {PageMethods._staticInstance.Add(x,y,onSuccess,onFailed,userContext); }
PageMethods.Add2= function(x,y,onSuccess,onFailed,userContext) {PageMethods._staticInstance.Add2(x,y,onSuccess,onFailed,userContext); }

Which is lightweight enough to live with. If the rest isn't in the cached portion, I'm sure at some point it will be. It's too easy of an optimization not to be implemented.

Regarding your initial exploration of the callback abilities in ms-ajax... if you want state on the server, shouldn't you be utilizing the postback functionality of asp.net, which already manages this? If you need a partial page rendering, then put your control in an updatepanel (or let the end-user do this, allowing them to control full or partial rendering).

If this isn't what you want -- an asp.net postback -- then you really have no choice but to use a stateless method. One always has the option of passing all the data necessary (moduleId, etc) to such a method. However, your argument that we should be raising server-side EVENTS is a strong one, and the updatepanel route seems the stronger choice.

Am I missing something in my reading of your analysis?

By BrandonHaynes on   2/13/2007

Re: Researching MS AJAX: PageMethods

Thanks for responding Brandon,
I would have thought the bulk of the js would have been in a cached file, but in my simple test it is not. I even switched it to non-debug and it is still there. I agree that having only the PageMethods.Add portion would be acceptible if that were the case.

Regarding your statements about state. I have spent the last couple months on and off looking at the updatepanel in my design of the DNNTabStrip. If you look at some of my past blogs you will see some of the conclusions I have come up with. The bottom line is any time you try and have a once-size-fits all mentality in your solutions, it almost always means you are sacrificing performance. This is the way I view the UpdatePanel. I want my control to just work, without special notes to the developer that he needs a certain component.

If you look at my blog from tonight you will see that I did investigate the toolkit's rating control, which uses a callback in the manner I am speaking. Inside DNN there are lots of places where a certain amount of state is expected during a callback. Probably the easiest to explain is the Edit In Place functionality. If you look at the code from the Text/HTML module (HtmlModule.ascx.vb) you will see that the UpdateLabel event is simple and straight forward to handle and persist the specific html for the specific module, without the need for the developer to make sure the right information is passed in the callback.

Hopefully this clears things up a bit. Thanks for the comments.

By jhenning@solpart.com on   2/13/2007
 


Customer Connect
Customer Connect provides cutting edge solutions that deliver sales, marketing and customer service results.
www.customer-connect.com
TechNexxus
Business process and technology sourcing solutions delivering superior people, process and value. We have used, and continue to use, DNN successfully in numerous client projects to deliver exceptional value. We are proud to support the DNN team and community.
www.technexxus.com
PartnerPoint - Microsoft Technology Community
PartnerPoint is one of the largest online communities of Microsoft Partners Worldwide. With over 5,000 active members, it serves as a collaboration platform for other technology communties around the globe
www.partnerpoint.com

DotNetNuke Corporation   Terms Of Use  Privacy Statement
DotNetNuke®, DNN®, and the DotNetNuke logo are trademarks of DotNetNuke Corporation
Hosted by MaximumASP