我确信有多种方法可以做到这一点。我从控制器手动渲染视图,然后将渲染的视图作为 JSON 响应的一部分传回。
这保留了每个实体的责任。视图仍然使用视图引擎定位,并且可以重复使用。除了名称和模型类型之外,控制器对视图知之甚少或一无所知。
手动渲染
public static class RenderHelper
{
public static string PartialView( Controller controller, string viewName, object model )
{
controller.ViewData.Model = model;
using( var sw = new StringWriter() )
{
var viewResult = ViewEngines.Engines.FindPartialView( controller.ControllerContext, viewName );
var viewContext = new ViewContext( controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw );
viewResult.View.Render( viewContext, sw );
viewResult.ViewEngine.ReleaseView( controller.ControllerContext, viewResult.View );
return sw.ToString();
}
}
}
在您的操作方法中:
object model = null; // whatever you want
var obj = new {
someOtherProperty = "hello",
view = RenderHelper.PartialView( this, "_PartialName", model )
};
return Json( obj );
请注意,我返回的是匿名类型。你可以返回任何你想要的(可序列化的)类型,只要它有一个用于渲染视图的字符串属性。
测试
测试使用手动渲染的动作需要稍作修改。这是由于渲染视图比在 MVC 管道中渲染的要早一些。
手动渲染
- 输入动作方法
- 显式渲染视图 <-- 这将使测试调用操作变得困难
- 退出动作方法
自动渲染
- 输入动作方法
- 创建视图结果
- 退出动作方法
- 处理视图结果(从而渲染视图)
换句话说,我们的手动渲染过程启动了许多其他难以测试的操作(例如与构建管理器交互以编译视图)。
假设您希望测试操作方法而不是视图的实际内容,您可以检查代码是否在托管环境中执行。
public static string PartialView( Controller controller, string viewName, object model )
{
// returns false from a VS 2013 unit test, true from IIS
if( !HostingEnvironment.IsHosted )
{
// return whatever you want here
return string.Empty;
}
// continue as usual
}
检查HostingEnvironment.IsHosted
成本低(实际上,它只是一个空检查)。