Araştırma yaptıktan sonra, bu sorunu IIS Express ve Controller sınıfının OnAuthorization yöntemini geçersiz kılarak çözebildim (Ref # 1). Ben de Hanselman tarafından önerilen rotaya gittim (Ref # 2). Ancak, iki nedenden dolayı bu iki çözümden tam olarak memnun kalmadım: 1. Ref # 1'in OnAuthorization, denetleyici sınıfı düzeyinde değil, yalnızca eylem düzeyinde çalışır 2. Ref # 2, çok fazla kurulum gerektirir (makecert için Win7 SDK ), netsh komutları ve 80 numaralı bağlantı noktasını ve 443 numaralı bağlantı noktasını kullanmak için VS2010'u yönetici olarak başlatmam gerekiyor, buna kaşlarını çatıyorum.
Bu nedenle, aşağıdaki koşullarla sadeliğe odaklanan bu çözümü buldum:
Denetleyici sınıfında veya eylem düzeyinde RequireHttps özniteliğini kullanabilmek istiyorum
MVC'nin RequireHttps özniteliği varken HTTPS kullanmasını ve yoksa HTTP kullanmasını istiyorum
Visual Studio'yu yönetici olarak çalıştırmak zorunda kalmak istemiyorum
IIS Express tarafından atanan herhangi bir HTTP ve HTTPS bağlantı noktasını kullanabilmek istiyorum (Bkz. Not 1)
IIS Express'in kendinden imzalı SSL sertifikasını yeniden kullanabilirim ve geçersiz SSL istemini görmem umurumda değil
Geliştirme, test ve üretimin tamamen aynı kod tabanına ve aynı ikili programa sahip olmasını ve ek kurulumdan (ör. Netsh, mmc cert ek bileşenini kullanarak vb.) Bağımsız olmasını istiyorum.
Şimdi, arka plan ve açıklamanın dışında, umarım bu kod birisine yardımcı olur ve biraz zaman kazandırır. Temel olarak, Controller'dan miras alan bir BaseController sınıfı oluşturun ve denetleyici sınıflarınızı bu temel sınıftan türetin. Şimdiye kadar okuduğunuza göre, bunları nasıl yapacağınızı bildiğinizi varsayıyorum. Öyleyse, mutlu kodlamalar!
Not 1: Bu, yararlı bir 'getConfig' işlevi kullanılarak elde edilir (koda bakın)
Referans # 1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Referans # 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== BaseController'daki Kod =====================
#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);
}
============== bitiş kodu ================
Web.Release.Config'de, HttpPort ve HttpsPort'u temizlemek için aşağıdakileri ekleyin (varsayılan 80 ve 443'ü kullanmak için).
<appSettings>
<add key="HttpPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
<add key="HttpsPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>