微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

渲染 RazorPage,路由参数为字符串

如何解决渲染 RazorPage,路由参数为字符串

我使用以下代码将 ASP.NET Core RazorPages 呈现为字符串:

public class RazorPagetoStringRenderer : IRazorPagetoStringRenderer
{
    private readonly IRazorViewEngine razorViewEngine;
    private readonly ITempDataProvider tempDataProvider;
    private readonly IHttpContextAccessor httpContext;
    private readonly IActionContextAccessor actionContext;
    private readonly IRazorPageActivator activator;

    public RazorPagetoStringRenderer(IRazorViewEngine razorViewEngine,ITempDataProvider tempDataProvider,IHttpContextAccessor httpContext,IActionContextAccessor actionContext,IRazorPageActivator activator)
    {
        this.razorViewEngine = razorViewEngine;
        this.tempDataProvider = tempDataProvider;
        this.httpContext = httpContext;
        this.actionContext = actionContext;
        this.activator = activator;
    }

    public async Task<string> RenderToStringAsync<T>(string pageName,T model) where T : PageModel
    {
        var context = new ActionContext(
            httpContext.HttpContext,httpContext.HttpContext.GetRouteData(),actionContext.ActionContext.ActionDescriptor
        );

        using (var sw = new StringWriter())
        {
            var result = razorViewEngine.GetPage(null,pageName);

            if (result.Page == null)
                throw new ArgumentNullException($"The page {pageName} cannot be found.");

            var view = new RazorView(razorViewEngine,activator,new List<IRazorPage>(),result.Page,HtmlEncoder.Default,new DiagnosticListener("VieWrenderService"));

            var viewContext = new ViewContext(
                context,view,new ViewDataDictionary<T>(new EmptyModelMetadataProvider(),new ModelStateDictionary())
                {
                    Model = model
                },new TempDataDictionary(
                    httpContext.HttpContext,tempDataProvider
                ),sw,new HtmlHelperOptions()
            );

            var page = (Page) result.Page;
            page.PageContext = new PageContext(actionContext.ActionContext)
            {
                ViewData = viewContext.ViewData
            };
            page.ViewContext = viewContext;

            activator.Activate(page,viewContext);
            await view.RenderAsync(viewContext);

            return sw.ToString();
        }
    }
}

当我这样称呼它时效果很好:

private async Task SendEmail(int orderId)
    {
        emailModel = new InvoiceEmailModel{InvoiceNumber = orderId};
        string htmlBody = await razorPagetoStringRenderer.RenderToStringAsync("/Areas/Email/Pages/InvoiceEmail.cshtml",emailModel);
        
        await emailSender.SendEmailAsync(UserEmail,$"Order #{orderId} Placed",htmlBody);
    }

但是,如果我通过将 InvoiceEmail.cshtml 中的第一行设置为需要参数来更改我的页面

@page "{orderId:int?}"

然后我将 InvoiceEmailModel PageModel 更改为有一个名为的新方法

public IActionResult OnGet(int orderId)

当我像这样从浏览器访问它时它也有效:localhost:5000/Email/InvoiceEmail?orderId=5。这仅在我在 Startup.cs MapControllers() 中注释掉并将其替换为 MapRazorPages() 时才有效 - 两者似乎都不起作用。

在任何情况下,如果我删除地图 razor 页面,只留下地图控制器并尝试访问 razor 页面,每当我尝试访问 Model 属性时,都会在 Page InvoiceEmail.cshtml 中收到 NullReferenceException 并且 OnGet 方法将不会执行.

我尝试像这样设置 ModelStateDictionary:

var modelState = new ModelStateDictionary();
modelState.SetModelValue("orderId",5,"5");

然后在 ActionContext 中使用它:

var context = new ActionContext(
            httpContext.HttpContext,actionContext.ActionContext.ActionDescriptor,modelState
        );

但这并没有改变输出。有谁知道如何指定 orderId 页面参数并让 OnGet 方法在我从代码运行时也执行?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。