Setelah meneliti dengan keras, saya dapat memecahkan masalah ini dengan IIS Express dan menimpa metode OnAuthorization kelas Controller (Ref # 1). Saya juga telah mengikuti rute yang direkomendasikan oleh Hanselman (Referensi # 2). Namun, saya tidak sepenuhnya puas dengan dua solusi ini karena dua alasan: 1. OnAuthorization Ref # 1 hanya bekerja pada level tindakan, bukan pada level kelas controller 2. Ref # 2 membutuhkan banyak pengaturan (Win7 SDK untuk makecert ), perintah netsh, dan, untuk menggunakan port 80 dan port 443, saya perlu meluncurkan VS2010 sebagai administrator, yang tidak saya sukai.
Jadi, saya menemukan solusi ini yang berfokus pada kesederhanaan dengan kondisi berikut:
Saya ingin dapat menggunakan attbbute RequireHttps di kelas Controller atau tingkat tindakan
Saya ingin MVC menggunakan HTTPS ketika atribut RequireHttps ada, dan menggunakan HTTP jika tidak ada
Saya tidak ingin menjalankan Visual Studio sebagai administrator
Saya ingin dapat menggunakan port HTTP dan HTTPS apa pun yang ditetapkan oleh IIS Express (Lihat Catatan # 1)
Saya dapat menggunakan kembali sertifikat SSL yang ditandatangani sendiri dari IIS Express, dan saya tidak peduli jika saya melihat prompt SSL yang tidak valid
Saya ingin dev, test, dan produksi memiliki basis kode yang sama persis dan biner yang sama dan independen dari pengaturan tambahan (misalnya menggunakan netsh, mmc cert snap-in, dll.) Sebanyak mungkin
Sekarang, dengan latar belakang dan penjelasannya, saya harap kode ini akan membantu seseorang dan menghemat waktu. Pada dasarnya, buat kelas BaseController yang diturunkan dari Controller, dan turunkan kelas kontroler Anda dari kelas dasar ini. Karena Anda telah membaca sejauh ini, saya berasumsi bahwa Anda tahu cara melakukannya. Selamat membuat kode!
Catatan # 1: Ini dicapai dengan menggunakan fungsi 'getConfig' yang berguna (lihat kode)
Referensi # 1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Ref # 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== Kode di 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);
}
============== kode akhir ================
Di Web.Release.Config, tambahkan berikut ini untuk membersihkan HttpPort dan HttpsPort (untuk menggunakan default 80 dan 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>