Response.Redirect and ASP.NET MVC – Do Not Mix

Update 28 November 2012: HttpResponse.Clear is safe but not recommended since it is a violation of the MVC pattern.  If you’re calling Clear(), then by definition you started doing one thing (like setting headers, writing to the response, etc.) but now suddenly need to back out and do something else.  In the MVC pattern, you return an ActionResult only when you’re sure that you want to go down some specific path of execution.

If you search on Response.Redirect, you’ll find the recommendation to avoid the call for performance reasons caused by the ThreadAbortException thrown.  But if you use  Response.Redirect(url, true) in an MVC application, no exception is thrown. Response.End and Response.Redirect do not cause a thread abort in MVC applications.  This is one of the reasons that we strongly discourage calling these methods from within MVC and instead encourage developers to return a RedirectResult or RedirectToRouteResult   from actions or filters. But what’s wrong with using Response.Redirect in an ASP.NET MVC application? Sometimes, it works.

The ASP.NET MVC framework is designed with a “tell me what to do next” pattern in mind.  This is why action methods return ActionResult instances – they represent some deferred behavior that the framework will perform at the appropriate time.  It’s almost like continuation-passing style for developers familiar with the CPS pattern.  But there was actually a reason for this design.

Consider what happens when you return a RedirectResult from an action.  Simply creating a RedirectResult (by newing one up or by calling one of the Controller.RedirectXX factory methods) doesn’t have any side effect.  When the object is returned from the action method, other parts of the pipeline get to inspect it.  Filters can modify it, replace it, log/audit it, or do whatever they want.  Perhaps there’s an MVC filter that will look at any RedirectResult winding its way up the stack, and if it sees one it will append ?some-query-parameter to the end of the URL.

At some point, the MVC framework will say “OK, everybody has said their piece, so it’s time to act,” and the ActionResult.Execute() method gets called.  The ActionResult.Execute() method has a side effect – it causes a redirection, writes to the response, and so on.  If this side effect were performed upfront, for example by calling Response.Redirect and triggering a thread abort from within the action method itself, by causing the view to be rendered within the action method, or any other thing that causes a side effect to occur – we wouldn’t have been able to create the rich pipeline that MVC currently has.

Thanks to Levi  for providing the above information.