1

已多次询问将视图渲染到字符串,但是我的问题有所不同。

ViewEngineResult.View一个方法叫做Render(ViewContext, TextWriter)

如果我传入包含我的电子邮件视图的控制器,我的代码可以正常工作,但是如果操作方法源自另一个控制器,那么我需要能够修改 ViewContext 以查看 EmailControllers 视图。

我无法确切地弄清楚该Render方法使用什么属性来确定要查看的视图文件夹。本质上,我希望弄清楚这一点,以便我可以告诉它查看电子邮件视图文件夹。

这是我的代码供参考:

public static string RenderPartialViewToString(Controller controller, string viewName, object model)
    {
        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);

                controller.ViewData.Model = oldModel;
                return sw.GetStringBuilder().ToString();
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

回顾一下,如果我在 Orders 控制器中传递在FindViewOrders 视图文件夹中查找我的视图,我需要告诉它在电子邮件视图文件夹中查找。

4

1 回答 1

1

ViewEngine 查看RouteData以确定.cshtml要加载的文件。特别是controlleraction属性。您可以(并且可能推荐)传递您希望使用的控制器名称,但您可以Email在下面的代码中看到我已经对其进行了硬编码。

public static string RenderPartialViewToString(Controller controller, string viewName, object model)
{
    var oldModel = controller.ViewData.Model;
    controller.ViewData.Model = model;
    try
    {
        using (var sw = new StringWriter())
        {

            controller.RouteData.Values["controller"] = "Email";

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

            controller.ViewData.Model = oldModel;
            return sw.GetStringBuilder().ToString();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

如果你真的想知道更多的东西

Razor 在尝试确定要使用的视图时会查找多个位置。{0}这是动作(或传入视图名称)并且{1}是控制器。

        ViewLocationFormats = new[] { 
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml", 
            "~/Views/Shared/{0}.cshtml", 
            "~/Views/Shared/{0}.vbhtml"
        }; 

和这里一样,除了我们也有{2}哪个是区域。

        AreaViewLocationFormats = new[] {
            "~/Areas/{2}/Views/{1}/{0}.cshtml", 
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml", 
            "~/Areas/{2}/Views/Shared/{0}.vbhtml" 
        };

所有这些参数都来自 RouteData (除非通过参数特别覆盖,例如View("viewname")。它们特别是action,controllerarea。通过修改这些值,您可以更改 MVC 的几种工作方式。包括在选择一个控制器之前确定要使用的控制器。与操作相同和地区。

希望这可以帮助。

于 2012-04-27T15:57:45.373 回答