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>();
}
}
この回答を参照してください:
コンストラクターインジェクションを使用する場合は、属性とフィルターを作成する必要があります。
///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 ...
私は非常にB Zの答えをお勧めします。 [Inject]を使用しないでください!
Darin Dimitrovが可能だと言ったように[Inject]を使用し、実際に.InRequestScopeと共に高負荷、高競合の状況でスレッドの問題を引き起こしました。
B Zの方法はWikiにもあります。RemoGloor(Ninjectの著者)がこれを行う正しい方法だと言っている場所を見てきました
https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
ダウンボート[インジェクト]はここで答えます。真剣に火傷するからです(前にテストを適切にロードしないと、おそらく本番環境で!)。
Ninjectで処理が処理されない場合に、簡単な解決策を見つけました。
var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));
実際、これはまさにカスタムAuthorizeAttributeで使用しているものです。別のFilterAttributeを実装するよりもはるかに簡単です。
途中でプロパティインジェクションを使用し、[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
名前空間ですので、カーネルで呼び出す前に、それをスコープに持っていることを確認してください。