将 MVC 4 视图中的 html 转换为字符串

Posted

技术标签:

【中文标题】将 MVC 4 视图中的 html 转换为字符串【英文标题】:Get html from MVC 4 view into a string 【发布时间】:2013-08-26 10:50:08 【问题描述】:

我正在尝试使用来自this question 的已接受答案。

看来这正是我正在寻找的,但我有一个问题。我不知道该怎么称呼它。这是我到目前为止所拥有的:

首先我从我提到的解决方案中复制代码:

public string Tohtml(string viewToRender, ViewDataDictionary viewData, ControllerContext controllerContext)

    var result = ViewEngines.Engines.FindView(controllerContext, viewToRender, null);

    StringWriter output;
    using (output = new StringWriter())
    
        var viewContext = new ViewContext(controllerContext, result.View, viewData, controllerContext.Controller.TempData, output);
        result.View.Render(viewContext, output);
        result.ViewEngine.ReleaseView(controllerContext, result.View);
    

    return output.ToString();

这就是我所拥有的:

string viewToRender = "...";
int Data1 = ...;
int Data2 = ...;

System.Web.Mvc.ViewDataDictionary viewData = new System.Web.Mvc.ViewDataDictionary();
viewData.Add("Data1",Data1);
viewData.Add("Data2",Data2);

string html = ToHtml(viewToRender, viewData, ?????)//Here is my problem.

我应该在controllerContext参数中传递什么?

【问题讨论】:

控制器上下文是 MVC 控制器的一个属性。如果您想查看当前控制器的视图,请键入:this.ControllerContext @Oliver 我想在控制器之外调用这个方法。这甚至可能吗?如果是,那么我想以某种方式定义控制器。我该怎么做? 我使用这个助手:public static string RenderPartialViewToString(Controller controller, string viewName, object model) 而不是我只调用controller.ControllerContext。 您是否尝试过为您的 Controller 创建一个新实例,然后将 controllerContext 传递给您的助手? @Oliver 感谢您的信息。如果我创建一个新对象,它可以工作......我是否可以像在 ViewToRender 中那样将它作为字符串传递?我必须使用反射吗? 【参考方案1】:

而不是继承Controller,这意味着你必须记住每次都实现这个,或者从CustomControllerBase继承,这意味着你必须记住每次都继承——只需创建一个扩展方法:

public static class ControllerExtensions

    public static string RenderView(this Controller controller, string viewName, object model)
    
        return RenderView(controller, viewName, new ViewDataDictionary(model));
    

    public static string RenderView(this Controller controller, string viewName, ViewDataDictionary viewData)
    
        var controllerContext = controller.ControllerContext;

        var viewResult = ViewEngines.Engines.FindView(controllerContext, viewName, null);

        StringWriter stringWriter;

        using (stringWriter = new StringWriter())
        
            var viewContext = new ViewContext(
                controllerContext,
                viewResult.View,
                viewData,
                controllerContext.Controller.TempData,
                stringWriter);

            viewResult.View.Render(viewContext, stringWriter);
            viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
        

        return stringWriter.ToString();
    

然后在您的Controller 中,您可以这样调用:

this.RenderView("ViewName", model);

【讨论】:

不错,我喜欢你的方法。谢谢队友 对于任何寻找局部视图的人,请将 FindView 替换为 FindPartialView。 如何设置viewData?对我来说,它是 null,这会引发错误。 是否可以调用返回视图的控制器动作而不是直接调用视图? @FrenkyB 你可以插入 controllerContext.Controller.ViewData 而不是 viewData【参考方案2】:

您可以创建一个明显扩展控制器的基本控制器并在基本控制器中使用上述功能,并且扩展此基本控制器的其他控制器将能够使用它。 但是必须将 ControllerContext 用作

Request.RequestContext

因此你的 BaseController 会是这样的

public class BaseController: Controller

//your function here

你的 ToHtml() 函数将是

protected virtual string ToHtml(string viewToRender, ViewDataDictionary viewData )

   var controllerContext=Request.RequestContext;
   var result = ViewEngines.Engines.FindView(controllerContext, viewToRender, null);

   StringWriter output;
   using (output = new StringWriter())
   
      var viewContext = new ViewContext(controllerContext, result.View, viewData, controllerContext.Controller.TempData, output);
      result.View.Render(viewContext, output);
      result.ViewEngine.ReleaseView(controllerContext, result.View);
   

   return output.ToString();

关于使用基本控制器

public class MyController: BaseController

//ToHtml(...);

【讨论】:

谢谢!你知道,我如何将Model 对象添加到渲染视图? 我找到了:) ViewData.Model = obj;. 在视图数据中发送什么?我没听懂。 @CodeRider 您可以从控制器发送 ViewData 中的任何对象、模型、原始值并在视图中获取其值。确保使用 SAME 键来设置和获取值,否则会发生 Null Exception。 可以指定控制器吗?假设我从“控制器 1”发出请求,但需要从“控制器 2”检索动作/结果。 (并且两个控制器都继承了基本控制器)这可能吗?【参考方案3】:

这几乎是dav_i's post 的副本,除了你有一个强类型化的模型并且还能够生成部分视图:

而不是继承Controller,这意味着你必须记住每次都实现这个,或者从CustomControllerBase继承,这意味着你必须记住每次都继承——只需创建一个扩展方法:

public static class ControllerExtensions

    public static string RenderView<TModel>(this Controller controller, string viewName, TModel model, bool partial = false)
    
        var controllerContext = controller.ControllerContext;
        controllerContext.Controller.ViewData.Model = model;

        // To be or not to be (partial)
        var viewResult = partial ? ViewEngines.Engines.FindPartialView(controllerContext, viewName) : ViewEngines.Engines.FindView(controllerContext, viewName, null);

        StringWriter stringWriter;

        using (stringWriter = new StringWriter())
        
            var viewContext = new ViewContext(
                controllerContext,
                viewResult.View,
                controllerContext.Controller.ViewData,
                controllerContext.Controller.TempData,
                stringWriter);

            viewResult.View.Render(viewContext, stringWriter);
            viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
        

        return stringWriter.ToString();
    

然后在您的Controller 中,您可以这样调用(查看完整视图):

this.RenderView("ViewName", model);

这意味着您还将获得 doctype 和 HTML 元素等。对于部分视图使用:

this.RenderView("ViewName", model, true);

【讨论】:

以上是关于将 MVC 4 视图中的 html 转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET MVC 中的字符串获取 Html 代码

Python之struct

带有实体框架和 SQL Server 数据库的 ASP.NET MVC - 图像未显示在视图中......错误显示“无法将“字节”转换为“字符串”

怎样将十六进制代码转换成文字?

将 MVC 视图呈现为 Parallel.ForEach 中的字符串时的依赖注入问题

为啥 MVC 在将对象传递给视图时倾向于将对象转换为数组?