How to switch between HTTP and HTTPS in ASP.NET MVC2
ASP.NET MVC2 has the new RequireHttpsAttribute that you can use to decorate any action to force any non-secure request to come through HTTPS (SSL). It can be used as simply as this:
[RequireHttps]
public ActionResult LogOn()
{
.....
}
Now any request to the LogOn action that is not over HTTPS will automatically be redirected back to itself over HTTPS. This is very useful and easy to implement.
Unfortunately though, once the scheme is changed to HTTPS, all following requests will also be under HTTPS, which is not necessarily what you want. In most cases you do not need all requests to your site to be secure but only certain ones such as the logon page or pages that accept credit card information.
To handle this you can override the Controller.OnAuthorization method. From within this method, you can check to see if the RequireHttps attribute is set on the Controller Action by searching the Attributes collection of the ActionDescriptor object. If the RequireHttpsAttribute is not set AND the request is under SSL, then return a redirect result to the HTTP (non-SSL) url:
public class ControllerBase : Controller
{
protected override void OnAuthorization(AuthorizationContext filterContext)
{//the RequireHttpsAttribute set on the Controller Action will handle redirecting to Https.
// We just need to handle any requests that are already under SSL but should not be.
if (Request.IsSecureConnection)
{
Boolean requireHttps = false;
requireHttps = filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), false).Count() >= 1;
//If this request is under ssl but yet the controller action
// does not require it, then redirect to the http version.
if (!requireHttps && !filterContext.IsChildAction)
{
UriBuilder uriBuilder = new UriBuilder(Request.Url);
//change the scheme
uriBuilder.Scheme = "http";
uriBuilder.Port = 80;
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
base.OnAuthorization(filterContext);
}
}
Now any HTTPS requests to controller actions that are not decorated with a RequireHttps attribute will be forced back to an HTTP (non-secure) request.
EDITED (2010-08-21): Modified the code as recommended by the comment from Donnie Hale to move the check for Request.SecureConnection to the outermost if block.
EDITED (2011-01-06): Modified the code as recommended by the comment from Sergio Tai to not perform this check if use Html.Action in views