ASP.NET MVC ActionFilters and Response.Redirect

Posted by Jason on December 19, 2008 at 5:28 pm

There is an issue with using the following code in an action filter:

  1. filterContext.HttpContext.Response.Redirect(loginUrl, true);

which is a bit of code quite common in an authentication filter. The problem is it will throw a ThreadAbortException as soon as you put your code on a live site resulting in the error page for anyone who is not logged in. This is probably not what you want since you are attempting to redirect them to the login page.

Now it is a little unfair to say that it’s an issue because that is the intended functionality. But it doesn’t fit well with MVC controllers, especially since Microsoft’s official suggestion is to set the endResponse flag to false. That is just downright misleading since your controller action (which the filter just decided you can’t access) is still executed after the filter fails authentication – resulting in the action code being executed anyway whilst you see the login screen on the browser and assume it all went swimmingly! Meanwhile those files that this user shouldn’t have access to got deleted.

Yeah, that’s what I just did during testing whilst proving to myself that you can’t fake the URL as a non-registered user. Imagine my surprise. It’s true that the chances of a malicious user actually working out the URL might be low, but that’s no reason to leave the door open.

Oh, and your unit tests probably won’t catch this because the filters don’t get executed by the unit tests. But I digress…

To cut a long story short, this bit of code in your base controller (assuming you have one, otherwise stick in in all of the controllers) will prevent the issue:

  1. protected override void OnException(ExceptionContext filterContext)
  2. {
  3.     if (filterContext.Exception is ThreadAbortException)
  4.     {
  5.         filterContext.ExceptionHandled = true;
  6.     }
  7. }

Using Html.DropDownList in ASP.NET MVC

Posted by Jason on December 9, 2008 at 3:07 pm

This is something I think is particularly poorly documented for the MVC framework. It took me a long time Googling and, in the end, guessing in order to get it to work correctly (and it’s still not how I’d like it, but there you go). Simply put, this is the code in the Controller:

  1. var portfolioSelect = new Dictionary<string, object>();
  2. foreach (var portfolio in portfolioList)
  3. {
  4.     portfolioSelect.Add(portfolio.ID, portfolio.Name);
  5. }
  6. ViewData["PortfolioSelectDropDownList"] = new SelectList(portfolioSelect, "key", "value", id);

And this is the code in the View:

  1. <%=Html.DropDownList("PortfolioSelectDropDownList")%>

I know it’s still only in Beta, but I think it’s time some of the Microsoft boys tidied up their otherwise useful blogs to remove and update many incorrect usage instructions for the latest cut of the framework. After all, it’s the only documentation we have at the moment.

One more issue I’ve found is the name that is assigned to the resulting <select> tag. It’s a bit irritating as I may not want the name to be the same is the key that is used in the ViewData (which is what it uses here, i.e. “PortfolioSelectDropDownList” in my case). That messes up my typed view. The only way I’ve found around this is to use the name of the variable in my typed view for the ViewData key, e.g. “Project.PortfolioID”. The result is that I get a select list and when the form is posted back my Project object is populated with the selected value.

To be honest it has a certain elegance to it so it may even be the intended usage! Still seems a bit strange to me though…

Creating Strongly-Typed Views in ASP.NET MVC Beta

Posted by Jason on December 5, 2008 at 12:42 pm

One of the big problems with the early adoption of any framework is the documentation. No books are released yet, if they are ever going to be, and so turning to Google is your best bet. In fact it’s your only option and my own preference is using Google over books anyway.

But frameworks change during development and you come across the issue that all of the top hits for your query are based on previous versions. When that previous version did it differently you’re stuck! I had this problem today when trying to create strongly-typed views. I love strongly-typed anythings, but I’m just a sucker for having a project that is more likely to work when another developer makes an edit and doesn’t bother fully checking the effects of their changes. It’s another safety net, and I’m a sucker for safety nets as well.

So, this is how I did it in bite-sized chunks. First the controller function:

  1. public ActionResult Index()
  2. {
  3.     var ContentObject = new ContentClass()
  4.     return View(ContentModel.Load(ContentObject));
  5. }

Next I created a new view by right-clicking the above method (bear in mind that I’m using Visual Studio 2008) and checking the ‘Create a strongly-typed view’ before entering the full name of the object type (ContentClass). That produces an aspx.cs which looks something like this:

  1. public partial class Index : ViewPage<ContentClass>

So far so good, but where I really came unstuck was actually using this in the view. Turns out it’s simpler than ever. All you need to use is the ViewData.Model parameter, which is automatically typed to whatever you set the view up as previously:

  1. <%
  2. foreach (var portfolio in ViewData.Model.Portfolios)
  3. {
  4. %>
  5.     <p><%= portfolio.ID %></p>
  6. <%
  7. }
  8. %>

All that I have to do now is pass that through to a UserControl. I’m assuming I can strongly-type those as well. We shall see.

Deploying ASP.NET MVC Applications

Posted by Jason on November 28, 2008 at 10:56 pm

Now I’m a huge fan of the ASP.NET MVC framework. So much so that I have taken to porting across applications already started using the Castle Monorail framework. Why? Well, there’s just a nice, warm, supported feeling when using a framework that is built-in to your chosen development platform.

Or at least that’s what you’d think. You know how it is – you get it all working on your lovely development machine and then once the decision has been made on where to host the final result, you upload your application and…bang…

HttpException (0x80004005): The incoming request does not match any route.

Oh yes, that works so well.

Suddenly that belief that, finally, someone has produced a framework which is so nicely integrated with your target platform comes crashing down around your head as you weep softly into your keyboard. No, ASP.NET MVC is not actually supported on anything under IIS7. Does your host offer IIS7 at the moment? I guess not.

Now don’t get me wrong, it does work on IIS6 but you have to mangle it a bit and unless you pay a fortune each month for access to your own virtual server then you’re likely to lose those pretty urls. That’s not the same as being supported. For those that have spent the last two hours Googling and still getting the same problem, here is the man with the answer:

http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx