这是设置.假设我有一些需要服务实例的动作过滤器:
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething(){}
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个需要该服务实例的ActionFilter:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService; // <--- How do we get this injected
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
在MVC 1/2中,将依赖关系注入动作过滤器是一个痛苦的屁股.最常见的方法是使用自定义操作调用因为在这里可以看到:http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/的这种解决方法背后的主要动机是因为以下方法被认为是与容器的草率和紧密耦合:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService;
public MyActionFilter()
:this(MyStaticKernel.Get<IMyService>()) //using Ninject, but would apply to any container
{
}
public MyActionFilter(IMyService myService)
{
_myService = myService;
} …Run Code Online (Sandbox Code Playgroud) c# asp.net-mvc dependency-injection actionfilterattribute asp.net-mvc-3
我尽可能多地阅读了这些答案,但它们似乎没有达到一个细节.
问题是当动作过滤器(由控制器注入的服务)绑定到相应的属性时,我一直无法弄清楚如何将参数/属性值从属性传递到其绑定过滤器.下面是代码,下面是我想要的假代码:
过滤器和属性
public class AuthorizationFilter : IAuthorizationFilter
{
private readonly IAuthorizationService _authorizationService;
private readonly UserRoles _requiredRoles; // Enum
public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles)
{
_authorizationService = authorizationService;
_requiredRoles = requiredRoles;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Session == null)
HandleUnauthorizedRequest(filterContext);
else {
var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles);
if (!authorized)
HandleUnauthorizedRequest(filterContext);
// else TODO: deal with cache...
}
}
}
public class RequireRolesAttribute : FilterAttribute
{
public readonly UserRoles RequiredRoles;
public RequireRolesAttribute(UserRoles requiredRoles)
{
RequiredRoles = requiredRoles;
} …Run Code Online (Sandbox Code Playgroud) attributes dependency-injection ninject filter asp.net-mvc-3
嘿那里,我已经成功地在我的FilterAttribute中使用了属性注入,但是我想知道它是否可以将它移动到构造函数中呢?
我目前的代码:
// AuthAttribute.cs
public class AuthAttribute : ActionFilterAttribute
{
public Roles _authRoles { get; private set; }
[Inject]
private readonly IAuthorizationService _service;
public AuthAttribute(Roles roles)
{
_authRoles = roles;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;
string redirectUrl = string.Format("?returnUrl={0}", redirectOnSuccess);
string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
filterContext.HttpContext.Response.Redirect(loginUrl, true);
}
else
{
bool isAuthorized = _service.Authorize(GetUserSession.Id, _authRoles.ToString());
if (!isAuthorized)
{
// TODO: Make custom "Not Authorized" error page.
throw new UnauthorizedAccessException("No access"); …Run Code Online (Sandbox Code Playgroud) c# asp.net dependency-injection actionfilterattribute asp.net-mvc-3
我有一个自定义授权类,它继承自FilterAttribute并实现IAuthorizationFilter.我正在使用最新版本的Ninject w/asp.net MVC 3支持.
我遇到的问题是我使用构造函数注入来注入存储库.但是在调用OnAuthorization时,存储库为null.这是代码......
public class MyAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly IMyRepo _MyRepo;
public MyAuthorizeAttribute() { }
public MyAuthorizeAttribute(IMyRepo myRepo)
{
_MyRepo= myRepo; //this gets initialized
}
public void OnAuthorization(AuthorizationContext filterContext)
{
_MyRepo.DoStuff(); //<< Null, wtf
}
}
Run Code Online (Sandbox Code Playgroud)
过滤器绑定:
Bind<IMyRepo>().To<MyRepo>().InRequestScope();
this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Controller, null).WhenControllerHas<MyAuthorizeAttribute >();
Run Code Online (Sandbox Code Playgroud)
更新: 我注意到的一件事是这个过滤器处于控制器级别.我在行动范围内有其他过滤器似乎正常工作......这可能是原因吗?
更新2: 我已经确认,如果我将过滤器范围更改为action,则存储库可用OnAuthorization(非null).
这在下面工作,但我需要在控制器范围,而不是行动.
this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Action, null).WhenActionMethodHas<MyAuthorizeAttribute >();
Run Code Online (Sandbox Code Playgroud) 我正在关注此页面上的ninject过滤器属性设置.
对他们来说,他们有:
.WithConstructorArgumentFromControllerAttribute<LogAttribute>(
"logLevel", attribute => attribute.LogLevel);
Run Code Online (Sandbox Code Playgroud)
第二个参数是期待a Func<LogAttribute, object> callback.他们的实际参数列表设置如下:
Log(LogLevel = Level.Debug)
Run Code Online (Sandbox Code Playgroud)
但我的filter属性设置如下:
public class AuthAttribute : FilterAttribute { }
public class AuthFilter : IAuthorizationFilter
{
private readonly IUserService userService;
private string[] roles;
//Stuck on the constructor also. How do I accept params?
public AuthFilter(IUserService userService, params string[] roles)
{
this.userService = userService;
this.roles = roles;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
不知怎的,这是错误的.因为我希望我的过滤器看起来像:
[Auth("Admin", "Contrib")]
Run Code Online (Sandbox Code Playgroud)
我的绑定:
kernel.BindFilter<AuthFilter>(FilterScope.Controller, 0)
.WhenControllerHas<AuthAttribute>()
.WithConstructorArgumentFromControllerAttribute<AuthAttribute>("roles", …Run Code Online (Sandbox Code Playgroud) 我使用的是asp.net mvc 3,ninject 2.0和ninject mvc 3插件.
我想知道如何将服务层添加到我的过滤器中(在这种情况下是授权过滤器?).
我喜欢做构造函数注入,所以这是可能的还是我必须注入属性?
谢谢
编辑
我有这个属性注入,但我的属性总是为空
[Inject]
public IAccountService AccountServiceHelper { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// check if context is set
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
// check if user is authenticated
if (httpContext.User.Identity.IsAuthenticated == true)
{
// stuff here
return true;
}
return false;
}
/// <summary>
/// Application_Start
/// </summary>
protected void Application_Start()
{
// Hook our DI stuff when application starts
IKernel kernel …Run Code Online (Sandbox Code Playgroud) 我遇到了一个有趣的设计问题,我正在写一个类库.我有一个AuthorizeAttribute的自定义实现,我希望客户能够像这样使用:
[Protected("permission_name")]
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,PermissionAttribute继承自AuthorizeAttribute并使用本地默认值(使用HttpContext创建的DefaultContext).
在幕后,该属性使用SecurityService来检查用户,角色和权限(SecurityService本身使用客户端提供的持久性服务,他们可以在应用程序的组合根中连接).
所以我的属性需要引用SecurityService才能运行.由于Attribute构造函数只能有编译时常量,所以我不能使用构造函数注入.
我不想强迫我的客户使用DI框架 - 如果他们愿意,他们应该能够在不使用IoC库的情况下发现并连接其组成根中的必要依赖项.
以下是我的选择:
上面2.的一个可能的解决方案是在应用程序启动时将SecurityService的实例设置为属性的静态属性,并使用guard子句来阻止它被设置多次,如下所示:
class ProtectedAttribute : ...
{
private static ISecurityService _SecurityService ;
public static ISecurityService SecurityService
{
get
{
return _SecurityService ;
}
set
{
if (_SecurityService != null)
throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ;
_SecurityService = value ;
}
}
}
Run Code Online (Sandbox Code Playgroud)
SecurityService可以是抽象服务外观,以便可以通过不同的实现进行扩展/替换.
有没有更好的方法来解决这个问题?
更新:添加一些代码来说明我将如何做:
在返回权限名称的属性上添加公共属性:
public class ProtectedAttribute : ...
{
private string _Permission …Run Code Online (Sandbox Code Playgroud) 我正在使用ASP.NET Web API,我需要获得授权,因此我创建了自定义授权属性
public class CustomAuthorizationAttribute : AuthorizeAttribute
Run Code Online (Sandbox Code Playgroud)
为了在构造函数中注入依赖项,我有以下内容:
public CustomAuthorizationAttribute(IAccountBL accountBl)
{
_accountBL = accountBl;
}
Run Code Online (Sandbox Code Playgroud)
在IAccountBL我的方法,它与用户是否被授权作出要求数据库检查交互.在内部成员API控制器中,我注册了该属性
[CustomAuthorization]
public class MemberController : ApiController
Run Code Online (Sandbox Code Playgroud)
但我得到以下错误
Project.Account.AccountBL'不包含带0个参数的构造函数
如果我注册就好
[CustomAuthorization(IAccountBL)]
Run Code Online (Sandbox Code Playgroud)

谢谢
我正在尝试使用依赖注入和动作过滤器属性为普通的MVC控制器(而不是WebAPI)根据这个答案/sf/answers/433591161/
我见过的文章说你必须使用kernel.BindFilter<>(),但这不适用于我的内核.
using Ninject;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using uQuiz.Domain;
using uQuiz.Domain.Abstract;
using uQuiz.Domain.Concrete;
using uQuiz.Domain.Models;
namespace uQuiz.WebUI.Infrastructure
{
/// <summary>
/// Dependency Resolver for Ninject, called within NinjectWebCommon.cs in App_start folder
/// </summary>
public class NinjectDependencyResolver : NinjectScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
: base (kernelParam)
{
this.kernel = kernelParam;
this.AddBindings();
}
public IDependencyScope BeginScope()
{
return new NinjectScope(kernel.BeginBlock());
}
private void AddBindings()
{
this.kernel.Bind(typeof(IQuizEntities)).To(typeof(QuizEntities)).InRequestScope(); …Run Code Online (Sandbox Code Playgroud) asp.net-mvc ×5
ninject ×5
c# ×4
.net ×1
asp.net ×1
attributes ×1
autofac ×1
filter ×1
ninject-2 ×1