我知道有很多类似的问题,但我没有得到任何我想要的答案。 我希望通过执行类似的操作将ActionResult转换为String:
public ActionResult ProductDetail(int id)
{
// ... lots of operations that include usage of ViewBag and a Model ...
return View(product);
}
要向客户端显示产品页面,但我希望能够通过JSON发送它,例如:
public JsonResult ProductDetailJSON(int id)
{
// ... lots of operations that include usage of ViewBag and a Model ...
return Json(new {
html = this.ProductDetail(id).ToString(),
name = ""
// ... more properties
}, JsonRequestBehavior.AllowGet);
}
因此,我将调用控制器操作并获得其响应(ActionResult
,实际上是ViewResult
)并将其转换为String
,但是使用控制器方法的所有业务代码创建它(特别包括ViewBag
用法)。
编辑澄清我为什么要这样做
我需要能够在浏览器中展示产品,因此我创建了名为ProductDetail
的控制器操作,并且工作正常。
之后需要有一个API,为给定的产品提供一个带有一些元数据(如销售单位,名称等)和View的JSON对象。一种选择是发送一个链接到视图,并且全部...但视图必须作为客户端要求内联。
为了避免代码重复并保持代码清洁,我想调用方法ProductDetail
,并捕获HTML Raw响应,将其作为String
放入JSON响应中。
我已经看到其他人用这样的方法呈现视图:
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
但是那样不会执行控制器逻辑。
答案 0 :(得分:6)
Here是一个有效的解决方案。
创建新类:
public class ResponseCapture : IDisposable
{
private readonly HttpResponseBase response;
private readonly TextWriter originalWriter;
private StringWriter localWriter;
public ResponseCapture(HttpResponseBase response)
{
this.response = response;
originalWriter = response.Output;
localWriter = new StringWriter();
response.Output = localWriter;
}
public override string ToString()
{
localWriter.Flush();
return localWriter.ToString();
}
public void Dispose()
{
if (localWriter != null)
{
localWriter.Dispose();
localWriter = null;
response.Output = originalWriter;
}
}
}
public static class ActionResultExtensions
{
public static string Capture(this ActionResult result, ControllerContext controllerContext)
{
using (var it = new ResponseCapture(controllerContext.RequestContext.HttpContext.Response))
{
result.ExecuteResult(controllerContext);
return it.ToString();
}
}
}
你的json方法中的执行此操作:
public JsonResult ProductDetailJSON(int id)
{
// ... lots of operations that include usage of ViewBag and a Model ...
return Json(new {
// ControllerContext - modify it so it accepts Id
html = View("ProductDetail").Capture(ControllerContext),
name = ""
// ... more properties
}, JsonRequestBehavior.AllowGet);
}