使用StructureMap的Asp.Net MVC 5自定义操作过滤器
发布时间:2020-12-16 06:33:24 所属栏目:asp.Net 来源:网络整理
导读:我正在使用structuremap在asp.net mvc custom acitonfilte中遇到问题 在我的“LogAttribute”类中,我有setter依赖注入,它在执行我的customfilterclass的“OnActionExecuted”方法时为null,即“LogAttribute” 我的LogAttribute类代码是 public class LogAttr
我正在使用structuremap在asp.net mvc custom acitonfilte中遇到问题
在我的“LogAttribute”类中,我有setter依赖注入,它在执行我的customfilterclass的“OnActionExecuted”方法时为null,即“LogAttribute” 我的LogAttribute类代码是 public class LogAttribute : ActionFilterAttribute { public ApplicationDbContext Context { get; set; } public string Description { get; set; } public LogAttribute(string description) { Description = description; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var userId = filterContext.HttpContext.User.Identity.GetUserId(); var user = Context.Users.Find(userId); **i am getting error here the Context is coming null here** Context.Logs.Add(new Log(user,filterContext.ActionDescriptor.ActionName,filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,Description ) ); Context.SaveChanges(); } } 我创建了另一个类,我将值传递给setter依赖项属性 public class StructureMapFilterProvider : FilterAttributeFilterProvider { private readonly Func<IContainer> _container; public StructureMapFilterProvider(Func<IContainer> container) { _container = container; } public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext,ActionDescriptor actionDescriptor) { var filters = base.GetFilters(controllerContext,actionDescriptor); var container = _container(); foreach (var filter in filters) { container.BuildUp(filter.Instance); yield return filter; } } } 我的依赖解析器类代码是 public class StructureMapDependencyResolver : IDependencyResolver { private readonly Func<IContainer> _containerFactory; public StructureMapDependencyResolver(Func<IContainer> containerFactory) { _containerFactory = containerFactory; } public object GetService(Type serviceType) { if (serviceType == null) { return null; } var container = _containerFactory(); return serviceType.IsAbstract || serviceType.IsInterface ? container.TryGetInstance(serviceType) : container.GetInstance(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return _containerFactory().GetAllInstances(serviceType).Cast<object>(); } } 我的global.ascx代码是 public class MvcApplication : System.Web.HttpApplication { public IContainer Container { get { return (IContainer)HttpContext.Current.Items["_Container"]; } set { HttpContext.Current.Items["_Container"] = value; } } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); DependencyResolver.SetResolver(new StructureMapDependencyResolver(() => Container ?? ObjectFactory.Container)); ObjectFactory.Configure(cfg => { cfg.Scan(Scan => { Scan.TheCallingAssembly(); Scan.WithDefaultConventions(); Scan.With(new ControllerConfiguration()); }); cfg.For<IFilterProvider>().Use(new StructureMapFilterProvider(() => Container ?? ObjectFactory.Container)); cfg.For<IUserStore<ApplicationUser>>() .Use<UserStore<ApplicationUser>>(); cfg.For<DbContext>() .Use(() => new ApplicationDbContext()); cfg.SetAllProperties(x => x.Matching(p => p.DeclaringType.CanBeCastTo(typeof(ActionFilterAttribute)) && p.DeclaringType.Namespace.StartsWith("TestingSturctureMap") && p.PropertyType.IsPrimitive && p.PropertyType != typeof(string))); }); } public void Application_BeginRequest() { Container = ObjectFactory.Container.GetNestedContainer(); } public void Application_EndRequest() { Container.Dispose(); Container = null; } } 解决方法
我安装了structuremap和StructureMap.MVC5 NuGet包.
这会将DependencyResolution文件夹和StructuremapMvc.cs添加到App_Start文件夹中. 然后我创建了Filters文件夹,并为其添加了一个属性,一个动作过滤器和一个过滤器提供程序类: 我的属性类–LogActionsAttribute – 是最简单的. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple = false)] public class LogActionsAttribute : System.Attribute { } 控制器上的用法: [LogActions] public class HomeController : System.Web.Mvc.Controller { public ActionResult Index() { return View(); } } 现在我需要添加一个动作过滤器来查找此属性并执行某些操作.在我的例子中,记录传入的参数和执行结果. ILog是一个自定义接口,包含此过滤器使用的这两种方法. ControllerLoggerFilter类: public class ControllerLoggerFilter : IActionFilter { private readonly ILog _log; private string _request; public ControllerLoggerFilter(ILog log) { _log = log; } public void OnActionExecuting(ActionExecutingContext filterContext) { if (ApplyBehavior(filterContext)) { ActionExecuting(filterContext); } } public void OnActionExecuted(ActionExecutedContext filterContext) { if (ApplyBehavior(filterContext)) { ActionExecuted(filterContext); } } private void ActionExecuting(ControllerContext c) { if (c == null || c.HttpContext == null) return; _log.LogInput(c.HttpContext.Request); _request = c.HttpContext.Request; } private void ActionExecuted(ControllerContext c) { if (c.HttpContext.Response == null) return; _log.LogOutput(_request,c.HttpContext.Response); } private static bool ApplyBehavior(ActionExecutingContext filterContext) { return filterContext.ActionDescriptor.ControllerDescriptor .GetCustomAttributes(typeof (LogActionsAttribute),false).Any(); } private static bool ApplyBehavior(ActionExecutedContext filterContext) { return filterContext.ActionDescriptor.ControllerDescriptor .GetCustomAttributes(typeof (LogActionsAttribute),false).Any(); } } 我现在不得不告诉MVC这个过滤器需要在管道中.由于它是由structuremap容器构建的,我需要一个自定义的IFilterProvider: public class MvcInjectableFilterProvider : IFilterProvider { private readonly IEnumerable<Filter> _list; public MvcInjectableFilterProvider(IContainer container) { _list = GetContainerFilters(container); } public IEnumerable<Filter> GetFilters(ControllerContext controllerContext,ActionDescriptor actionDescriptor) { return _list; } private static IEnumerable<Filter> GetContainerFilters(IContainer container) { return container.GetAllInstances<IActionFilter>() .Select(instance => new Filter(instance,FilterScope.Action,null)); } } 最后要做的事情:在我的IoC.cs中注册我的课程. public static class IoC { public static IContainer Initialize() { return new Container(c => { c.AddRegistry<DefaultRegistry>(); // added these lines: c.For<ILog>().Use<Log>(); c.For<IActionFilter>().Use<ControllerLoggerFilter>(); c.For<IFilterProvider>().Use<MvcInjectableFilterProvider>(); }); } } 资料来源: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net-mvc – ASP.NET MVC:让API控制器操作同时返回View
- asp.net-mvc – ASP.NET MVC在调用方法时查找调用方法!Mod
- ASP.NET – 提高性能
- asp.net-mvc-3 – 不支持使用相同的DbCompiledModel来针对不
- asp.net – 抛出类型“System.OutOfMemoryException”的异常
- asp.net – Datatable的行计算功能
- asp.net – 视图状态中存储的项目的生命周期是多少?
- asp.net-mvc – 使用Action Filter检查URL中的参数的MVC.停
- 验证 – 想知道为什么DisplayName属性在被覆盖属性的LabelF
- asp.net – 为什么设置为SqlServer时会话超时不起作用?
推荐文章
站长推荐
- asp.net-mvc-2 – 在选择聚合时,如何处理Linq到N
- asp.net-mvc – 在实体框架代码中为同一表定义多
- ASP.NET Web Api中的Swashbuckle被嵌套控制器搞糊
- asp.net-mvc – 寻找第三方CMS与MVC网站集成
- asp.net-mvc-4 – VS2012 RTM缺少.net 4.5和mvc项
- asp.net – 问题设置cookie到期DateTime.Max(999
- asp.net mvc – 如何实现面包屑助手在asp.net mv
- asp.net-mvc – 如何在ASP.NET MVC控制器中读取G
- asp.net – 我可以在MasterPage中使用UpdatePane
- asp.net-mvc – MVC,DbContext和多线程
热点阅读