问题描述
我在我的 ASP.NET MVC 项目中使用母版页.此母版页需要存在一些 ViewData,它会在每个页面上显示此内容.
I'm using a masterpage in my ASP.NET MVC project. This masterpage expects some ViewData to be present, which displays this on every page.
如果我没有在我的控制器中设置这个 ViewData 键,我会收到一个找不到它的错误.但是,我不想在每个控制器中都设置 ViewData(我不想在每个控制器中都说 ViewData["foo"] = GetFoo();
).
If I don't set this ViewData key in my controllers, I get an error that it can't find it. However, I don't want to set the ViewData in every controller (I don't want to say ViewData["foo"] = GetFoo();
in every controller).
所以,我想在一个基本控制器中设置它,并让每个控制器都从这个基本控制器继承.在基本控制器默认构造函数中,我设置了 ViewData.我在这里找到了类似的方法:http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. 到目前为止一切顺利,这有效……但问题是这些数据来自某个地方的数据库.
So, I was thinking of setting this in a base controller, and have every controller inherit from this base controller. In the base controller default constructur, I set the ViewData. I found a similar approach here: http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. So far so good, this works... but the problem is that this data comes from a database somewhere.
现在,当我想对我的控制器进行单元测试时,从基本控制器继承的控制器调用其默认构造函数.在默认构造函数中,我初始化我的存储库类以从数据库中获取此数据.结果:我的单元测试失败了,因为它无法访问数据(我当然不希望他们希望访问这些数据).
Now when I want to Unit Test my controllers, the ones that inherit from the base controller call its default constructor. In the default constructor, I initialize my repository class to get this data from the database. Result: my unit tests fail, since it can't access the data (and I certainly don't want them to access this data).
我也不想将正确的 Repository(或 DataContext,不管你怎么命名)类传递给每个控制器,然后将它传递给默认控制器,然后我可以用我的单元测试来模拟.控制器反过来依赖于其他存储库类,我最终会向构造函数传递多个参数.我的感觉工作太多了,还是我错了?还有其他解决方案吗?
I also don't want to pass the correct Repository (or DataContext, whatever you name it) class to every controller which in turn pass it to the default controller, which I could then mock with my unit tests. The controllers in turn rely on other repository classes, and I would end up passing multiple parameters to the constructor. Too much work for my feeling, or am I wrong? Is there another solution?
我已经尝试使用 StructureMap,但最后我觉得这不会解决我的问题,因为每个控制器仍然必须调用将初始化存储库类的基构造函数,所以我不能嘲笑它.
I've tried using StructureMap but in the end I didn't feel like that is going to fix my problem, since every controller will still have to call the base constructor which will initialize the repository class, so I can't mock it.
This is a similar question but I find no satisfactory answer was given. Can I solve this in a neat way, maybe using StructureMap as a solution? Or should I jsut suck it and pass a Repository to every controller and pass it again to the base controller? Again, It feels like so much work for something so simple. Thanks!
推荐答案
我看到两个选项:
第一:
在 YourBaseController.OnActionExecuting() 或 YourBaseController.OnActionExecuted() 中为 MasterPage 设置 ViewData:
Set the ViewData for MasterPage in YourBaseController.OnActionExecuting() or YourBaseController.OnActionExecuted():
public class YourBaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Optional: Work only for GET request
if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
return;
// Optional: Do not work with AjaxRequests
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
return;
...
filterContext.Controller.ViewData["foo"] = ...
}
}
第二:
或创建自定义过滤器:
public class DataForMasterPageAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Optional: Work only for GET request
if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
return;
// Optional: Do not work with AjaxRequests
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
return;
...
filterContext.Controller.ViewData["foo"] = ...
}
}
然后应用于您的控制器:
and then apply to your controllers:
[DataForMasterPage]
public class YourController : YourBaseController
{
...
}
我认为第二种解决方案完全适合您的情况.
I think the second solution is exactly for your case.
这篇关于ASP.NET MVC - 在基本控制器中为母版页设置 ViewData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!