C# 以编程方式将Razor页面呈现为HTML字符串 目标 我正试图在后端生成一个HTML字符串 使用HtmlToPDF库将其转换为PDF 我还希望能够在浏览器中轻松查看生成的HTML,以便进行调试/调整。只有当IsDevelopment()时,该页面才会公开 我希望它尽可能简单
我正在使用ASP.NETCore3.1 方法 剃刀页面 我想我应该试试新的剃须刀页面,因为它们的广告宣传非常简单C# 以编程方式将Razor页面呈现为HTML字符串 目标 我正试图在后端生成一个HTML字符串 使用HtmlToPDF库将其转换为PDF 我还希望能够在浏览器中轻松查看生成的HTML,以便进行调试/调整。只有当IsDevelopment()时,该页面才会公开 我希望它尽可能简单,c#,asp.net-core,razor-pages,asp.net-core-3.1,razorengine,C#,Asp.net Core,Razor Pages,Asp.net Core 3.1,Razorengine,我正在使用ASP.NETCore3.1 方法 剃刀页面 我想我应该试试新的剃须刀页面,因为它们的广告宣传非常简单 @page @使用MyProject.Pages.Pdf @模型索引模型 试验 @模型消息 namespace MyProject.Pages.Pdf { 公共类索引模型:PageModel { 私有只读MyDbContext\u context; 公共索引模型(MyDbContext上下文) { _上下文=上下文; } 公共字符串消息{get;private set;}=“C
@page
@使用MyProject.Pages.Pdf
@模型索引模型
试验
@模型消息
namespace MyProject.Pages.Pdf
{
公共类索引模型:PageModel
{
私有只读MyDbContext\u context;
公共索引模型(MyDbContext上下文)
{
_上下文=上下文;
}
公共字符串消息{get;private set;}=“C#中的页面模型”;
公共异步任务OnGetAsync()
{
var count=await_context.Foos.CountAsync();
Message+=$“服务器时间为{DateTime.Now},Foo计数为{count}”;
返回页();
}
}
}
这在浏览器中工作-耶
呈现并获取HTML字符串
我发现它似乎做了我想要的
但问题就从这里开始:(
问题
首先,我觉得很奇怪,当你通过\u razorViewEngine.FindPage
查找页面时,它不知道如何填充ViewContext
或Model
。我认为IndexModel
的工作就是填充这些页面。我希望有可能向ASP.NET索要IndexModel
页面就是这样
无论如何……下一个问题。为了呈现页面,我必须手动创建一个ViewContext
,我必须为它提供一个模型
。但是页面就是模型,因为它是一个页面,所以它不是一个简单的ViewModel。它依赖于DI,需要OnGetAsync()
将被执行以填充模型。这几乎是第22条军规
我还尝试通过\u razorViewEngine.FindView
获取视图而不是页面,但这也需要一个模型,所以我们回到了第22条军规
另一个问题。调试/调整页面的目的是轻松查看生成的内容。但是如果我必须在索引模型
之外创建模型
,那么它就不再代表某个服务中实际生成的内容
所有这些都让我想知道我是否走对了路。或者我遗漏了什么吗?请参考以下步骤来渲染字符串的局部视图:
public interface IRazorPartialToStringRenderer
{
Task<string> RenderPartialToStringAsync<TModel>(string partialName, TModel model);
}
public class ContactModel : PageModel
{
private readonly IRazorPartialToStringRenderer _renderer;
public ContactModel(IRazorPartialToStringRenderer renderer)
{
_renderer = renderer;
}
public void OnGet()
{
}
[BindProperty]
public ContactForm ContactForm { get; set; }
[TempData]
public string PostResult { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var body = await _renderer.RenderPartialToStringAsync("_ContactEmailPartial", ContactForm); //transfer model to the partial view, and then render the Partial view to string.
PostResult = "Check your specified pickup directory";
return RedirectToPage();
}
}
public class ContactForm
{
public string Email { get; set; }
public string Message { get; set; }
public string Name { get; set; }
public string Subject { get; set; }
public Priority Priority { get; set; }
}
public enum Priority
{
Low, Medium, High
}
公共类联系人模型:页面模型
{
专用只读IRazorPartialToStringRenderer\u渲染器;
公共联系人模型(IRazorPartialToStringRenderer)
{
_渲染器=渲染器;
}
公共互联网
{
}
[BindProperty]
公共联系人表单联系人表单{get;set;}
[临时数据]
公共字符串PostResult{get;set;}
公共异步任务OnPostAsync()
{
var body=wait _renderer.RenderPartialToStringAsync(“_ContactEmailPartial”,ContactForm);//将模型传输到局部视图,然后将局部视图渲染为字符串。
PostResult=“检查指定的收货目录”;
返回重定向Topage();
}
}
公开课联络表格
{
公共字符串电子邮件{get;set;}
公共字符串消息{get;set;}
公共字符串名称{get;set;}
公共字符串主题{get;set;}
公共优先级{get;set;}
}
公共枚举优先级
{
低、中、高
}
更多详细步骤,请查看此博客。我成功破解了它!毕竟我走错了路…解决方案是使用
视图组件。
。但它仍然很时髦
多亏了
- 还有很多
名称空间MyProject.ViewComponents
{
公共类MyViewComponent:ViewComponent
{
私有只读MyDbContext\u context;
公共MyViewComponent(MyDbContext上下文)
{
_上下文=上下文;
}
公共异步任务InvokeAsync()
{
var count=await_context.Foos.CountAsync();
var message=$“服务器时间为{DateTime.Now},Foo计数为{count}”;
返回视图(消息);
}
}
}
并且视图被放置在页面/Shared/Components/My/Default.cshtml
@model string
<h2>Test</h2>
<p>
@Model
</p>
与RouteData
来自控制器
[HttpGet]
公共异步任务Get()
{
var html=await_renderViewComponentService
.RenderViewComponentToStringAsync();
//用html做些什么
返回Ok(新的{html});
}
用FromRoute
[HttpGet(“{id}”)]
公共异步任务Get([FromRoute]int id)
{
var html=await_renderViewComponentService
.RenderViewComponentToStringAsync(id);
//用html做些什么
返回Ok(新的{html});
}
奇怪的
非常不幸的是,注入的IViewComponentThelper
无法开箱即用
所以我们必须做这件非常不直观的事情来让它工作
(\u viewComponentHelper作为IViewContextAware)。上下文化(viewContext);
这导致了一系列奇怪的事情,比如伪ActionContext
和ViewContext
,它们需要TextWriter
,但它没有任何用途!事实上,holeViewContext
根本没有使用。它只需要存在:(
还有空视图
…用于
public class ContactModel : PageModel
{
private readonly IRazorPartialToStringRenderer _renderer;
public ContactModel(IRazorPartialToStringRenderer renderer)
{
_renderer = renderer;
}
public void OnGet()
{
}
[BindProperty]
public ContactForm ContactForm { get; set; }
[TempData]
public string PostResult { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var body = await _renderer.RenderPartialToStringAsync("_ContactEmailPartial", ContactForm); //transfer model to the partial view, and then render the Partial view to string.
PostResult = "Check your specified pickup directory";
return RedirectToPage();
}
}
public class ContactForm
{
public string Email { get; set; }
public string Message { get; set; }
public string Name { get; set; }
public string Subject { get; set; }
public Priority Priority { get; set; }
}
public enum Priority
{
Low, Medium, High
}
@model string
<h2>Test</h2>
<p>
@Model
</p>
@page
@using MyProject.ViewComponents
@await Component.InvokeAsync(typeof(MyViewComponent))
@page "{id}"
@using MyProject.ViewComponents
@await Component.InvokeAsync(typeof(MyViewComponent), RouteData.Values["id"])