如何将ASP.NET MVC视图渲染成一个字符串?

 2023-02-17    436  

问题描述

我想输出两个不同的视图(作为将作为电子邮件发送的字符串),以及向用户显示的另一个页面.

在ASP.NET MVC Beta中是可能的吗?

如何将ASP.NET MVC视图渲染成一个字符串?

我尝试了多个例子:

1. 在ASP.NET MVC Beta

中渲染到String串

如果我使用这个例子,我会收到”在HTTP之后无法重定向
标题已被发送.”.

2. MVC框架:捕获视图的输出

如果我用它,我似乎无法做出重定向,就像它一样
尝试呈现可能不存在的视图.如果我要退回视图,它
完全搞砸了,看起来并不适合.

有没有人对这些问题有任何想法/解决方案,或者对更好的建议有任何建议?

非常感谢!

下面是一个例子.我想做的是创建 getview foremail方法:

public ActionResult OrderResult(string ref)
{
    //Get the order
    Order order = OrderService.GetOrder(ref);

    //The email helper would do the meat and veg by getting the view as a string
    //Pass the control name (OrderResultEmail) and the model (order)
    string emailView = GetViewForEmail("OrderResultEmail", order);

    //Email the order out
    EmailHelper(order, emailView);
    return View("OrderResult", order);
}

从蒂姆·斯科特(更改和格式化)的接受答案:

public virtual string RenderViewToString(
    ControllerContext controllerContext,
    string viewPath,
    string masterPath,
    ViewDataDictionary viewData,
    TempDataDictionary tempData)
{
    Stream filter = null;
    ViewPage viewPage = new ViewPage();

    //Right, create our view
    viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData);

    //Get the response context, flush it and get the response filter.
    var response = viewPage.ViewContext.HttpContext.Response;
    response.Flush();
    var oldFilter = response.Filter;

    try
    {
        //Put a new filter into the response
        filter = new MemoryStream();
        response.Filter = filter;

        //Now render the view into the memorystream and flush the response
        viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
        response.Flush();

        //Now read the rendered view.
        filter.Position = 0;
        var reader = new StreamReader(filter, response.ContentEncoding);
        return reader.ReadToEnd();
    }
    finally
    {
        //Clean up.
        if (filter != null)
        {
            filter.Dispose();
        }

        //Now replace the response filter
        response.Filter = oldFilter;
    }
}

示例用法

假设来自控制器的呼叫获取订单确认电子邮件,传递网站.

string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);

推荐答案

这是我想出的,它为我工作.我将以下方法添加到我的控制器基类. (您可以始终使这些静态方法在其他地方接受控制器作为我假设的参数)

mvc2 .ascx样式

protected string RenderViewToString<T>(string viewPath, T model) {
  ViewData.Model = model;
  using (var writer = new StringWriter()) {
    var view = new WebFormView(ControllerContext, viewPath);
    var vdd = new ViewDataDictionary<T>(model);
    var viewCxt = new ViewContext(ControllerContext, view, vdd,
                                new TempDataDictionary(), writer);
    viewCxt.View.Render(viewCxt, writer);
    return writer.ToString();
  }
}

razor .cshtml style

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

编辑:添加了剃刀代码.

其他推荐答案

此答案不是在我的路上.这是最初来自 https://stackoverflow.com/a/2759898/27189898/2718354 但在这里我显示了使用方式它与”静态”关键字以使所有控制器常见.

为此,您必须在类文件中制作static类. (假设您的类文件名是Utils.cs)

这个例子是剃刀.

utils.cs

public static class RazorViewToString
{
    public static string RenderRazorViewToString(this 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.GetStringBuilder().ToString();
        }
    }
}

现在您可以通过将Controlle文件中的命名空间作为以下方式添加命名空间来从控制器中调用此类作为参数到控制器.

string result = RazorViewToString.RenderRazorViewToString(this ,"ViewName", model);

作为@Sergey给出的建议,此扩展方法还可以从COTROLLER调用以下,如下所示

string result = this.RenderRazorViewToString("ViewName", model);

我希望这对你有用的代码清洁和整洁.

其他推荐答案

这适用于我:

public virtual string RenderView(ViewContext viewContext)
{
    var response = viewContext.HttpContext.Response;
    response.Flush();
    var oldFilter = response.Filter;
    Stream filter = null;
    try
    {
        filter = new MemoryStream();
        response.Filter = filter;
        viewContext.View.Render(viewContext, viewContext.HttpContext.Response.Output);
        response.Flush();
        filter.Position = 0;
        var reader = new StreamReader(filter, response.ContentEncoding);
        return reader.ReadToEnd();
    }
    finally
    {
        if (filter != null)
        {
            filter.Dispose();
        }
        response.Filter = oldFilter;
    }
}

以上所述是小编给大家介绍的如何将ASP.NET MVC视图渲染成一个字符串?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/34167.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。