web-dev-qa-db-ja.com

asp.net mvcのNinjectおよびFilter属性を使用した依存性注入

Asp.net mvc 3のカスタム認証フィルターを作成しています。ユーザーサービスをクラスに注入する必要がありますが、これを行う方法がわかりません。

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
    private IUserService userService;
    private string[] roles;

    public AuthorizeAttribute(params string[] roles)
    {
        this.roles = roles;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        throw new NotImplementedException();
    }
}

私は、依存性注入にninjectを使用しています。 Factoryまたはサービスロケーターパターンを使用したくありません。

Global.acsxでのバインディングは次のようになります。

    internal class SiteModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IUserService>().To<UserService>();
        }
    }
56
Shawn Mclean

この回答を参照してください:

カスタム認証MVC 3およびNinject IoC

コンストラクターインジェクションを使用する場合は、属性とフィルターを作成する必要があります。

///marker attribute
public class MyAuthorizeAttribute : FilterAttribute { }

//filter
public class MyAuthorizeFilter : IAuthorizationFilter
{
      private readonly IUserService _userService;
      public MyAuthorizeFilter(IUserService userService)
      {
          _userService = userService;
      }

      public void OnAuthorization(AuthorizationContext filterContext)
      {
          var validUser = _userService.CheckIsValid();

          if (!validUser)
          {
              filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "action", "AccessDenied" }, { "controller", "Error" } });
          }
      }
}

バインディング:

this.BindFilter<MyAuthorizeFilter>(System.Web.Mvc.FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>();

コントローラ:

[MyAuthorizeAttribute]
public class YourController : Controller
{

}

HTH ...

81
B Z

私は非常にB Zの答えをお勧めします。 [Inject]を使用しないでください!

Darin Dimitrovが可能だと言ったように[Inject]を使用し、実際に.InRequestScopeと共に高負荷、高競合の状況でスレッドの問題を引き起こしました。

B Zの方法はWikiにもあります。RemoGloor(Ninjectの著者)がこれを行う正しい方法だと言っている場所を見てきました

https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations

ダウンボート[インジェクト]はここで答えます。真剣に火傷するからです(前にテストを適切にロードしないと、おそらく本番環境で!)。

11
John Culviner

Ninjectで処理が処理されない場合に、簡単な解決策を見つけました。

var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));

実際、これはまさにカスタムAuthorizeAttributeで使用しているものです。別のFilterAttributeを実装するよりもはるかに簡単です。

9
Wolfgang

途中でプロパティインジェクションを使用し、[Inject]属性:

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
    [Inject]
    public IUserService UserService { get; set; }

    private string[] roles;

    ...
}

コンストラクター注入は、コントローラー/アクションをそれらで装飾することができなくなるため、属性ではうまく機能しません。 NInjectのフィルターバインディング構文でのみコンストラクター挿入を使用できます。

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
    private readonly IUserService userService;

    private string[] roles;

    public AuthorizeAttribute(IUserService userService, params string[] roles)
    {
        this.userService = userService;
        this.roles = roles;
    }

    ...
}

その後:

internal class SiteModule : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        Bind<IUserService>().To<UserService>();

        this.BindFilter<AuthorizeAttribute>(FilterScope.Controller, 0)
            .WhenControllerType<AdminController>();
    }
}

BindFilter<>拡張メソッドはNinject.Web.Mvc.FilterBindingSyntax名前空間ですので、カーネルで呼び出す前に、それをスコープに持っていることを確認してください。

8
Darin Dimitrov