Wednesday, March 28, 2012

PageMethods

Hi Folks

I'm getting an error with AJAX Beta1 trying to access PageMethods...

function beginImport() { disableButton('btnSubmit'); displayProgress(); updateText('Importing Translations, please wait for process to complete before clicking anything!'); PageMethods.Import(onImportComplete); }

Causes this error...

Error: PageMethods is undefined

Are you defining the onImportComplete function in Jscript?

I have the same problem. I keep getting "PageMethods is not defined" error. Here's my code:

<%@. Page Language="C#" AutoEventWireup="true" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><title>Untitled</title><script runat="server"> [System.Web.Services.WebMethod] public string GetMessage() { return "Hello World"; }</script></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <a href="#" onclick="javascript:preview();">Test</a> <script type="text/javascript" language="javascript"> function preview() { PageMethods.GetMessage(onComplete); } function onComplete(res) { alert(res); } </script> </form></body></html>

Shawn Burke talks about PageMethods and Ajax Beta in hisblog

It seems that they need to be static and marked with the ScriptMethod attribute. But if PageMethods are static how do we access page control values within such a method?


I am completely stuck on the pagemethods, and having the same problem. I have read the blog and added the [ScriptMethod] tag to the page method (this tag is not in Microsoft's pagemethod tutorial (here), but I am willing to try anything at this point). I have used the default web.config file that is created when you use the ASP.NET AJAX CTP - Enabled Website template in VS2005, and verified that all of the settings are present as outlined in the migration white paper and the webservice tutorial on ajax.asp.net.

I need to be able to call a pagemethod because i need access to the viewstate and server control properties on the page. A webservice would not give these to me.

All of this worked fine in the July CTP... here is my code:

[C#]

[WebMethod]
[Microsoft.Web.Script.Services.ScriptMethod]
publicstatic GeneralLiability.GeneralLiabilityQuote GetQuote()
{
returnnew GeneralLiability.GeneralLiabilityQuote(10);
}

[JS]

Rate:function()
{
this.showLoadingPanel();
this._MustRefresh.set_visible(false);
// should be page method
PageMethods.GetQuote(this.onGetQuoteComplete, this.onGetQuoteTimeOut);
},

[ScriptManager]

<asp:ScriptManagerID="ScriptManager1"ScriptMode="Debug"runat="server">
<Scripts>
<asp:ScriptReferenceAssembly="Microsoft.Web.Preview"Name="Microsoft.Web.Resources.ScriptLibrary.PreviewScript.js"/>
<asp:ScriptReferenceAssembly="Microsoft.Web.Preview"Name="Microsoft.Web.Resources.ScriptLibrary.PreviewGlitz.js"/>
<asp:ScriptReferenceAssembly="Microsoft.Web.Preview"Name="Microsoft.Web.Resources.ScriptLibrary.PreviewDragDrop.js"/>
</Scripts>
<Services>
// ths webservice is a work around until i get the PageMethod working
<asp:ServiceReferencePath="~/WebServices/RateWebService.asmx"/>
</Services>
</asp:ScriptManager>


Spent alittle more time looking at the PageMethods issue.

I wrote a small test app and realized that the PageMethods object exists when the webmethod is included in the aspx file (as long as I added the
[Microsoft.Web.Script.Services.ScriptMethod]) attribute, but when I move it to the code-behind file, it gives me the undefined error... which leads me to question... are pagemethods no longer allowed in the code-behind file?

Anyone?


See:http://blogs.msdn.com/sburke/archive/2006/10/21/hint-components-that-use-web-services-with-asp-net-ajax-v1-0-beta.aspx. PageMethods are broken in Beta1 and do not work in code behind.

Dimitrod, you say: "But if PageMethods are static how do we access page control values within such a method?".
I may be wrong, but IMO it does not make sense to access controls in PageMethods. PageMethods are part of the business layer. You should read control values using client-side code, pass these values to the method as parameters and read the returned data in the form of a basic type or a complex serialized object. I personally think it is a good thing that PageMethods are now static.


In the Atlas July CTP, Im using the Page.User.Identity.Name as a security verification inside the PageMethods , How would I do this in the new version without passing parameters in javascript, as this would reveal the values.

>> I may be wrong, but IMO it does not make sense to access controls in PageMethods. PageMethods are part of the business layer.

Yes and no. But the point is you can already achieve teh 'business layer' effect by calling a Web Service and now with PageMethods being forced to be static you're doing nothing but duplicating that functionality. All this does give you another place to store your 'service methods'.

Allowing access to the page is very valuable IMHO because it allows you to read values set on the client without having to pass every damn field value as a parameter or as part of an object you first populate on the client.

Consider this: You have a form with 50 input fields on it and the user fills that out. Now you want to use AJAX to save those values. If you use PageMethods or Web Service you have to pass 50 parameters or create a client object that first parses the values out of the fields, possibly converts to the proper types etc. Then you send the data to the server, and you get the parse the values AGAIN on the server - out of the parameters or object into a business object or a DataRow or whatever.

Instead not passing parameters but receiving the values from the client directly on the server in the POST buffer lets you deal with the input values once and store it directly into your object.

I can be a huge timesaver and reduces boatloads of error prone $get() statements on the client.

If all that PageMethods does is duplicate Web/SCript Service behavior but in a page I say cut the whole thing and take the overhead out of the Page class.


Page.User is merely a convenience property that wrapsSystem.Threading.Thread.CurrentPrincipal, which is static, so just access that instead :)


Rick,

Convincing point of view, although a form with 50 input fields seems theoretical to me because it is not very user friendly. I should not have said "it does not makes sense" but I still do not like it.

Despite the fact that you definitely have a point, I prefer the more stateless approach of parsing the fields on the client and feeding a Javascript object that is passed to the web service or page method as you describe. Contrary to what you say, it is not needed to parse the object again on the server, the ASP.NET Ajax layer does that automatically for you, although you may have to write a couple of converters. Note that my business objects are very light data structures which are effectively persisted by business brokers.

By the way, thank you for your valuable web site, which I often consult.


I agree as well - in most cases I use Web Services to abstract the logic, because it's just cleaner. But I would very much like to have the option to be able to get at the data in an easier way in the page.

As to the form with 50 fields: Well there's lots of ways to represent data <s>. Yeah you're probably right but I have a couple of forms that have this much data in various pages of a tabbed interface that's driven through AJAX. In fact in a properly architected AJAX application values are probably updated more frequently than one giant form submit.

But even so even if you have a smallish form like this:

http://www.west-wind.com/atlas/CustomerList/AtlasCustomerList.aspx

You then have code like this to retrieve the data to send to the server:

// *** Cheating: This object contains only strings!
// If other types exist conversion
// must be done here.
Customer.Companyname = GetValue('txtCompany');
Customer.Contactname = GetValue('txtContactName');
Customer.Address = GetValue('txtAddress');
Customer.City = GetValue('txtCity');
Customer.Postalcode = GetValue('txtPostalCode');
Customer.Region = GetValue('txtRegion');
Customer.Country = GetValue('txtCountry');

// *** Pass back the customer object to the server
CustomerService.SaveCustomer(Customer,SaveCustomerCallback,ErrorCallback,ErrorCallback);

It gets worse if the object your setting values on has typed values - then you have to do type conversion in JavaScript which is no fun... Then on the server you do that parsing again out of the object so you're just duplicating the work.

When I meant 'parsing on the server' I didn't mean parse the object. You do get the object back on teh server. But it's a proxy at best and from there you have to move the data out into a real object that actually does the data logic - an Entity that can save or a DataRow or whatever it may be. For most types a type converter isn't even required as the JSON proxy creates the required proxy objects on the client for you. That is very cool, but it's still more work than it has to be - you're still 'reading' the data twice - once on the client, then again on the server. Instead you could do it once and be done with it.


As something of an ASP.NET AJAX Novice I find this thread very interesting.

For me it touches a wider issue which is that for the newbie there is a vast array of possible approaches to building an ASP.NET AJAX app and the best path is not always clear.

My very first app simply used an UpdatePanel and seemed to work fine but then I decided I wanted a bit more control over what was happening.

Consequently my next app used PageMethods to call functions in the ASP.NET Codebehind. Again this seemed to work fine for such things as retrieving Strings etc.

Then I looked at Web Services and devised a couple of those which I then referenced from my ASPX pages (using the ScriptManager)

Now though I'm not really very clear where to go next.

I guess it's like anything else, you just need to give it time and try lots of different things before you can make a judgement call on the best way forward. The danger is that for those of us who have never used much javascript, we may be tempted to try and avoid it (using the UpdatePanels etc) but then come unstuck when we want a bit more control over our app's behaviour.

I hope the documentation will help with this though once the framework goes RTM.


I think ScriptMethods (PageMethods) are part of the UI layer; consider where they are declared - no business logic should be residing in the Page class. I hope they change it so that they'll go back to being state-aware and part of the Page lifecycle again. The way it's implemented in the new beta, there's really not much distinction between a ScriptMethod and a WebMethod (web service) any more.

insted of breaking ypur head and program again and again

it is better to wait to next version or final version

i will stick in july ctp until a better version will come

my program need page.clientscript.registerStartupscript and PageMethod

and both of them not working in ajax beta 1

so why go ther from july ctp?

No comments:

Post a Comment