views:

1878

answers:

6

I want to use the RequireHttpsAttribute to prevent unsecured HTTP requests from being sent to an action method.

C#

[RequireHttps] //apply to all actions in controller
public class SomeController 
{
    [RequireHttps] //apply to this action only
    public ActionResult SomeAction()
    {
        ...
    }
}

VB

<RequireHttps()> _
Public Class SomeController

    <RequireHttps()> _
    Public Function SomeAction() As ActionResult
        ...
    End Function

End Class

Unfortunately, ASP.NET Development Server doesn't support HTTPS.

How can I make my ASP.NET MVC application use RequireHttps when published to the production environment, but not when run on my development workstation on the ASP.NET Development Server?

+6  A: 

How about inheriting the RequireHttps attribute in a custom attribute. Then, inside your custom attribute, check the IsLocal property of the current request to see if the request is coming from the local machine. If it is, then do not apply the base functionality. Otherwise, call the base operation.

spot
+24  A: 

This won't help if you run Release builds on your development workstation, but conditional compilation could do the job...

#if !DEBUG
[RequireHttps] //apply to all actions in controller
#endif
public class SomeController 
{
    //... or ...
#if !DEBUG
    [RequireHttps] //apply to this action only
#endif
    public ActionResult SomeAction()
    {
    }

}

Update

In Visual Basic, attributes are technically part of the same line as the definition they apply to. You can't put conditional compilation statements inside a line, so you're forced to write the function declaration twice - once with the attribute, and once without. It does work, though, if you don't mind the ugliness.

#If Not Debug Then
    <RequireHttps()> _
    Function SomeAction() As ActionResult
#Else
    Function SomeAction() As ActionResult
#End If
        ...
    End Function

Update 2

Several people have mentioned deriving from RequireHttpsAttribute without providing an example, so here's one for you. I think that this approach would be much cleaner than the conditional compilation approach, and it would be my preference in your position.

DISCLAIMER: I haven't tested this code, even a little bit, and my VB is fairly rusty. All I know is that it compiles. I wrote it based on the suggestions of spot, queen3, and Lance Fisher. If it doesn't work, it should at least convey the general idea, and give you starting point.

Public Class RemoteRequireHttpsAttribute
    Inherits System.Web.Mvc.RequireHttpsAttribute

    Public Overrides Sub OnAuthorization(ByVal filterContext As  _
                                         System.Web.Mvc.AuthorizationContext)
        If IsNothing(filterContext) Then
            Throw New ArgumentNullException("filterContext")
        End If

        If Not IsNothing(filterContext.HttpContext) AndAlso _
            filterContext.HttpContext.Request.IsLocal Then
            Return
        End If

        MyBase.OnAuthorization(filterContext)
    End Sub

End Class

Basically, the new attribute just quits out instead of running the default SSL authorization code, if the current request is local (that is, you're accessing the site through localhost). You can use it like this:

<RemoteRequireHttps()> _
Public Class SomeController

    <RemoteRequireHttps()> _
    Public Function SomeAction() As ActionResult
        ...
    End Function

End Class

Much cleaner! Provided my un-tested code actually works.

Joel Mueller
Thanks for, um, editing my post for me, Zack. Your question was in C#, so I posted a C# response. I didn't know VB was relevant. Anyone know if there is a way to use conditional compilation to control attributes in VB, or is that just not possible?
Joel Mueller
Yes, it works for C#, and it works for VB too, but you have to do some rather ugly duplication of the function/class definition. See my updated answer above.
Joel Mueller
Sorry. VB code samples are getting harder and harder to come by. I didn't think it would matter. I've updated the original question. Do conditional compilation around attributes work for sure in C#? I haven't tested. That seems like a perfect, elegant solution.
Zack Peterson
A little ugly, but it'll work. Thank you, Joel.
Zack Peterson
Your RemoteRequireHttpsAttribute code works perfectly. That's much more elegant for VB than the conditional compilation. Thanks again Joel.
Zack Peterson
+2  A: 

If you can derive and override - do it. If you can't - MVC comes with sources, just take the sources and create your own [ForceHttps] attribute that checks IsLocal.

queen3
+9  A: 

Deriving from RequireHttps is a good approach.

To side step the issue entirely, you can use IIS on your local machine with a self-signed certificate too. IIS is faster than the built-in webserver, and you have the advantage that your development environment is more like production.

Lance Fisher
+1 this is what I do. The fewer moving parts, the better
Gabe Moothart
+3  A: 

As it was the ASP.Net Development Server that caused your problem in the first place, it's worth noting that Microsoft will soon release IIS Express. This is a cut-down version of IIS that will be as easy to use as the Development Server, but will support the full feature set of IIS 7.5 including SSL.

Samuel Jack