如何在ASP.NET核心自定义标记帮助器中使用视图?
我一直在关注这篇关于编写自定义标记帮助程序的Microsoft文章 我看到的每个代码中的元素标记都是用C硬编码的# 示例(取自上述链接)如何在ASP.NET核心自定义标记帮助器中使用视图?,asp.net,asp.net-mvc,asp.net-core,asp.net-core-tag-helpers,Asp.net,Asp.net Mvc,Asp.net Core,Asp.net Core Tag Helpers,我一直在关注这篇关于编写自定义标记帮助程序的Microsoft文章 我看到的每个代码中的元素标记都是用C硬编码的# 示例(取自上述链接) 公共覆盖无效进程(TagHelperContext上下文,TagHelperOutput输出) { output.TagName=“section”; output.Content.SetHtmlContent( $@“版本:{Info.Version} 版权年:{Info.CopyrightYear} 已批准:{Info.Approved} 要显示的标记数:
公共覆盖无效进程(TagHelperContext上下文,TagHelperOutput输出)
{
output.TagName=“section”;
output.Content.SetHtmlContent(
$@“- 版本:{Info.Version}
- 版权年:{Info.CopyrightYear}
- 已批准:{Info.Approved}
- 要显示的标记数:{Info.TagsToShow}
”;
output.TagMode=TagMode.starttagendtag;
}
有没有一种方法可以从cshtml文件加载标记模板,而不是这样做?(类似于加载局部视图)
我的目的是要有单独的cshtml
文件(每个元素类型一个),这样我就可以轻松地设置它们的样式。而且我的C#看起来很干净
谢谢
詹姆斯
我已经实现了类似的东西,但是它需要一个循环的方法,通过创建一个带有依赖注入的自定义ViewRendering服务,并使用它将视图渲染成字符串。我喜欢这种方法,因为它允许我的应用程序在很多事情上使用视图,包括电子邮件模板、TagHelper,以及任何其他需要将视图呈现为字符串以用于代码的情况,同时还允许我将模型传递给视图以获得更多动态元素
定义服务的接口:
公共接口IViewRenderService
{
字符串RenderView(字符串视图名称);
字符串RenderView(字符串视图名称,TModel模型);
}
服务的实施(重要部分):
使用Microsoft.AspNetCore.Http;
使用Microsoft.AspNetCore.Mvc;
使用Microsoft.AspNetCore.Mvc.Abstractions;
使用Microsoft.AspNetCore.Mvc.ModelBinding;
使用Microsoft.AspNetCore.Mvc.Razor;
使用Microsoft.AspNetCore.Mvc.Rendering;
使用Microsoft.AspNetCore.Mvc.ViewFeatures;
使用Microsoft.AspNetCore.Routing;
使用制度;
使用System.IO;
公共类ViewRenderService:IViewRenderService
{
私有只读IRazorViewEngine(u viewEngine);
私有只读ITempDataProvider _tempDataProvider;
私有只读服务器ViceProvider\u服务提供商;
公共ViewRenderService(IRazorViewEngine、ITempDataProvider、tempDataProvider、IServiceProvider服务提供商)
{
_viewEngine=viewEngine;
_tempDataProvider=tempDataProvider;
_服务提供者=服务提供者;
}
公共字符串RenderView(字符串视图名称)
{
var actionContext=GetActionContext();
var viewEngineResult=_viewEngine.FindView(actionContext,viewName,false);
如果(!viewEngineResult.Success)
{
抛出新的InvalidOperationException(string.Format(“找不到视图”{0}',viewName));
}
var view=viewEngineResult.view;
使用(var输出=新的StringWriter())
{
var viewContext=新的viewContext(
行动背景,
看法
新ViewDataDictionary(
metadataProvider:new EmptyModelMetadataProvider(),
modelState:new ModelStateDictionary()),
新数据字典(
actionContext.HttpContext,
_临时数据提供者),
产出,
新的HtmlHelpOptions());
view.RenderAsync(viewContext.GetAwaiter().GetResult();
返回output.ToString();
}
}
公共字符串RenderView(字符串视图名称,TModel模型)
{
var actionContext=GetActionContext();
var viewEngineResult=_viewEngine.FindView(actionContext,viewName,false);
如果(!viewEngineResult.Success)
{
抛出新的InvalidOperationException(string.Format(“找不到视图”{0}',viewName));
}
var view=viewEngineResult.view;
使用(var输出=新的StringWriter())
{
var viewContext=新的viewContext(
行动背景,
看法
新ViewDataDictionary(
metadataProvider:new EmptyModelMetadataProvider(),
modelState:新的ModelStateDictionary())
{
模型
},
新数据字典(
actionContext.HttpContext,
_临时数据提供者),
产出,
新的HtmlHelpOptions());
view.RenderAsync(viewContext.GetAwaiter().GetResult();
返回output.ToString();
}
}
私有ActionContext GetActionContext()
{
var httpContext=new DefaultHttpContext();
httpContext.RequestServices=\u serviceProvider;
返回新的ActionContext(httpContext,new RoutedData(),new ActionDescriptor());
}
}
然后在Startup.cs中
public void配置服务(IServiceCollection服务)
{
...
services.AddTransient();
...
}
最后,您将在这样的代码中使用它(在本例中为控制器):
公共类TestController:Controller
{
私有IViewRenderService viewRenderService;
公共测试控制器(IViewRenderService _viewRenderService)
{
viewRenderService=_viewRenderService;
}
公共异步任务索引()
{
//代码
var stringOfView=viewRenderService.RenderView(“EmailTemplate/EmailConfirmation”);
//将视图作为字符串执行某些操作的代码
返回视图();
}
}
您可以将视图放在视图文件夹中它们自己的文件夹下(在上面的示例中,视图路径是:/Views/EmailTemplate/EmailConfirmation.cshtml)
如果您的视图需要一个模型,您将通过i
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "section";
output.Content.SetHtmlContent(
$@"<ul><li><strong>Version:</strong> {Info.Version}</li>
<li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
<li><strong>Approved:</strong> {Info.Approved}</li>
<li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
output.TagMode = TagMode.StartTagAndEndTag;
}
<!-- Views/Shared/TagHelpers/MyList.cshtml -->
@model YourInfoClass
<ul>
<li><strong>Version:</strong> @Model.Version</li>
<li><strong>Copyright Year:</strong> @Model.CopyrightYear</li>
<li><strong>Approved:</strong> @Model.Approved</li>
<li><strong>Number of tags to show:</strong> @Model.TagsToShow</li>
</ul>
[HtmlTargetElement("mylist")]
public class MyListTagHelper : TagHelper
{
private HtmlHelper _htmlHelper;
private HtmlEncoder _htmlEncoder;
public MyListTagHelper(IHtmlHelper htmlHelper, HtmlEncoder htmlEncoder)
{
_htmlHelper = htmlHelper as HtmlHelper;
_htmlEncoder = htmlEncoder;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "section";
output.TagMode = TagMode.StartTagAndEndTag;
var partial = await _htmlHelper.PartialAsync("TagHelpers/MyList", Info);
var writer = new StringWriter();
partial.WriteTo(writer, _htmlEncoder);
output.Content.SetHtmlContent(writer.ToString());
}
}
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;
namespace UsingCshtmlTemplatesInTagHelpers.TagHelpers
{
public class Holder
{
public string Name { get; set; }
}
public class TemplateRendererTagHelper : TagHelper
{
[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }
private IHtmlHelper _htmlHelper;
public TemplateRendererTagHelper(IHtmlHelper htmlHelper)
{
_htmlHelper = htmlHelper;
}
public override async Task ProcessAsync(TagHelperContext context
, TagHelperOutput output)
{
(_htmlHelper as IViewContextAware).Contextualize(ViewContext);
/*
* Create some data that are going
* to be passed to the view
*/
_htmlHelper.ViewData["Name"] = "Ali";
_htmlHelper.ViewBag.AnotherName = "Kamel";
Holder model = new Holder { Name = "Charles Henry" };
output.TagName = "div";
/*
* model is passed explicitly
* ViewData and ViewBag are passed implicitly
*/
output.Content.SetHtmlContent(await _htmlHelper.PartialAsync("Template", model));
}
}
}