0

カスタムを使用して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 になります。

ここで何が欠けているか知っている人はいますか?

4

4 に答える 4

0

このスレッドで説明されているように、これをカスタム フィルター プロバイダーで動作させることができませんでした。

ASP.NET Web Api でアクション フィルターを単体テストするにはどうすればよいですか?

たくさんのオプションを試しましたが、依存関係解決関数を属性に挿入することになりました。そうすれば、単体テストはフェイクやモックなどを返す関数を注入でき、アプリケーションは IoC コンテナーを使用して依存関係を解決する関数を注入できます。

私はそれをどのように機能させたかについての短いブログ投稿を書きました。あなたがそれについてどう思うか、そしてそれがあなたを助けたかどうか聞いてみたいです:

http://danielsaidi.com/blog/2015/09/11/asp-net-and-webapi-attributes-with-structuremap

于 2015-09-10T10:28:17.097 に答える
0

残念ながら、何が起こっているのかを追跡することはできませんでした。だから、今のところ問題を「修正」した方法は次のとおりです-

    [SetterProperty]
    public UserProfileRepository User
    {
        get { return _user ?? DependencyResolver.Current.GetService<UserProfileRepository>(); }
        set { _user = value; }
    }

インジェクションが機能する場合は、注入された値が使用されます。それ以外の場合は、 を使用しDependencyResolverて手作業で汚い作業を行います。きれいではありませんが、今のところ他に選択肢はありません。

于 2014-12-22T20:40:41.783 に答える
0

私も同じ問題に直面していて、さまざまな方法を試していましたが、最終的にこれは削除後に機能し[AllowMultiple = true]、今AuthorizeCoreでは一度呼び出されます。これがどのようにリンクされているのか興味がありますAuthorizeCore

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CompanyAuthorizeAttribute : AuthorizeAttribute
{}

そうなる前に

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class CompanyAuthorizeAttribute : AuthorizeAttribute
{}
于 2014-12-18T17:07:45.473 に答える