1

In the old days:

We used Response.Redirect, which sets the 302 response header and raises a ThreadAbortException to prevent anything else from happening after the redirect.

Now, with MVC:

We return a RedirectResult, which avoids the performance issues with ThreadAbortException and also allows the rest of the pipeline to inspect the results before actually sending them back to the browser. It's a different way of thinking about a redirect-- now instead of halting execution, a redirect is more like returning from a function.

My question has to do with mixing and matching these patterns.

Here's the requirement. We have an MVC site, and site contains an HttpModule that is in charge of authentication. If anything goes wrong with authentication, it drops cookies and redirects to an external web page. So the HttpModule makes a decision whether to send the redirect header or pass control to the MVC site. If it sends the redirect header, it has to halt execution-- if authentication failed, we don't want the site to be accessible in any way, shape, or form.

What's the "right" way to do this? Should the HttpModule simply use Response.Redirect just like we have always done? Or is there some clever way to accomplish this that is more consistent with the MVC pattern? Is there any way for the HttpModule to tell the pipeline to stop processing?

Or should I be using some completely different pattern, something that doesn't use an HttpModule? Perhaps an MVC filter? The thing is, the modularity/separation of concerns between the module and the site itself is very important. Anyone have any recommendations?

Jasmine Howell
  • 831
  • 5
  • 4

2 Answers2

2

Thought I'd throw the answer up here in case anyone else has a question in a similar problem domain.

The answer is actually very simple.

HttpContext.ApplicationInstance.CompleteRequest()

The above call no longer throws a ThreadAbortException (this changed with .NET 2.0) so you can safely use it to tell the pipeline to halt execution. When the HttpModule exits, the web site proper is bypassed and control goes directly to EndRequest-- exactly what I needed. This was not possible in .NET 1.1 but I don't think there are a lot of 1.1 MVC projects out there ;)

Jasmine Howell
  • 831
  • 5
  • 4
1

Since you mentioned this was for authentication, you should use the Authorize Attribute. You can use it either at the Class level or the Action level.

[Authorize]
public class HomeController : Controller
{
    // All actions will require authorization
}

public class ImageController : Controller
{
    public ActionResult PublicImage()
    {
    }

    [Authorize]
    public ActionResult ImageRequiringAuth()
    {
    }
}

For your use case, you may need to inherit from the AuthorizationAttribute, as described in this answer.

Community
  • 1
  • 1
John Koerner
  • 37,428
  • 8
  • 84
  • 134
  • Thank you John for your reply. I did look at this sort of approach. Here are the two reasons I decided against it: 1. The team that works on authentication is separate from the team that works on the UI. The attributing approach requires modifications to the site code itself. I was hoping for a more componentized approach, where I could drop a DLL into the bin folder, add some config, and be done. 2. The module we are working on intercepts all requests, not just requests for actions defined in the web site (e.g. handlers for login and logout that are not implemented as web site actions). – Jasmine Howell Apr 14 '13 at 03:13