ASP.NET Core 将包含部分视图的视图渲染为字符串

时间:2021-07-19 07:31:10

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

我正在努力渲染一个在视图内部有部分的视图。

视图确实被渲染为字符串,但视图内部的部分根本没有被渲染。

这是我对字符串实用程序代码的看法:

public static class EmailUtility
    {
        public static async Task<string> RenderPartialViewToString(this Controller controller, string viewName, object model)
        {
            controller.ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
                ViewEngineResult viewEngineResult = GetViewEngineResult(controller, viewName, false, viewEngine);

                if (!viewEngineResult.Success)
                {
                    return $"A view with the name {viewName} could not be found";
                }

                ViewContext viewContext = new ViewContext(
                    controller.ControllerContext,
                    viewEngineResult.View,
                    controller.ViewData,
                    controller.TempData,
                    sw,
                    new HtmlHelperOptions()
                );

                await viewEngineResult.View.RenderAsync(viewContext);

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

        private static ViewEngineResult GetViewEngineResult(Controller controller, string viewName, bool isPartial, IViewEngine viewEngine)
        {
            if (viewName.StartsWith("~/"))
            {
                var hostingEnv = controller.HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)) as IWebHostEnvironment;
                return viewEngine.GetView(hostingEnv.WebRootPath, viewName, !isPartial);
            }
            else
            {
                return viewEngine.FindView(controller.ControllerContext, viewName, !isPartial);
            }
        }
    }

这是我在控制器中调用方法的方式:

string html = await this.RenderPartialViewToString("~/Views/Shared/MailerLayoutMaster.cshtml", model);

这是 MailerLayoutMaster.cshtml:

@model Model

@{ 
    Layout = null;
}

<!DOCTYPE html>
<html>
    <head>

    </head>
    <body>
        @{ 
            switch ((int) Model.EmailType)
            {
                case (int) EmailTypeEnum.ContactUsSubmitted:
                    await Html.PartialAsync("../Shared/MailTemplates/EmailPartial.cshtml", Model);
                    break;
                default:
                    
                    break;
            }
        }
    </body>
</html>

这是我的 EmailPartial.cshtml

@model Model

<table>
    <tr>
        <td>Name: <b>@Model.Name</b></td>
    </tr>
    <tr>
        <td>Surname: <b>@Model.Surname</b></td>
    </tr>
    <tr>
        <td>Email: <b>@Model.Email</b></td>
    </tr>
    <tr>
        <td>Number: <b>@Model.Phone</b></td>
    </tr>
</table>

这是我得到的字符串:

<!DOCTYPE html>
<html lang="en-ZA">
    <head>

    </head>
    <body>

    </body>
</html>

如果有帮助,这是我的项目结构:

Controllers
    Controller.cs
Utilities
    ViewToStringUtil.cs
Views
    Shared
        MailTemplates
            EmailPartial.cshtml
        MailerLayoutMaster.cshtml

2 个答案:

答案 0 :(得分:0)

我认为这是因为您没有以正确的方式调用局部视图。不需要使用 .cshtml 扩展来调用局部视图。更新您的代码,如下所示:-

string html = await this.RenderPartialViewToString("~/Views/Shared/MailerLayoutMaster", model);

 switch ((int) Model.EmailType)
            {
                case (int) EmailTypeEnum.ContactUsSubmitted:
                    await Html.PartialAsync("../Shared/MailTemplates/EmailPartial", Model);
                    break;

//clarify code

此外,您可以根据文件夹结构尝试不使用完整路径,只需使用部分视图名称。您可以检查此过程是否有效。

string html = await this.RenderPartialViewToString("PartialViewName", model);

答案 1 :(得分:0)

解决方案非常简单。

我需要的只是一个 @ 之前

await Html.PartialAsync("../Shared/MailTemplates/EmailPartial.cshtml", Model);

应该是:

@await Html.PartialAsync("../Shared/MailTemplates/EmailPartial.cshtml", Model);
相关问题