将ActionResult转换为字符串

4

我知道有很多类似的问题,但是在任何一个问题中我都没有得到我想要的答案。我想通过做类似以下的事情将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),并将其转换为字符串,但使用控制器方法的所有业务代码创建它(特别是ViewBag的使用)。
编辑:关于为什么我要这样做的澄清
我需要能够在浏览器中呈现产品,因此我创建了我的控制器操作称为ProductDetail,并且运行得非常好。
之后需要具有API,该API提供给定产品的JSON对象以及视图中的一些元数据(例如已售出的单位,名称等)。其中一种选择是发送到视图的链接,仅此而已...但是,视图必须作为客户端要求内联。
为避免代码重复并保持干净,我想调用方法ProductDetail,并捕获HTML Raw响应,将其放入JSON响应中作为String。
我已经看到其他人使用此类方法呈现视图:
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();
    }
}

但是这种方式不会执行控制器逻辑


为什么你想要那样做?你能解释一下为什么需要它吗?它不太清楚。 - Ehsan Sajjad
添加了一个澄清,希望有所帮助。 - Vicenç Gascó
据我理解,您想有时获取普通的HTML页面,有时获取一个JSON对象,该对象将包含HTML代码作为其属性之一? - Viktor Arsanov
绝对的 @ViktorArsanov - Vicenç Gascó
1个回答

8

这里 提供了一个可行的解决方案。

创建新类:

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

原始链接已更改为此链接:http://blog.approache.com/2010/11/render-any-aspnet-mvc-actionresult-to.html。 - stomy
我读了这个内容,但在获取ControllerContext时卡住了。出于调试目的,我想将ActionResult转换为显示的HTML。 - Kevin Burton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接