find a location for property in a new city

Tuesday, 14 June 2011

Two bugs in ASP.NET MVC 3 and a workaround for both

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.

Follow britishdev on Twitter

4 comments:

  1. What is the solution for FormsAuthentication.LoginUrl is always /Account/Login ??? I can´t see anything after AppSettings:

    ReplyDelete
  2. That's strange. What browser are you using? The line you can't see is using JavaScript to syntax Higlight it so maybe that is causing problems.

    Anyway the line is: <add key="loginUrl" value="~/login"></add>

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Cool, I'd these problem other day and I've solved with this post. Thanks.

    ReplyDelete