ActionResult to String

时间:2014-10-01 10:24:01

标签: c# asp.net asp.net-mvc view

我知道有很多类似的问题,但我没有得到任何我想要的答案。 我希望通过执行类似的操作将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();
    }
}

但是那样不会执行控制器逻辑

1 个答案:

答案 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);
}