C# ASP.NET MVC Razor:如何渲染Razor局部视图';在控制器操作中添加HTML

C# ASP.NET MVC Razor:如何渲染Razor局部视图';在控制器操作中添加HTML,c#,asp.net-mvc,razor,C#,Asp.net Mvc,Razor,如何在ASP.NET视图引擎上生成给定部分视图的HTML 但如果在razor部分视图上使用此功能,它将不起作用,因为例外情况是部分视图不是从“UserControl”派生的 如何修复渲染以支持razor局部视图 我需要这个,因为我从这个部分视图生成电子邮件 更新: 失败的代码(@mcl): 更新 protected string RenderPartialViewToString(string viewName, object model) { if (string.IsNullOrEm

如何在ASP.NET视图引擎上生成给定部分视图的HTML

但如果在razor部分视图上使用此功能,它将不起作用,因为例外情况是部分视图不是从“UserControl”派生的

如何修复渲染以支持razor局部视图

我需要这个,因为我从这个部分视图生成电子邮件

更新:

失败的代码(@mcl):

更新

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter()) {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

您还可以使用中的
RenderView控制器扩展
()

然后像这样使用它:

public ActionResult Do() {
var html = this.RenderView("index", theModel);
...
}

它适用于razorweb表单视图引擎

我看到有人想知道如何为另一个控制器执行此操作

在我的例子中,我的所有电子邮件模板都在Views/email文件夹中,但是你可以修改它,将其传递到与视图关联的控制器中

public static string RenderViewToString(Controller controller, string viewName, object model)
    {
        var oldController = controller.RouteData.Values["controller"].ToString();

        if (controller.GetType() != typeof(EmailController))
            controller.RouteData.Values["controller"] = "Email";

        var oldModel = controller.ViewData.Model;
        controller.ViewData.Model = model;
        try
        {
            using (var sw = new StringWriter())
            {
                var viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName,
                                                                           null);

                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                //Cleanup
                controller.ViewData.Model = oldModel;
                controller.RouteData.Values["controller"] = oldController;

                return sw.GetStringBuilder().ToString();
            }
        }
        catch (Exception ex)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

            throw ex;
        }
    }
基本上,这是采取一个控制器,如AccountController,并将其修改为认为它是一个EmailController,以便代码可以查看
视图/Email
文件夹。之所以有必要这样做,是因为
FindView
方法没有将直线路径作为参数,它需要
ControllerContext


呈现字符串后,它会将AccountController返回到其初始状态,以供响应对象使用。

虽然已经给出了足够的答案,但我想提出一个不太详细的解决方案,该解决方案可以在MVC控制器类中不使用可用的帮助器方法的情况下使用。使用名为“RazorEngine”的第三方库,您可以使用.Net文件IO获取razor文件的内容并调用

string html = Razor.Parse(razorViewContentString, modelObject);

获取第三方库。

伟大的代码;小提示:如果您有时不得不绕过更多数据,而不仅仅是viewmodel

 if (model is ViewDataDictionary)
 {
     controller.ViewData = model as ViewDataDictionary;
 } else {
     controller.ViewData.Model = model;
 }

借用@jgauffin answer作为HtmlHelper扩展:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString RenderPartialViewToString(
        this HtmlHelper html, 
        ControllerContext controllerContext, 
        ViewDataDictionary viewData,
        TempDataDictionary tempData,
        string viewName, 
        object model)
    {
        viewData.Model = model;
        string result = String.Empty;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
            ViewContext viewContext = new ViewContext(controllerContext, viewResult.View, viewData, tempData, sw);
            viewResult.View.Render(viewContext, sw);

            result = sw.GetStringBuilder().ToString();
        }

        return MvcHtmlString.Create(result);
    }
}
在razor视图中的用法:

Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model)

是的,这是在视图中渲染局部视图的方式。但是如何在控制器动作中渲染它呢?太好了,现在就是这样!使用Razon和ASP表示法。一个子问题:如何呈现在另一个控制器范围内的视图,然后呈现当前视图?假设它在“EmailController”范围内(电子邮件视图文件夹)?这是一个很好的解决方案。我确实需要电子邮件,并选择使用它。@AmeyKhadatkar:不。jquery是客户端,视图在发送到浏览器之前在服务器端生成。您能显示到目前为止生成异常的代码吗?检查了链接@ChurkNorris是的作者,这是一个商业产品(目前最新版本为2012年3月12日)。(最新版本2011年6月9日)仍然是开源的,但可能不会再开发了。有没有1.9的叉子?@Omu:RenderView无效。请参见@Roland这是一个自定义控制器扩展您尚未完成回答您能否解释使用@Html.Partial(字符串partialViewName、对象模型、ViewDataDictionary viewData)的区别?因为它需要HtmlHelper,有什么好处?
public static class HtmlHelperExtensions
{
    public static MvcHtmlString RenderPartialViewToString(
        this HtmlHelper html, 
        ControllerContext controllerContext, 
        ViewDataDictionary viewData,
        TempDataDictionary tempData,
        string viewName, 
        object model)
    {
        viewData.Model = model;
        string result = String.Empty;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
            ViewContext viewContext = new ViewContext(controllerContext, viewResult.View, viewData, tempData, sw);
            viewResult.View.Render(viewContext, sw);

            result = sw.GetStringBuilder().ToString();
        }

        return MvcHtmlString.Create(result);
    }
}
Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model)