問題を調査した後、IIS ExpressとコントローラークラスのOnAuthorizationメソッドのオーバーライドでこの問題を解決することができました(参照#1)。私はまた、ハンセルマンが推奨するルートを使用しました(参照番号2)。ただし、次の2つの理由により、これら2つのソリューションに完全に満足できませんでした。1. Ref#1のOnAuthorizationは、アクションレベルでのみ機能し、コントローラークラスレベルでは機能しません。 )、netshコマンド、そしてポート80とポート443を使用するには、VS2010を管理者として起動する必要があります。
そこで、次の条件でシンプルさを重視するこのソリューションを思いつきました。
コントローラークラスまたはアクションレベルでRequireHttps attbbuteを使用できるようにしたい
RequireHttps属性が存在する場合はMVCでHTTPSを使用し、存在しない場合はHTTPを使用したい
管理者としてVisual Studioを実行する必要がない
IIS Expressによって割り当てられたHTTPおよびHTTPSポートを使用できるようにしたい(注1を参照)
IIS Expressの自己署名SSL証明書を再利用できますが、無効なSSLプロンプトが表示されても問題ありません
開発、テスト、および本番環境で、まったく同じコードベースと同じバイナリを使用し、追加のセットアップ(たとえば、netsh、mmc certスナップインなど)からできるだけ独立させたい
今、背景と説明が邪魔にならないように、このコードが誰かを助け、時間を節約できることを願っています。基本的に、Controllerから継承するBaseControllerクラスを作成し、この基本クラスからコントローラークラスを派生させます。ここまで読んだので、これらの方法を知っていると思います。だから、幸せなコーディング!
Note#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);
}
==============終了コード================
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>