В рамках системы авторизации с поддержкой идентификации я хотел бы использовать IAuhtorizationFilter и Attributes, чтобы ограничить доступ к методам действий в моих контроллерах. У меня все работает очень хорошо, отчасти благодаря помощи следующих ресурсов:
- Ninject Binding Attribute to Filter with Constructor Arguments
- https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
- Пользовательская авторизация MVC 3 и Ninject IoC
- https://github.com/ninject/ninject.web.mvc/wiki/Dependency-injection-for-filters
Однако, когда я пытаюсь украсить метод действия более чем одним из моих атрибутов, я получаю следующее исключение (извините за форматирование):
[InvalidOperationException: Sequence contains more than one element] System.Linq.Enumerable.Single(IEnumerable`1 source) +2691369 Ninject.Web.Mvc.FilterBindingSyntax.c__DisplayClass15`1.b__14(IContext ctx, ControllerContext controllerContext, ActionDescriptor actionDescriptor) in c:\Projects\Ninject\Maintenance2.2\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\FilterBindingSyntax\FilterFilterBindingBuilder.cs:379 Ninject.Web.Mvc.FilterBindingSyntax.c__DisplayClass12.b__11(IContext ctx) in c:\Projects\Ninject\Maintenance2.2\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\FilterBindingSyntax\FilterFilterBindingBuilder.cs:358 Ninject.Parameters.c__DisplayClass6.b__4(IContext ctx, ITarget target) in c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Parameters\Parameter.cs:60 Ninject.Parameters.Parameter.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Parameters\Parameter.cs:88 Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:97 Ninject.Activation.Providers.c__DisplayClass2.b__1(ITarget target) in c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:81 ...
Вот очень упрощенная версия моего кода, демонстрирующая проблему в приложении MVC3:
Атрибут:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class SampleAttribute : Attribute
{
private Guid typeId;
public bool IsAllowed { get; set; }
public SampleAttribute(bool IsAllowed)
{
this.IsAllowed = IsAllowed;
this.typeId = new Guid();
}
public override object TypeId
{
get
{
return (object)typeId;
}
}
}
Фильтр:
public class SampleFilter : IAuthorizationFilter, IMvcFilter
{
private bool isAllowed;
public bool AllowMultiple
{
get { return true; }
}
public int Order
{
get { return 0; }
}
public SampleFilter(bool isAllowed)
{
this.isAllowed = isAllowed;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
if (!isAllowed)
throw new Exception("unauthorized");
}
}
Контроллер:
public class HomeController : Controller
{
[Sample(true)]
[Sample(false)]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
Приведенный выше метод контроллера работает должным образом, если один или другой атрибут Sample
в методе Index()
удален. Наличие обоих на месте генерирует исключение. Я понимаю, что в этом упрощенном примере нет ситуации, в которой потребовались бы оба атрибута, но это просто для иллюстрации.
Что мне не хватает?