我有几个控制器,我希望每个ActionResult返回相同的viewdata.在这种情况下,我知道我将始终需要基本的产品和员工信息.
现在我一直在做这样的事情:
public ActionResult ProductBacklog(int id) { PopulateGlobalData(id); // do some other things return View(Strongviewmodel); }
其中PopulateGlobalData()定义为:
public void PopulateGlobalData(int id) { ViewData["employeeName"] = employeeRepo.Find(Thread.CurrentPrincipal.Identity.Name).First().FullName; ViewData["productName"] = productRepo.Find(id).First().Name; }
这只是伪代码,所以原谅任何明显的错误,有没有更好的方法来做到这一点?我想让我的控制器继承一个几乎与你在这里看到的相同的类,但我没有看到任何巨大的优势.感觉我正在做的事情是错误的和不可维护的,最好的方法是什么?
解决方法
您可以编写一个自定义
action filter attribute,它将获取此数据并将其存储在使用此属性修饰的每个操作/控制器的视图模型中.
public class GlobalDataInjectorAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { string id = filterContext.HttpContext.Request["id"]; // TODO: use the id and fetch data filterContext.Controller.ViewData["employeeName"] = employeeName; filterContext.Controller.ViewData["productName"] = productName; base.OnActionExecuted(filterContext); } }
当然,使用基本视图模型和强类型视图会更加清晰:
public class GlobalDataInjectorAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { string id = filterContext.HttpContext.Request["id"]; // TODO: use the id and fetch data var model = filterContext.Controller.ViewData.Model as Baseviewmodel; if (model != null) { model.EmployeeName = employeeName; model.ProductName = productName; } base.OnActionExecuted(filterContext); } }
现在剩下的就是用这个属性装饰你的基本控制器:
[GlobalDataInjector] public abstract class BaseController: Controller { }
还有另一个更有趣的解决方案,我个人更喜欢并涉及child actions.在这里,您定义了一个处理此信息检索的控制器:
public class GlobalDataController: Index { private readonly IEmployeesRepository _employeesRepository; private readonly IProductsRepository _productsRepository; public GlobalDataController( IEmployeesRepository employeesRepository,IProductsRepository productsRepository ) { // usual constructor DI stuff _employeesRepository = employeesRepository; _productsRepository = productsRepository; } [ChildActionOnly] public ActionResult Index(int id) { var model = new Myviewmodel { EmployeeName = _employeesRepository.Find(Thread.CurrentPrincipal.Identity.Name).First().FullName,ProductName = _productsRepository.Find(id).First().Name; }; return View(model); } }
现在剩下的就是include这个需要的地方(可能是全球的主页):
<%= Html.Action("Index","GlobalData",new { id = Request["id"] }) %>
或者如果id是路由的一部分:
<%= Html.Action("Index",new { id = ViewContext.RouteData.GetrequiredString("id") }) %>