Внедрение зависимостей с атрибутом Ninject и Filter для asp.net mvc - PullRequest
56 голосов
/ 01 июня 2011

Я пишу собственный Фильтр авторизации для asp.net mvc 3. Мне нужно внедрить userservice в класс, но я не знаю, как это сделать.

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();
    }
}

Я используюобъект для внедрения зависимости.Я не хочу использовать шаблон фабричного или сервисного локатора.

Мои привязки выглядят так в global.acsx:

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

Ответы [ 4 ]

81 голосов
/ 01 июня 2011

Смотрите этот ответ:

Пользовательская авторизация 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
{

}

НТН ...

11 голосов
/ 26 июня 2013

Я бы очень рекомендовал бы ответ БЖ. НЕ ИСПОЛЬЗУЙТЕ [Inject]!

Я использовал [Inject], как, по словам Дарина Димитрова, было возможно, и это на самом деле вызывало проблемы с многопоточностью в условиях высокой нагрузки и высокой конкуренции в сочетании с .InRequestScope.

BZ - это то же, что и в Wiki, и я видел много мест, где Remo Gloor (автор Ninject) говорит, что это правильный способ сделать это

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

Downvote [Inject] отвечает здесь, потому что серьезно вы обожжетесь (вероятно, в работе, если вы не загрузите тест должным образом!)

9 голосов
/ 19 ноября 2014

Я нашел простое решение для любого случая, когда конструкция не обрабатывается Ninject:

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

На самом деле это именно то, что я использую с моим пользовательским AuthorizeAttribute.Гораздо проще, чем реализовать отдельный FilterAttribute.

8 голосов
/ 01 июня 2011

По пути можно использовать инъекцию свойства и украсить свойство атрибутом [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, поэтомуубедитесь, что вы перенесли это в область видимости, прежде чем вызывать его в ядре.

...