カスタムを使用してAuthorizeAttribute
、ユーザー認証のいくつかの側面を処理します。認証中に値を確認するには、データベースへのアクセスを追加する必要があります。このプロジェクトはリポジトリ パターンを使用し、リポジトリはすべて StructureMap を介してコントローラー コンストラクターでインスタンス化されます。
残念ながら、フィルターでコンストラクター注入を使用する方法はないようです。Jimmy Bogard ( http://lostechies.com/jimmybogard/2010/05/03/dependency-injection-in-asp-net-mvc-filters/ ) の記事で、プロパティ インジェクションを使用してこのシナリオを処理する方法を説明している記事を見つけました。基本的に、Jimmy のコードはGetFilters
メソッドをインターセプトし、各フィルターControllerActionInvoker
で実行BuildUp
してプロパティを設定します。これはまさに私が必要としていたものだったので、次のクラスを追加しました -
public class InjectingActionInvoker : ControllerActionInvoker
{
private readonly IContainer _container;
public InjectingActionInvoker(IContainer container)
{
_container = container;
}
protected override FilterInfo GetFilters(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
var info = base.GetFilters(controllerContext, actionDescriptor);
info.AuthorizationFilters.ForEach(_container.BuildUp);
info.ActionFilters.ForEach(_container.BuildUp);
info.ResultFilters.ForEach(_container.BuildUp);
info.ExceptionFilters.ForEach(_container.BuildUp);
return info;
}
}
そして、これらの行でそれを StructureMap に配線します -
For<IActionInvoker>().Use<InjectingActionInvoker>();
For<ITempDataProvider>().Use<SessionStateTempDataProvider>();
Policies.SetAllProperties(c =>
{
c.OfType<IActionInvoker>();
c.OfType<ITempDataProvider>();
c.WithAnyTypeFromNamespaceContainingType<UserProfileRepository>();
});
最後に、パブリック プロパティをカスタムAuthorizeAttribute
クラスに追加しました。
[SetterProperty]
public UserProfileRepository User { get; set; }
プロジェクトを実行して安全なページにアクセスすると、AuthorizeCore
コードが 2 回ヒットします。初めて、私のプロパティが設定され、適切に機能しています。ただし、プロパティが null であるため、2 番目の呼び出しは失敗します。メソッドにブレークポイントを設定しましたGetFilters
が、最初にヒットしただけです。残念ながら、StructureMap や Filters について、これがどこで横行しているのかを正確に把握できるほど十分に理解していません。
以下は、誰にとっても役立つ場合に備えて、コールスタックです-
コール #1
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 78 C#
[External Code]
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C#
[External Code]
コール #2
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 69 C#
[External Code]
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C#
[External Code]
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Menu_cshtml.Execute() Line 2 C#
[External Code]
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Layout_cshtml.Execute() Line 51 C#
[External Code]
StructureMap の達人で知恵を共有したい人はいますか? 助けてくれてありがとう!
編集:_Menu.cshtml
ファイルのコードは次のとおりです-
@(Html.Kendo().Menu()
.Name("Menu")
.Items(items =>
{
items.Add().Text("My Dashboard").Action("Dashboard", "Home");
items.Add().Text("My Account").Action("Edit", "Account");
items.Add().Text("Purchase/Renew").Action("Index", "Purchase");
items.Add().Text("Administration")
.Items(children =>
{
children.Add().Text("Accounts").Action("Index", "UserProfile");
children.Add().Text("Coupons").Action("Index", "Coupon");
});
items.Add().Text("Logout").Action("Logout", "Logon");
})
)
NightOwl888 からのいくつかのプロンプトのおかげで、問題を Kendo Menu コールに切り分けました。の最終行にブレークポイントを配置して_Menu.cshtml
ステップインすると、DoGetInstance が HomeController に対して呼び出されていることがわかります。それが完了するとすぐに、OnAuthorization が 2 度目に起動され、リポジトリ プロパティが null になります。
ここで何が欠けているか知っている人はいますか?