หลังจากค้นคว้า aroud แล้วฉันสามารถแก้ปัญหานี้ได้ด้วย IIS Express และการแทนที่เมธอด OnAuthorization ของคลาส Controller (Ref # 1) ฉันได้ไปกับเส้นทางที่แนะนำโดย Hanselman (Ref # 2) อย่างไรก็ตามฉันไม่พอใจกับโซลูชันทั้งสองนี้อย่างสมบูรณ์เนื่องจากเหตุผลสองประการ: 1. OnAuthorization ของ Ref # 1 ใช้งานได้ในระดับการดำเนินการเท่านั้นไม่ใช่ในระดับคลาสคอนโทรลเลอร์ 2 Ref # 2 ต้องการการตั้งค่าจำนวนมาก (Win7 SDK สำหรับ makecert ), คำสั่ง netsh และในการใช้พอร์ต 80 และพอร์ต 443 ฉันต้องเปิด VS2010 ในฐานะผู้ดูแลระบบซึ่งฉันขมวดคิ้ว
ดังนั้นฉันจึงคิดวิธีแก้ปัญหานี้ที่เน้นความเรียบง่ายโดยมีเงื่อนไขต่อไปนี้:
ฉันต้องการใช้ Attbbute RequireHttps ที่ระดับ Controller หรือระดับการกระทำ
ฉันต้องการให้ MVC ใช้ HTTPS เมื่อมีแอตทริบิวต์ RequireHttps และใช้ HTTP หากไม่มี
ฉันไม่ต้องการที่จะต้องเรียกใช้ Visual Studio ในฐานะผู้ดูแลระบบ
ฉันต้องการใช้พอร์ต HTTP และ HTTPS ใด ๆ ที่ IIS Express กำหนด (ดูหมายเหตุ # 1)
ฉันสามารถใช้ใบรับรอง SSL ที่ลงชื่อด้วยตนเองของ IIS Express ซ้ำได้และฉันไม่สนใจว่าฉันจะเห็นข้อความแจ้ง SSL ที่ไม่ถูกต้องหรือไม่
ฉันต้องการให้ dev ทดสอบและการผลิตมีฐานรหัสเดียวกันและไบนารีเดียวกันและเป็นอิสระจากการตั้งค่าเพิ่มเติม (เช่นการใช้ netsh, mmc cert snap-in ฯลฯ ) ที่สุด
ตอนนี้ด้วยพื้นหลังและคำอธิบายที่ไม่ชัดเจนฉันหวังว่ารหัสนี้จะช่วยใครบางคนและประหยัดเวลาได้บ้าง โดยทั่วไปให้สร้างคลาส BaseController ที่สืบทอดมาจาก Controller และรับคลาสคอนโทรลเลอร์ของคุณจากคลาสพื้นฐานนี้ เนื่องจากคุณได้อ่านมาจนถึงตอนนี้ฉันคิดว่าคุณรู้วิธีดำเนินการเหล่านี้ ขอให้มีความสุขกับการเขียนโค้ด!
หมายเหตุ # 1: ทำได้โดยการใช้ฟังก์ชันที่มีประโยชน์ 'getConfig' (ดูรหัส)
Ref # 1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Ref # 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== รหัสใน 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);
}
============== end code ================
ใน Web.Release.Config ให้เพิ่มสิ่งต่อไปนี้เพื่อล้าง HttpPort และ HttpsPort (เพื่อใช้ค่าเริ่มต้น 80 และ 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>