我想创建自己的自定义HTML Helper,就像ASP.NET MVC中使用的那样,但我还没有找到如何以正确的方式实现它们。
我已经找到了如何创建自定义标记助手而不是HTML助手。如何创建自己的自定义HTML帮助程序?
答案 0 :(得分:36)
HTML Helpers看起来在ASP.NET Core中受支持,正在等待文档:
https://docs.microsoft.com/en-au/aspnet/core/mvc/views/html-helpers
[编辑:]自回答以来,上述页面不再存在。我会说HTML Helpers虽然有效,但在ASP.NET Core中不再“支持”。
查看ASP.NET Core源代码,它们与旧版本的ASP.NET MVC非常相似:
MyHTMLHelpers.cs:
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
namespace MyApp.Helpers
{
public static class MyHTMLHelpers
{
public static IHtmlContent HelloWorldHTMLString(this IHtmlHelper htmlHelper)
=> new HtmlString("<strong>Hello World</strong>");
public static String HelloWorldString(this IHtmlHelper htmlHelper)
=> "<strong>Hello World</strong>";
}
}
_ViewImports.cshtml(第二行是重要的变化):
@using MyApp
@using MyApp.Helpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
MyView.cshtml:
<div>@Html.HelloWorldHTMLString()</div>
<div>@Html.HelloWorldString()</div>
输出:
Hello World
&lt; strong&gt; Hello World&lt; / strong&gt;
答案 1 :(得分:36)
对我而言,我以为我的HTML帮助程序无法正常工作,直到我发现扩展方法现在位于IHtmlHelper
而不是HtmlHelper
。
对于 .net核心:
public static IHtmlContent CheckboxListFor<TModel>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, List<CheckboxListItem>>> expression) ...
而不是 .net :
public static HtmlString CheckboxListFor<TModel>(this HtmlHelper<TModel> html,
Expression<Func<TModel, List<CheckboxListItem>>> expression) ...
编辑:我还将.net核心的返回类型更新为 IHtmlContent ,因为使用类似HtmlContentBuilder
的内容是一种更好的撰写HTML的方式内容和返回返回IHtmlContent
答案 2 :(得分:4)
Danny van der Kraan在blog post here中对此进行了很好的解释。以下答案摘自这篇文章:
ASP.NET Core 1.0 [MVC 6]
附带了一项名为TagHelpers
的新功能。在ASP.Net Core 1.0
中,没有像MVC那样的HTML Helper概念。
什么是TagHelpers?
TagHelpers
可以看作是随着第一个MVC
框架的推出而引入的HTML助手的演变。要提供上下文,您必须想象使用经典ASP,您可以自动生成HTML的唯一方法是通过自定义子例程。之后,ASP.NET带有服务器控件,视图状态是最大的优势,可以模拟桌面应用程序的外观,并帮助桌面开发人员进行转换。但我们都知道当我们试图将方块塞进圆孔时会发生什么。我们不得不面对这样一个事实:Web开发与桌面开发完全不同。为了与正确的Web开发保持一致,使用HTML帮助程序启动了ASP.NET MVC
框架,以自动化HTML输出。但HTML助手从来没有真正凝聚,特别是与前端开发人员和设计人员没有关系。其中一个主要的烦恼是,它使您在视图工作期间从尖括号(HTML, CSS)
切换到C# (Razor syntax)
,这使得体验不必要地令人不舒服。 [MVC 6]
希望通过引入TagHelpers
来解决这个问题以及一些较小的问题。例
HTML助手:
@Html.ActionLink(”Home”, ”Index”, ”Home”)
使用锚TagHelper,它看起来像:
<a asp-action="Index" asp-controller="Home">Home</a>
PS: 请注意,asp-只是一种惯例,但稍后会更多。
在浏览器中呈现的输出对于两者都是相同的:
<a href="/">Home</a>
PS: 如果默认路线未被更改。
有关TagHelpers
click here
答案 3 :(得分:3)
我无法使HtmlHelper扩展方法起作用,我总是收到:
'IHtmlHelper'不包含' MethodName '的定义,并且没有可以找到接受类型'IHtmlHelper'的第一个参数的扩展方法' MethodName '(是你错过了使用指令或程序集引用?)
即使我的 _ViewImports.cshtml 文件中有正确的命名空间。所以我决定使用Razor页面的功能来支持注册依赖注入的注入服务。作为示例,我需要将配置文件中的一些值注入我的 _Layout.cshtml 文件中。所以我做了以下事情:
1)定义了 IConfigurationHelperService 界面:
public interface IConfigurationHelperService
{
string GetApiUrl();
}
2)在ConfigurationHelperSerivce类中定义了该接口的实现(它本身使用依赖注入来获取常规配置类):
public class ConfigurationHelperService : IConfigurationHelperService
{
public ConfigurationHelperService(IConfiguration configuration)
{
Configuration = configuration;
}
private IConfiguration Configuration { get; }
public string GetApiUrl()
{
return GetConfigurationValue(ApiUrl);
}
private string GetConfigurationValue(string key)
{
var value = Configuration[key];
if (value.IsNullOrEmpty()) throw new KeyNotFoundException($"Configruation does not contain an instance of {key}");
return value;
}
}
3)通过Startup.cs中的ConfigureServices注册注入服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigurationHelperService, ConfigurationHelperService>();
services.AddMvc();
}
4)在我的 _ViewImports.cshtml 文件中添加了正确的命名空间作为using语句。
5)使用 @inject 关键字定义它,以便在 _Layout.cshtml 文件中使用。
@inject IConfigurationHelperService ConfigHelper
<!DOCTYPE html>
<html>
...
@ConfigHelper.GetApiUrl()
...
</html>
它对我很有用,我可以在更简单的页面上看到更多用途,其中定义模型的工作量太大。
答案 4 :(得分:3)
要创建自定义 HTML 帮助程序,您必须创建静态类和静态方法。
以下示例是用于提交按钮的自定义 HTML 助手。
namespace TagHelpers.Helpers
{
public static class CustomHtmlHelpers
{
public static IHtmlContent SubmitButton(this IHtmlHelper htmlHelper, string value, string name )
{
string str = "<input type='submit' value ='"+ value +"'name='"+ name +"' />";
return new HtmlString(str);
}
}
}
确保在下面添加 using 语句。
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
要访问页面上任何地方的帮助程序,您需要将命名空间添加到 viewimports.cshtml 文件中
@using TagHelpers.Helpers
现在,您现在可以在要定义按钮的页面上使用它。
<div>
@Html.SubmitButton("Login", "Command")
@Html.SubmitButton("Cancel", "Command")
</div>
答案 5 :(得分:2)
好吧,我猜这个答案不会被注意到,但这是我使用服务注册时想到的:
我希望它能对某人有所帮助。
注册服务:
services.AddTransient<IHtmlHelperFactory, HtmlHelperFactory>();
使用服务:
var helper = HttpContext.RequestServices.GetRequiredService<IHtmlHelperFactory>().Create();
接口:
public interface IHtmlHelperFactory
{
IHtmlHelper Create();
}
实施:
public class HtmlHelperFactory : IHtmlHelperFactory
{
private readonly IHttpContextAccessor _contextAccessor;
public class FakeView : IView
{
/// <inheritdoc />
public Task RenderAsync(ViewContext context)
{
return Task.CompletedTask;
}
/// <inheritdoc />
public string Path { get; } = "View";
}
public HtmlHelperFactory(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
/// <inheritdoc />
public IHtmlHelper Create()
{
var modelMetadataProvider = _contextAccessor.HttpContext.RequestServices.GetRequiredService<IModelMetadataProvider>();
var tempDataProvider = _contextAccessor.HttpContext.RequestServices.GetRequiredService<ITempDataProvider>();
var htmlHelper = _contextAccessor.HttpContext.RequestServices.GetRequiredService<IHtmlHelper>();
var viewContext = new ViewContext(
new ActionContext(_contextAccessor.HttpContext, _contextAccessor.HttpContext.GetRouteData(), new ControllerActionDescriptor()),
new FakeView(),
new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()),
new TempDataDictionary(_contextAccessor.HttpContext, tempDataProvider),
TextWriter.Null,
new HtmlHelperOptions()
);
((IViewContextAware)htmlHelper).Contextualize(viewContext);
return htmlHelper;
}
}
答案 6 :(得分:2)
这是一个基于视图中的Enum值获取Enum名称的示例。枚举类型的自定义HTML帮助器
public static IHtmlContent DisplayEnumFor(this IHtmlHelper htmlHelper, string value, Type enumType)
{
if (htmlHelper == null)
throw new ArgumentNullException(nameof(htmlHelper));
if (value == null)
throw new ArgumentNullException(nameof(value));
if (!enumType.IsEnum)
throw new ArgumentException("Type must be an enumerated type");
foreach (var item in Enum.GetValues(enumType))
if (((int)item).ToString().Equals(value.Trim()))
return new HtmlString(item.ToString());
return new HtmlString(value);
}
答案 7 :(得分:1)
以下是使用TagBuilders的.Net Core 2的示例
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.IO;
public static IHtmlContent HelloWorld(this IHtmlHelper html, string name)
{
var span = new TagBuilder("span");
span.InnerHtml.Append("Hello, " + name + "!");
var br = new TagBuilder("br") {TagRenderMode = TagRenderMode.SelfClosing};
string result;
using (var writer = new StringWriter())
{
span.WriteTo(writer, System.Text.Encodings.Web.HtmlEncoder.Default);
br.WriteTo(writer, System.Text.Encodings.Web.HtmlEncoder.Default);
result = writer.ToString();
}
return new HtmlString(result);
}