Reputation: 861
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?
Upvotes: 1
Views: 1333
Reputation: 861
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 ;)
Upvotes: 2
Reputation: 38077
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.
Upvotes: 1