【问题标题】:ActionResult to String动作结果到字符串
【发布时间】:2014-11-26 03:59:54
【问题描述】:

我知道有很多类似的问题,但我没有得到我想要的答案。 我想通过执行以下操作将 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,它为给定的产品提供一个带有一些元数据(如销售单位、名称等)和视图的 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();
    }
}

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

【问题讨论】:

  • 你为什么要这样?你能解释一下为什么需要它吗,不清楚
  • 添加了说明,希望对您有所帮助
  • 据我了解,您有时希望获得一个通用的 html 页面,有时是一个 json 对象,它还包含 html 代码作为其属性之一?
  • 绝对是@ViktorArsanov

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


【解决方案1】:

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

【讨论】:

猜你喜欢
  • 2013-09-21
  • 2012-11-20
  • 1970-01-01
  • 2011-07-04
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
相关资源
最近更新 更多