如果我没有在我的控制器中设置此ViewData键,我得到一个错误,它找不到它。但是,我不想在每个控制器中设置ViewData(我不想在每个控制器中说ViewData [“foo”] = GetFoo();)。
所以,我想在一个基本控制器中设置这个,并让每个控制器继承这个基本控制器。在基本控制器默认构造函数中,我设置了ViewData。我在这里找到了一个类似的方法:http://www.asp.net/learn/MVC/tutorial-13-cs.aspx.到目前为止这么好,这工作…但问题是,这些数据来自数据库某处。
现在当我想要单元测试我的控制器,从基本控制器继承的那些调用其默认构造函数。在默认构造函数中,我初始化我的存储库类以从数据库获取此数据。结果:我的单元测试失败,因为它不能访问数据(我当然不希望他们访问这些数据)。
我也不想传递正确的Repository(或DataContext,无论你命名它)类到每个控制器,反过来它传递给默认控制器,然后我可以模拟我的单元测试。控制器反过来依赖其他存储库类,我最终会传递多个参数到构造函数。为我的感觉太多的工作,或我错了吗?还有其他解决方案吗?
我试过使用StructureMap,但最终我不觉得这将解决我的问题,因为每个控制器仍然必须调用基本构造函数,它将初始化存储库类,所以我不能模拟它。
This是一个类似的问题,但我没有找到满意的答案。我可以用一个整洁的方式解决这个问题,也许使用StructureMap作为解决方案?或者应该我jsut吸它,并传递一个存储库到每个控制器,并再次传递到基本控制器?再次,它感觉像这么多的工作,这么简单的东西。谢谢!
解决方法
第一:
在YourBaseController.OnActionExecuting()或YourBaseController.OnActionExecuted()中设置MasterPage的ViewData:
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"] = ... } }
然后应用到您的控制器:
[DataForMasterPage] public class YourController : YourBaseController { ... }
我认为第二个解决方案是为你的情况。