Dopo aver cercato aroud, sono stato in grado di risolvere questo problema con IIS Express e un override del metodo OnAuthorization della classe Controller (Rif # 1). Sono andato anche con il percorso consigliato da Hanselman (Rif # 2). Tuttavia, non ero completamente soddisfatto di queste due soluzioni per due motivi: 1. L'autorizzazione On di Ref # 1 funziona solo a livello di azione, non a livello di classe controller 2. Ref # 2 richiede molte impostazioni (Win7 SDK per makecert ), comandi netsh e, per poter utilizzare la porta 80 e la porta 443, devo avviare VS2010 come amministratore, cosa che non mi piace.
Quindi, ho trovato questa soluzione che si concentra sulla semplicità con le seguenti condizioni:
Voglio essere in grado di utilizzare l'attributo RequireHttps a livello di classe o azione Controller
Voglio che MVC utilizzi HTTPS quando l'attributo RequireHttps è presente e utilizzi HTTP se è assente
Non voglio dover eseguire Visual Studio come amministratore
Voglio essere in grado di utilizzare qualsiasi porta HTTP e HTTPS assegnata da IIS Express (vedi nota n. 1)
Posso riutilizzare il certificato SSL autofirmato di IIS Express e non mi interessa se vedo il prompt SSL non valido
Voglio che sviluppo, test e produzione abbiano la stessa identica base di codice e lo stesso binario e il più possibile indipendenti dalla configurazione aggiuntiva (ad esempio utilizzando netsh, snap-in mmc cert, ecc.)
Ora, con lo sfondo e la spiegazione fuori mano, spero che questo codice aiuti qualcuno e faccia risparmiare un po 'di tempo. Fondamentalmente, crea una classe BaseController che eredita da Controller e deriva le classi del controller da questa classe base. Dato che hai letto fin qui, presumo che tu sappia come farlo. Quindi, buona programmazione!
Nota # 1: ciò si ottiene utilizzando un'utile funzione 'getConfig' (vedi codice)
Rif n.1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Rif # 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== Codice in BaseController ===================
#region Override to reroute to non-SSL port if controller action does not have RequireHttps attribute to save on CPU
// By L. Keng, 2012/08/27
// Note that this code works with RequireHttps at the controller class or action level.
// Credit: Various stackoverflow.com posts and http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
protected override void OnAuthorization(AuthorizationContext filterContext)
{
// if the controller class or the action has RequireHttps attribute
var requireHttps = (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0
|| filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0);
if (Request.IsSecureConnection)
{
// If request has a secure connection but we don't need SSL, and we are not on a child action
if (!requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "http",
Port = int.Parse(getConfig("HttpPort", "80")) // grab from config; default to port 80
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
else
{
// If request does not have a secure connection but we need SSL, and we are not on a child action
if (requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "https",
Port = int.Parse(getConfig("HttpsPort", "443")) // grab from config; default to port 443
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
base.OnAuthorization(filterContext);
}
#endregion
// a useful helper function to get appSettings value; allow caller to specify a default value if one cannot be found
internal static string getConfig(string name, string defaultValue = null)
{
var val = System.Configuration.ConfigurationManager.AppSettings[name];
return (val == null ? defaultValue : val);
}
============== codice finale ================
In Web.Release.Config, aggiungi quanto segue per cancellare HttpPort e HttpsPort (per usare i valori predefiniti 80 e 443).
<appSettings>
<add key="HttpPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
<add key="HttpsPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>