RSS

Monthly Archives: June 2011

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”.

  • 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: , ,

ASP.NET MVC – RadioButtonList and a Code Nugget issue with Generics

I’ve been reading about a RadioButtonList that used to exist in MVC Futures but was removed from the release. There are different solutions in the forums for this, suggesting various implementations. I decided to combine some of the ideas into an extension method, which creates a radio button list with LABEL FORs. It also checks the selected OPTION, and provides a wrapping div with css class that can be easily used. This looks like this:

  • Lines 24-27 & 38-41 contain a wrapping div, in case a css class for a container was specified.
  • Lines 30-35 is where the important stuff resides: iterate over the items of the dictionary (line 18), and create radio buttons with corresponding LABEL FORs.

Although this was sufficient, I decided to take this one step further and create another extension method especially for enum types. This method creates the dictionary out of an enum, and the label’s text out of a local resource file (using LocalResX which was demonstrated some time ago here). This is how it looks:


Now all I had to do was call the new extension method from the View, or so I thought. This was my code (note that Visual Studio failed to color the generic part and the rest of the arguments):

Much to my surprise, I received the following compilation error:

CS1502: The best overloaded method match for ‘System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)’ has some invalid arguments“.

Say what??

After some experimenting, I replaced the generic <T> with an argument of Type in the extension method, removed the <DayOfWeek> from my View and replaced it with a “typeof(DayOfWeek)” – it solved the problem. But hey, what if I did prefer to use generics? Why did the View fail to compile when I placed the generic on my extension method?

What I had done was to compare the resulting compilation of a successful non-generic implementation (using Reflector), and the failed compilation source code (from the Compilation Error page, simply click on the “Show Complete Compilation Source” to view the source code), and I noticed what had happened here:

What happened was that the View failed to recognize the generic call to the extension method, and assumed that RadioButtonList was a property, or a “HelperResult”, as the compiler error states. Check it out in the screenshot above – Html.RadioButtonList should have been called like a method with parentheses! After that I understood that the fact that Visual Studio did not cope and color the generic call in the View wasn’t a designer coloring bug as I initially thought, but rather what seems to be like a Razor bug.

I still wanted to solve this and use generics instead of passing a “typeof” argument. So what I had to do was recall the Razor Code nuggets vs. Code blocks post from a while back on how to replace the call to Write( ), performed by using a Code nugget (@), with a Code block. I made the changes:

Now I received another compilation error, but it was a whole lot better and simply stated that the result of the RadioButtonList<T> extension method is an MvcHtmlString, whereas Html.Raw expects a string. Well, I’m not sure if MS should have provided an implicit conversion method from string to MvcHtmlString and vice versa, and I wasn’t sure I wanted to do it myself, so I had to choose between calling MvcHtmlString’s ToHtmlString( ) method from the View, or from the extension method and return a string instead. I chose the latter, because I wanted to View’s code to remain cleaner, especially if this method will be reused. So, one more time:

Now the View compiled successfully. Checking the assembly with Reflector showed what I expected:

As you can see, now the code calls the RadioButtonList<T> extension method as expected. The resulting string is sent to Html.Raw and from there to the Write(…) method (which was auto-generated by Razor as a result of using ‘@’).

Although this was worked around, I still expect that Razor will support calling generic methods using a Code nugget and not only via a Code block. It’s certainly possible that I’m missing something here, and sure, the workaround isn’t too bad, but it’s just one of those things which make you feel like it’s a “breach” that wasn’t taken care of, and it also was time consuming. I also wonder why MS dropped the RadioButtonList method that was said to exist back in the previews. I guess that it’s written somewhere on the web…

 
2 Comments

Posted by on 12/06/2011 in Software Development

 

Tags: , , , , , ,

Ode to SharpZipLib

Not much technical stuff expected in this post, nor any sample code or screenshots. I simply wanted to share an experience with different compression solutions under high loads. Disclaimer may be required though: Nothing in this post is intended to slander any compression solution whatsoever. 

Different compression solutions for developers exist for years now, within the .NET framework and outside it. I had several different projects which required compression solutions in various scenarios. I always preferred and looked for free solutions over a paid-for solution, and I always preferred a managed solution which was easy to work with, over other alternatives, such as older COM solutions or simply Dll external function calls. Amongst the different compression solutions I used are .NET’s GZipStream and Deflate, SharpZipLib and 7zip. Possibly others that I don’t recall.

I guess that when a .NET developer is looking for a compression solution, there are several features which are essential, these are:

1. Reliability – uncompressed data must be identical to the original input; trivial request, but one cannot do without.
2. Stability – must not fail under high stress loads.
3. Decent compression rate/percentage.

Arguable, but I find the following necessary but not mandatory:
4. Performance – Good compression speed.
5. A free solution or at least cheap.
6. Managed code and general ease of use.

Lately I was looking again for updated compression solutions. I googled and found posts like Peter Bromberg’s compression comparison. which compared different compression solutions, and performed some tests of my own. The drive to make this search arose from an application using 7zip compression, which under stress tests began to fail with Out of Memory exceptions. Searching through the web I found that I wasn’t the only one, and this seems like a known issue. Although 7-Zip is my favorite client application for zipping, and although it was great in previous solutions, in this particular development many compressions are made simulatenously and under a heavy load, so I had to find an alternate solution which would be 100% stable. Attempts to use different 7zip “helpers” and reuse the LZMA demo code supplied with the SDK to solve this failed altogether, which led to this search in the first place.

.NET Framework’s GZipStream and Deflate were tested and found to be both reliable and stable, but provided  relatively poor compression (if at all). Other solutions were either not free, or they were tested but found unreliable, or they weren’t tested for various reasons. However, the good ol’ SharpZipLib proved the best of all worlds. Although it’s compression rate isn’t as good as 7zip’s, it was way better than GZipStream/Deflate and other alternatives, and it proved reliable as far as data integrity or memory consumption.

I know, I know. SharpZipLib has an “old fashioned” API which is a little cumbersome; it’s not the best compression in the world, and it’s speed isn’t the fastest out there. BUT, it’s licensed so that it can be used freely in closed source applications; it provides a compression rate and speed which are reasonable; it has managed code which is “not-so-bad”; but most importantly – it was stable. Under high loads it didn’t crash, not even once. The memory consumption seemed reasonable. The CPU didn’t go crazy comparing to stress test without compression at all.

So, that’s my latest experience with compression solutions for the .NET. I reckon that there are alternatives which may be better – feel free to share your thoughts and experience.

 
Leave a comment

Posted by on 01/06/2011 in Software Development

 

Tags: ,