RSS

Tag Archives: WebForms

Posting complex types using ASP.NET Ajax, WebForms

This is a minor post, which is some sort of a completion to the previous post dealing with the same topic only for using MVC. So, if you require background, you may want to consider reading that post first.

Fortunately, ASP.NET Ajax makes it really easy to send JSON back and forth. Using jQuery, there is some tweaking that had to be done in order to get this to work. However in WebForms usnig ASP.NET Ajax PageMethods or WebMethods – ASP.NET takes care about the technical details, leaving you to implement only the logic. Note that the same technique and guidelines are used just like in MVC: the data is sent from the Client browser to the Server using POST and in JSON format, with a Content-Type of application/json. All properties must match in data-type and names.

This is the client code:

    <form id="form1" runat="server">
    <asp:ScriptManager runat="server" EnablePageMethods="true" />
    <input type="button" value='click me to test' onclick='Test();' />
    <script type="text/javascript">
        function Test() {
            var data =
            {
                people: [
                    {name: 'Joe', age: 20},
                    {name: 'Jane', age: 30}
                ]
            };

            PageMethods.Test(data, function (result){
                alert("Done");
            });
        }
    </script>
    </form>

And the server side, containing classes matching the client type:

    [WebMethod]
    public static void Test(MyPeople data)
    {

    }

    public class MyPeople
    {
        public IEnumerable<Person> People { get; set; }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

And the traffic:

As you can see for yourself, this is pretty much straight forward. ASP.NET Ajax client infrastructure takes care to POST the data and send it in JSON format and the appropriate application/json content-type, which is great.

Advertisements
 
Leave a comment

Posted by on 27/07/2012 in Software Development

 

Tags: , , , ,

ASP.NET WebForms Routing

This post is more of a “technical completion” post for using Routing in WebForms, which covers some of the issues I have come across. If you require a quick start on Routing, or technical MVC stuff, please read this post first.

I was happy to learn that it’s quite easy to use MS’ built-in Url Routing solution for ASP.NET WebForms. This is quite easy to accomplish in IIS 7, and requires some tweaking in IIS 6. Read this on how to configure your web.config file to support routing according to your IIS configuration. You may want to check that Url Routing is installed.

One pit fall that I’ve encountered was when I needed to deploy a routing solution on a certain server. There seemed to be a slight configuration difference from my development machine, and routing did not work. What I eventually did was to perform a minor tweak in the configuration file, and added a runAllManagedModulesForAllRequests as described here. Note that there are those who consider this configuration tweak “inappropriate” as far as performance, resources and error prone, but their suggested solutions didn’t seem to solve my issue. I decided to perform a simple check, what ASP.NET MVC’s template is configured like – and runAllManagedModulesForAllRequests=true is exactly that. I reckon that if the guys at MS provide this configuration in ASP.NET MVC, it’s good enough for WebForms too.

Enough with the configuration, where are those pitfalls?

As with ASP.NET MVC, the routes are set in the Global.asax file. Here are some routes that will be used in this post:

get.aspx is the sample page in this post. It contains a single PageMethod and will be our test case:

PageMethods
Unlike Web Services (asmx) WebMethods, there is an issue with Url Routing when it comes to PageMethods. It seems like the client is unable to provide the correct url for the page, and the server seems to fail in figuring out which page and method should be invoked. The error received in the client is “405 Method Not Allowed“, and the response contains a somewhat confusing “The HTTP verb POST used to access path ‘…’ is not allowed.” message, which basically means that the Url isn’t resolved correctly and therefore does not reach the correct PageMethod.

Indeed, the Url the client sends by default to our get.aspx page is: “http://localhost:54885/WebSite2/get/1/Get&#8221;.

  • The first “get” is the route which routes to get.aspx;
  • The “1” is a simple {id}.
  • The second “Get” is the PageMethod.

Because we received the 405 error message, I used the Route Debugger, and as expected, the Route Debugger showed a “No Match” on that url. Initially I thought that it would be easy to write a RouteHandler and provide a generic solution for PageMethod urls, but after I started coding I noticed that it’s not as easy as it may seem. Possible, but not as easy as the workaround. In order to workaround, all you have to do is to set the path in the client JavaScript to the correct page and you’re done. This is done like so:

Note: You can read here how to call your PageMethods using jQuery.

HttpHandlers – ashx files

It seems like ASP.NET 4 has no support for routing to ashx handler files. When you attempt to route to an ashx you’ll get the following exception:

Type ‘MyHandler’ does not inherit from ‘System.Web.UI.Page’.

Fortunately, this is quite easy to get by, because coding a Route handler which will take care of ashx files is trivial enough. Note, that the solution suggested here is based on a Web site and not a Web application, so the route handler code resides in App_Code.

So, there are three steps to this:

  1. Refactor your ashx code to an App_Code class which inherits from IHttpHandler.
  2. Write a simple Route handler which will create that handler when requested to.
  3. Add the new route handler to the routes defined in Global.asax.

Step 1: Refactor the handler – basically, this is your starting point for your actual “business” implementation (although I encourage calling a Business Layer from here):

Step 2: Create a simple Route handler to return the IHttpHandler:

Step 3: Register the new route in Global.asax:

That’s all there is to it. Now you can use a route for targeting your handler, for example:

http://<server>/handler/123

UPDATE: For routing Web Services (asmx), click here.

Route Data

One last issue is in cases that you perform url rewriting or other processing, and you suddenly notice that your Route Data is gone. This is quite frustrating as you can plainly see that url in the browser’s address bar. Fortunately, the solution is quite simple and also uses a Route Handler. All we have to do, is copy the Route Data in a custom Route handler to HttpContext.Current.Items collection, and we have them for the entire http request. Two steps here:

Step 1: Write a simple custom Route handler which copies the route data:

Step 2: Configure Global.asax accordingly:

To sum up – it’s quite cool to be able to use Routing in WebForms. I just finished a small project where I used Routing and the result is quite awesome. It wasn’t just looking better, but it also allowed me to “white label” the website dynamically. For example, I could do the following: http://server/productA/login and http://server/productB/login, and it really felt like two different websites.

 
4 Comments

Posted by on 22/06/2011 in Software Development

 

Tags: , ,

A quick guide to have jQuery call your ASP.NET PageMethods

I based most of my solution and understandings on several posts from Dave Ward. Although Dave’s excellent posts cover everything written here and more, it still took me quite a while to get this going. That is why I decided to sum up my current experience in this single post, which may be considered as a quick guide to having jQuery call WebMethods (PageMethods in particular).

Assuming that we have the following PageMethod, how do we use jQuery to call it?

There are several stages I had to go in order to use jQuery alongside PageMethods:

  1. Use the correct url for the PageMethod.
  2. Ensure that the client and server use json content types.
  3. Pass arguments to the PageMethod as JSON strings (see the ‘JSON, objects, and strings: oh my!‘).
  4. Interpret the result using the ‘d’ key (see the ‘Waiter, there‚Äôs a .d in my msg soup!‘).

Here’s the client code I ended up with (explanation below):

Correct url? No surprises here. In order to invoke the correct PageMethod you have to supply a valid url for that method. It’s easy to use ResolveUrl to get this right.

json: As you can see, I used jQuery’s ajaxSetup method in order to assure that all ajax calls are sent using json. Naturally, you don’t have to do this if you do not want JSON, or if not your calls are json-based. But, no doubt that placing the ajaxSetup call in a js file that gets loaded from a master page is very comfortable to ensure that all your jQuery ajax calls are using the same basis.

JSON arguments: This is the part where it get tricky. As Dave Ward explains so well in his post, ASP.NET expects arguments in JSON format, whereas jQuery sends JavaScript objects (which are mistaken for JSON objects) in query string format (that is, if you try to send JavaScript objects). This means that you have to provide jQuery not with a JavaScript object, but rather with a proper JSON string. This will ensure that jQuery wont parametrize your data in key=value format and will provide ASP.NET the desired JSON format. This is important because it means that if you decide to pass your data object as an invalid JSON string, you’ll be frustrated why the thing isn’t working. That’s why when I learned of the JSON native support that now exists in the popular browsers (IE8, FF 3.5 etc.), it became an obvious solution: using JSON.stringify() ensures that the data gets sent in proper JSON format.

Whats with the ‘d’? As explained in Dave’s post, ASP.NET 3.5 and onwards returns a JSON response from the server with a key of ‘d’, for security purposes (preventing XSS attacks). While ASP.NET Ajax framework automatically handles the new ‘d’ formatted result, so that you’ll end up with the intended data without ever knowing that a ‘d’ was there in the first place, you have to handle this manually when using jQuery and WebMethods. jQuery’s combination of ajaxSetup and dataFilter event allows us to handle response from the server prior to actually calling your “onsuccess” callbacks. The proposed solution in the code above assumes that our site is working only with ASP.NET 3.5 WebMethods, and therefore a ‘d’ is always returned. I believe that usually that will be the case, although a more complex solution for checking if a ‘d’ is there already exists. Anyway, the proposed solution simply takes a JSON string returned from from the server, parses it and extracts the actual data from the ‘d’ key. It then transforms the actual data back to a string (which is what jQuery will expect to get when the dataFilter event has ended…).

Following the described steps should get you to use jQuery with ASP.NET’s WebMethods and PageMethods.

After this has consumed precious time to get going, the big question that remains is: was it worth it. You could argue that using jQuery is faster, or that it seems like MS’s client framework is destined to “retire” in favor of jQuery. But honestly, having to go through all this trouble for calling a PageMethod just seems way too much. In short, personally, I’d rather have the good old script proxies which are extremely easy to use over the not-so-trivial jQuery alternative.

Just a reminder though: in MVC using jQuery is quite trivial.

 
2 Comments

Posted by on 20/05/2011 in Software Development

 

Tags: , , , ,