June 2008 - Posts

The MVC routing assembly – part II
Fri, Jun 6 2008 14:59

In my previous post, we’ve seen that all routes must implement the contract defined by the RouteBase class. As you might expect, the framework defines one implementation of that contract through the Route class. Currently, the Route class exposes the following properties:

public class Route : RouteBase
{
    public RouteValueDictionary Constraints { get; set; }
    public RouteValueDictionary DataTokens { get; set; }
    public RouteValueDictionary Defaults { get; set; }
    public IRouteHandler RouteHandler { get; set; }
    public string Url { get; set; }
}

Lets start with the Url property since it’s probably the most important property defined by the class. This property is used for setting up the url associated with a route. Here’s an example:

var route = new Route( “foo/bar”, new MvcRouteHandler() );

In this case, whenever you write http://yoursite/foo/bar and you’re using the url routing framework, that request will be associated with the previous route.

Even though you can use fixed urls, you’ll normally end up using patterns instead. A pattern lets you define a placeholder whose value depends on the requested url. Here’s another example that shows a simple pattern:

var route = new Route( “foo/{anything}”, new MvcRouteHandler() );

Generally, the placeholders defined in a url are called parameters. In this case, the following urls will be automatically mapped to the previous route by the UrlModule:

http://yoursite/foo/bar

http://yoursite/foo/anotherBar

In a future post we’ll discuss the route resolution mechanism in more detail. For now, just keep in mind that the previous urls match the pattern defined by the previous example route.

You’re not limited to a single parameter, ie, you can have several placeholders in a url. For instance, you can apply the following approach if you want to have localization (MSDN uses a similar strategy):

var route = new Route( “foo/{lang}-{locale}/{anything}”, new MvcRouteHandler() );

There’s even a catch all parameter. A catch all parameter starts with the * and you’re free to use any valid name (for instance, spaces aren’t allowed). Here’s an example of the its use:

var route = new Route( “foo/{*anything}”, new MvcRouteHandler() );

Again, I’m using the anything name because I’ve just copied the previous snippet. There’s really nothing forcing you to give a specific name to a parameter. The catch all parameter is a good option when, for example, you need to use the separator character for a parameter value.

The Route object keeps an internal dictionary that associates each parameter to a value that is passed in the url associated with the current request (we’ll see how this works in a future post).

If you’re using the MVC framework, your routes need to have 2 known parameters called controller and action. How do you define these parameters? Simple: just define an url pattern with parameters with those names. Here’s an example:

var route = new Route( “{controller}/{action}”, new MvcRouteHandler() );

Ok, now if you  use the following url:

http://yoursite/products/showproducts

You’ll end up setting the controller parameter to products and the action to show products. Ok, this works well in some scenarios…but what about those scenarios where you have a fixed url and you want to associate it to a controller? And when you want to have a default action and/or a default controller? Simple: in these cases you can set up the Defaults property of the route. Nothing better than a quick example:

var route = new Route( “myApp/{action}”,
                                      new RouteValueDictionary( new { controller = “Products”, action = “showproducts” } ),
                                      new MvcRouterHandler() );

This is how you set up the Defaults property. The easiest way to initialize it is to add an anonymous object which has properties with the same name as the parameters defined on the url. Since RouteValueDictionary is a string/object dictionary, you can also use the traditional Dictionary<T,K> API to add defaults to this dictionary.

Keep in mind that the values defined on the dictionary will only be used when the parameter value isn’t set up on the current url. In the previous example, controller will always be set to “Products” because the url pattern used doesn’t contain a parameter with the name controller.

When you have a route with parameters on the url, you might need to get the current value of one of those parameters. To do that, you’ll use the GetRequiredString method of the RouteData class. So, in the previous example, if you get a reference to the RouteData, you’ll be able to get the value of the controller parameter by running the following code:

var routeDataRef = get_reference_to_current_route_data;
var controller = routeDataRef.GetRequiredString( “controller” );

The DataTokens property is an “extra”. You can use it to add items to a dictionary (RouteValueDictionary, if you want to be specific about it) and those items will always be available whenever you get a reference to that route. Btw, you can also get a reference to this dictionary through the RouteData.DataTokens property (keep in mind that this is an instance property, not a static property).

This is becoming a really big post, so we’ll leave the Constraints property to another post.

by luisabreu | with no comments
Filed under: ,
The MVC routing assembly – part I
Fri, Jun 6 2008 11:49

 

In these last 2 days I’ve been looking at the internals of the System.Web.Routing assembly. I’ve thought about writing some posts with several notes on how it works so that I have a future reference when I need it. Putting it here on my blog will make it easy to find these notes and it may even help the guys that are starting out (but that are a little behind me right now).

In this post, I’ll just present the basics (and there really isn’t much to say, believe me). The routing assembly is based on three or four basic types + a module which is responsible for intercepting the requests and performing the mapping magic. But lets start with those three or four basic types…

The RouteBase type is (arguably) one of the most important types you’ll find on this assembly. It’s main objective is to define the contract that all routes must implement (normally, you’ll end up using the derived Route class in your programs). Currently, the class defines the following contract:

public abstract class RouteBase
{
    protected RouteBase();
    public abstract RouteData GetRouteData(HttpContextBase httpContext);
    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
}

As you can see, each concrete route type must implement two methods: GetRouteData and GetVirtualPath. The first (GetRouteData) is used (indirectly) by the UrlModule (which will be presented in a future post) to get info associated with the current request. The RouteData object returned by this method has all the necessary info about the current route.  At this time, it’s important to note that if none of the pre-registered routes (you’ll see more on this when we talk about the RouteTable class) return a valid value from this method, then the routing framework won’t do anything and the request will end up beeing handled like if the routing platform didn’t exist.

Now, when there’s a route which matches the current url request and you have a valid RouteData object, that instance will be used for getting an IRouteHandler associated with the current route. The IRouteHandler has the following signature:

public interface IRouteHandler
{
    IHttpHandler GetHttpHandler(RequestContext requestContext);
}

As you can see, the main objective of an IRouteHandler is to return and IHttpHandler that will process the request. Notice that the GetHttpHandler will receive an instance to the current RequestContext, which should be propagated to the handler that will end up processing the request. This class (RequestContext) has two properties which will give you the current RouteData and the ASP.NET wrapped context (property HttpContext – for more info on these wrappers, check my previous post on the subject).

It’s now time to look at the GetVirtualPath method exposed by the RouteBase class. The main objective of this method is to return an instance of the VirtualPathData associated with this request. You won’t normally be using this method if you’re going to use the MVC approach. On the other hand, it might be really important if you want to use the routing module with the Web Forms approach (just download the MVC preview code and take a look at the Futures folder).

Ok, so in this post we’ve already introduced several topics:

  • the RouteCase class sets up the basic contract that all route types must implement;
  • we’ve seen that there are some utility classes that will help propagating the route information along the ASP.NET pipeline (RouteData and RequestContext are two classes that do just that);
  • when using routing, the request will be intercepted by a HTTP module (UrlModule) which will do its magic and reuse the contract defined by the RouteBase class to forward the request to an IRouteHandler;
  • The IRouteHandler is there so that you can easilly forward the current RequestContext to an HTTP handler (IHttpHandler) that should be used to handle the request.

In the next post, we’ll look at the use of routes and route tables.

Velocity and MEF CTPs announced
Thu, Jun 5 2008 21:19

Well, I'm not sure on how anyone is able to keep up with this pace! So, two new frameworks are out: Velocity and MEF. And I'm still late on the ASP.NET MVC study and haven't looked at Silverlight since the 1.1 version...damn...

by luisabreu | 1 comment(s)
Filed under:
The CurrentNotification property
Tue, Jun 3 2008 11:54

I’m not sure if most of you are already using IIS 7 and the latest release of the ASP.NET platform. Even though I’m still limited to IIS 6 on production sites, I’m lucky to have Vista running at home and this means that I can run some tests on the new features of the plarform.

One of the new properties exposed by the HttpRequest object is the CurrentNotification property. You’ll only be able to use it when your web app is hosted on IIS 7 and it requires that your code is compiled against .NET 3.0. This property returns a value from the RequestNotification enumeration, which lets you know the current event being processed by the HttpApplication.

With this event  info you can, for instance, handle exceptions by using strategy A when they happen from within the execution of the page and by using strategy B when they’re generated during the authentication of the request. With the previous release, there really wasn’t an easy way to get this info.

by luisabreu | with no comments
Filed under:
The System.Web.Abstractions
Tue, Jun 3 2008 11:04

Yesterday I’ve started looking at the new MVC platform. After looking at the MVC project, I’ve decided to take a look at the System.Web.Abstractions. In this dll you’ll find several wrappers of the objects you normally use on  a Web Forms ASP.NET application. The next figure shows some of them:

MVCWrapper

If you end up using the new routing assembly, you’ll end up using these classes. Notice like this assembly adds 2 classes for “each wrapped” class…for instance, the HttpSessionStateBase class defines an API and just implements all members by throwing a NotImplementedException. These are the general classes that are used by the rest of the MVC platform.

Then there are the XXXWrapper classes that extend the XXXBase classes and are responsible for encapsulating the ASP.NET traditional classes (as you might expect, the implementation of the XXXWrapper methods consists on delegating all the work to an internal field that points to the associated ASP.NET class).

I’m assuming that one of the main reasons that le to the introduction of these abstractions is testing. Since the rest of the API uses the XXXBase classes, you can simply create your own stubs or mocks of these classes and use them in your tests. I’m not sure if using interfaces wouldn’t have been better, but at least now you can easilly mock these ASP.NET intrinsic objects.

It looks like there are still some rough edges though…for instance, there’s an HttpContextWrapper2 class which doesn’t seem to do anything usefull. Another thing that is interesting is that the Cache object isn’t wrapped! So, you have all the other main classes wrapped (event the HttpPostedFile class is wrapped), but the Cache property still delegates to the System.Web.Cache object. I’m supposing that this means that you won’t be able to mock the Cache object…maybe someone forgot to wrap this class?

So, now that I’ve already looked at the System.Web.Abstractions assembly, it’s time to move on and start looking at the routing assembly.

by luisabreu | 4 comment(s)
Filed under:
Parallel Extensions June CTP is out
Mon, Jun 2 2008 23:08

The Parallel Extensions CTP is out. It seems like now the PLINQ does no longer depends on the Thread pool. Instead of doing that, PLINQ now relies on the Task Parallel Library. Interesting...it's time to run some more tests...

More Posts « Previous page

Search

This Blog

Tags

Community

Archives

Syndication

Email Notifications

News




  • View Luis Abreu's profile on LinkedIn


    Follow me at Twitter

    My books

    Silverlight 4.0: Curso Completo

    ASP.NET 4.0: Curso Completo

    Portuguese LINQ book cover

    Portuguese ASP.NET 3.5 book cover

    Portuguese ASP.NET AJAX book cover

    Portuguese ASP.NET AJAX book cover