在我的ASP.NET MVC网站的区域中执行全局视图数据的最佳方法? [英] Best way to do global viewdata in an area of my ASP.NET MVC site?
问题描述
我有几个控制器,我希望每个ActionResult返回相同的视图数据.在这种情况下,我知道我将永远需要基本的产品和员工信息.
I have an several controllers where I want every ActionResult to return the same viewdata. In this case, I know I will always need basic product and employee information.
现在我正在做这样的事情:
Right now I've been doing something like this:
public ActionResult ProductBacklog(int id) {
PopulateGlobalData(id);
// do some other things
return View(StrongViewModel);
}
其中PopulateGlobalData()定义为:
Where PopulateGlobalData() is defined as:
public void PopulateGlobalData(int id) {
ViewData["employeeName"] = employeeRepo.Find(Thread.CurrentPrincipal.Identity.Name).First().FullName;
ViewData["productName"] = productRepo.Find(id).First().Name;
}
这只是伪代码,因此可以原谅任何明显的错误,是否有更好的方法来做到这一点?我想到让我的控制器继承一个类,该类几乎可以执行与您在此处看到的相同的操作,但是我没有看到任何好处.感觉我在做的事是错误的并且难以维护,解决这个问题的最佳方法是什么?
This is just pseudo-code so forgive any obvious errors, is there a better way to be doing this? I thought of having my controller inherit a class that pretty much does the same thing you see here, but I didn't see any great advantages to that. It feels like what I'm doing is wrong and unmaintable, what's the best way to go about this?
推荐答案
You could write a custom action filter attribute which will fetch this data and store it in the view model on each action/controller decorated with this 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);
}
}
当然,使用基本视图模型和强类型视图会更加干净:
Of course it would much cleaner to use a base view model and strongly typed views:
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);
}
}
现在剩下的就是用此属性装饰基本控制器了:
Now all that's left is to is to decorate your base controller with this attribute:
[GlobalDataInjector]
public abstract class BaseController: Controller
{ }
我个人更喜欢另一个有趣的解决方案,它涉及到子动作.在这里,您定义一个控制器来处理此信息的检索:
There's another more interesting solution which I personally prefer and which involves child actions. Here you define a controller which handles the retrieval of this information:
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);
}
}
现在剩下的就是包括,只要需要(如果是全局的,则可能是母版页):
And now all that's left is to include this wherever needed (probably the master page if global):
<%= Html.Action("Index", "GlobalData", new { id = Request["id"] }) %>
或如果ID是路线的一部分:
or if the id is part of the routes:
<%= Html.Action("Index", "GlobalData",
new { id = ViewContext.RouteData.GetRequiredString("id") }) %>
这篇关于在我的ASP.NET MVC网站的区域中执行全局视图数据的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!