So I spent an hour today arsing about with a couple of ASP.NET MVC 3 bugs. One was a Routing issue that caused it to act differently to MVC 2. The second I found was a FormsAuthentication issue that insisting on sending me to /Account/Login.
Amazing how this crept in really given that it was community tested to death with such a massive ASP.NET MVC following so it is a wonder they weren't weeded out and fixed before RTM.
Oh well, don't pretend you don't like a challenge.
Routing doesn't work the same in MVC3 from MVC2
Here is an example of this bug in action
My current route is:
routes.MapRoute("groups", "groups/{groupSlug}/{action}/{id}/{urlTitle}",
new
{
controller = "groups",
groupSlug = UrlParameter.Optional,
action = "index",
id = UrlParameter.Optional,
urlTitle = UrlParameter.Optional
});
I am using this route in an ActionLink like this (well obviously I've changed it for clarity - but I was totally using T4MVC!):
<%: Html.ActionLink(item.Group.Title, "index", new { groupSlug = "something" })%>
In MVC2 it that produces the URL
/groups/something
. But in MVC3 it produces the URL
/groups?groupSlug=something
.
MVC3 Routing UrlParameter.Optional workaround
I struggled with this for a good few hours, many a time exclaiming that, "my route
IS there! What the hell is wrong with you?!" I took it apart piece by piece to discover that MVC3 no longer likes multiple
UrlParameter.Optional
's in a row.
A rather ugly workaround for this is to put in a new route for each of these problem routes that have no reference to the following
UrlParameter.Optional
's. So
AFTER the above route you I need to put in another route like this:
//workaround for MVC3 bug
routes.MapRoute("groupsFix", "groups/{groupSlug}/{action}",
new
{
controller = "groups",
groupSlug = UrlParameter.Optional,
action = "index"
});
Since writing this I have discovered it is a known issue and Phil Haack has a much better explanation than me! Obviously.
FormsAuthentication.LoginUrl is always /Account/Login
I have setup my forms authentication in web.config to register the LoginUrl as "~/login" but since upgrading to MVC3 it has decided to ignore that and now FormsAuthentication.LoginUrl returns "~/Account/LogIn" regardless of what I set in web.config.
There is a workaround for this though. You simply need to add this line to your AppSettings:
and everything works how it used to. Strangeness indeed.
Conclusion
Live with it. Fix up your errors as explained above and continue staying up to speed with ASP.NET MVC. It's worth it if even just for Razor alone.