Earlier in this blog post I said that the URL routing system
in the ASP.NET MVC Framework was responsible for two things:
Mapping incoming URLs to Controllers/Actions to handle
Helping construct outgoing URLs that can be used to later
call back to Controllers/Actions (for example: form posts, <a
href=""> links, and AJAX calls)
The URL routing system has a number of helper methods and
classes that make it easy to dynamically look up and construct URLs at runtime
(you can also lookup URLs by working with the RouteTable's Route's collection
directly).
Html.ActionLink
In Part 1 of this blog series I briefly discussed the
Html.ActionLink() view helper method. It can be used within views and
allows you to dynamically generate <a href="">
hyperlinks. What is cool is that it generates these URLs using the URL
mapping rules defined in the MVC Routing System. For example, the two
Html.ActionLink calls below:
Figure 15
automatically pick up the special Search results route rule
we configured earlier in this post, and the "href" attribute they
generate automatically reflect this:
Figure 16
In particular note above how the second call
to Html.ActionLink automatically mapped the "page" parameter as part
of the URL (and note how the first call omitted the page parameter value -
since it knew a default value would be provided on the server side).
Url.Action
In addition to using Html.ActionLink, ASP.NET
MVC also has a Url.Action() view helper method. This generates raw string
URLs - which you can then use however you want. For example, the code
snippet below:
Figure 17
would use the URL routing system to return the
below raw URL (not wrapped in a <a href=""> element):
Figure 18
Controller.RedirectToAction
ASP.NET MVC also supports a
Controller.RedirectToAction() helper method that you can use within controllers
to perform redirects (where the URLs are computed using the URL routing
system).
For example when the below code is invoked
within a controller:
Figure 19
It internally generates a call to Response.Redirect("/Search/Beverages")
DRY
The beauty of all of the above helper methods is that they
enable us to avoid having to hard-code in URL paths within our Controller and
View Logic. If at a later point we decide to change the search URL route
mapping rule back from "/Search/[query]/[page]" to
"/Search/Results/[query]/[page]" or
/Search/Results?query=[query]&page=[page]" we can easily do so by
editing it in one place (our route registration code). We don't need to
change any code within our views or controllers to pick up the new URL (this
maintaining the "DRY principle").
Constructing Outgoing URLs from the Routing System
(using Lambda Expressions)
The previous URL helper examples took advantage of the new anonymous type support that VB and C# now support with VS 2008. In the examples above we are using anonymous types to effectively
pass a sequence of name/value pairs to use to help map the URLs (you can think
of this as a cleaner way to generate dictionaries).
In addition to passing parameters in a dynamic way using
anonymous types, the ASP.NET MVC framework also supports the ability to create
action routes using a strongly-typed mechanism that provides compile-time
checking and intellisense for the URL helpers. It does this using Generic
types and the new VB and C# support for Lambda Expressions.
For example, the below anonymous type ActionLink call:
Figure 20
Can also be written as:
Figure 21
In addition to being slightly terser to write,
this second option has the benefit of being type-safe, which means that you get
compile-time checking of the expression as well as Visual Studio code
intellisense (you can also use refactoring tools with it):
Figure 22
Notice above how we can use intellisense to pick the Action
method on the SearchController we want to use - and how the parameters are
strongly-typed. The generated URLs are all driven off of the ASP.NET MVC
URL Routing system.
You might be wondering - how the heck does this work?
If you remember eight months ago when I blogged about Lambda Expressions, I talked about how Lambda expressions
could be compiled both as a code delegate, as well as to an expression tree
object which can be used at runtime to analyze the Lambda expression.
With the Html.ActionLink<T> helper method we using this expression tree
option and are analyzing the lambda at runtime to look up the action method it
invokes as well as the parameters types, names and values that are being
specified in the expression. We can use these with the MVC Url Routing
system to return the appropriate URL and associated HTML.
Important: When using this Lambda Expression approach we
never actually execute the Controller action. For example, the below code
does not invoke the "Results" action method on our SearchController:
Figure 23
Instead it just returns this HTML hyperlink:
Figure 24
When this hyperlink is clicked by an end-user it will then
send back a http request to the server that will invoke the SearchController's
Results action method.