我在ActionResult上编写了一个扩展方法,用于单元测试,它将断言ViewName返回的是否是预期的。这是我到目前为止的代码:
public static void AssertViewWasReturned(this ActionResult result, string viewName)
{
string actualViewName;
if (result is ViewResult)
actualViewName = (result as ViewResult).ViewName;
else if (result is PartialViewResult)
actualViewName = (result as PartialViewResult).ViewName;
else
throw new InvalidOperationException("Results of type " + result.GetType() + " don't have a ViewName");
Assert.AreEqual(viewName, actualViewName, string.Format("Expected a View named{0}, got a View named {1}", viewName, actualViewName));
}
这种方法很好,除非控制器在没有指定名称的情况下返回视图 - 在这种情况下result.ViewName
是一个空字符串。
所以,我的问题是 - 从ViewResult对象那里告诉我ViewName的名称是什么,ViewName是一个空字符串吗?
答案 0 :(得分:6)
如果未通过MVC管道调用您的控制器方法,则不会向Controller.ViewData
字典添加其他信息(我假设它会以某种方式提供“操作”-key,但无法确认)。但是,由于您在路由框架的上下文“外部”使用控制器,因此无法知道被调用的方法。
所以答案就是“不”。如果未指定视图的名称,则无法从操作返回的ViewResult中确定它。至少不是你的控制器的测试方式(顺便说一句,这完全没问题)。
答案 1 :(得分:4)
对于它的价值 - 我已经修改了我的测试我的扩展方法(包含J. Tihon的反馈):
public static void AssertViewWasReturned(this ActionResult result, string viewName, string defaultViewName)
{
Assert.IsInstanceOf<ViewResultBase>(result, "Result is not an instance of ViewResultBase");
var viewResult = (ViewResultBase)result;
var actualViewName = viewResult.ViewName;
if (actualViewName == "")
actualViewName = defaultViewName;
Assert.AreEqual(viewName, actualViewName, string.Format("Expected a View named{0}, got a View named {1}", viewName, actualViewName));
}
这意味着我的单元测试可以包含这样的代码:
var result = controller.MyAction();
result.AssertViewWasReturned("ExpectedViewName","MyAction")
它不如我所希望的那样好,因为我需要指定'defaultViewName'(即动作名称),但这是一个合理的比较。
答案 2 :(得分:2)
您可以更新控制器以始终传递所需的视图。
而不是:
public ActionResult Index()
{
return View();
}
请改为:
public ActionResult Index()
{
return View("Index");
}
要么改变你的单位测试代码。
答案 3 :(得分:1)
不确定我是否理解您的问题,但如果调用View()
方法时没有参数,MVC将在名为Controller的目录中查找具有调用操作方法名称的View(不带“Controller”后缀添加到名称上。)
例如,这个动作:
public class UserController : Controller
{
public ActionResult SomeAction()
{
// some code here
return View();
}
}
因为这是一个空的View()
调用,MVC将查找路径和文件名为~\Views\User\SomeAction.cshtml
的视图。
这会回答你的问题吗?
答案 4 :(得分:1)
您必须在返回时调用您的视图名称。
前:
Public ActionResult Index(){
// your code
Return View("YourViewName", DataToSendForView);
}
答案 5 :(得分:0)
您可以覆盖控制器。 OnResultExecuted
方法是控制器生命周期中有可用视图的点。
protected override void OnResultExecuted(ResultExecutedContext ctx)
{
base.OnResultExecuted(ctx);
String ViewPath = ((System.Web.Mvc.BuildManagerCompiledView)((System.Web.Mvc.ViewResultBase)ctx.Result).View).ViewPath.ToString();
}