在ASP.Net Core中创建自定义HTML帮助程序

Due*_*ctu 33 asp.net-core-mvc asp.net-core

我想像在MVC中一样创建自定义HTML Helper,但我找不到如何以正确的方式制作.

我找到了如何创建自定义标记助手但没有HTML助手.

谢谢你的时间!

dou*_*ald 45

对我来说,我认为我的HTML助手没有工作,直到我发现扩展方法现在IHtmlHelper没有HtmlHelper.

所以对于.net核心:

public static IHtmlContent CheckboxListFor<TModel>(this IHtmlHelper<TModel> html,
            Expression<Func<TModel, List<CheckboxListItem>>> expression) ...
Run Code Online (Sandbox Code Playgroud)

而不是.net:

public static HtmlString CheckboxListFor<TModel>(this HtmlHelper<TModel> html,
            Expression<Func<TModel, List<CheckboxListItem>>> expression) ...
Run Code Online (Sandbox Code Playgroud)

编辑:我还将.net核心的返回类型更新为IHtmlContent,因为使用类似于编写HtmlContentBuilder HTML内容并返回返回的更好方法IHtmlContent

  • 没有注意到我的错误中的区别,应该尝试过该接口。谢谢! (2认同)

Aka*_*oni 38

HTML Helper看起来在ASP.NET Core中受支持,正在等待文档:

https://docs.microsoft.com/en-au/aspnet/core/mvc/views/html-helpers

查看ASP.NET Core源代码,它们与旧版本的ASP.NET MVC非常相似:

https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Rendering/HtmlHelperDisplayExtensions.cs


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>";
    }
}
Run Code Online (Sandbox Code Playgroud)

_ViewImports.cshtml(第二行是重要的变化):

@using MyApp
@using MyApp.Helpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Run Code Online (Sandbox Code Playgroud)

MyView.cshtml:

<div>@Html.HelloWorldHTMLString()</div>
<div>@Html.HelloWorldString()</div>
Run Code Online (Sandbox Code Playgroud)

输出:

你好,世界

<strong> Hello World </ strong>


Ren*_*ené 8

这是使用 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);
}
Run Code Online (Sandbox Code Playgroud)


Dbl*_*Dbl 7

好吧,我想这个答案不会被注意到,但这是我使用服务注册想到的:

我希望它能帮助某人。

注册服务:

services.AddTransient<IHtmlHelperFactory, HtmlHelperFactory>();
Run Code Online (Sandbox Code Playgroud)

使用服务:

var helper = HttpContext.RequestServices.GetRequiredService<IHtmlHelperFactory>().Create();
Run Code Online (Sandbox Code Playgroud)

界面:

public interface IHtmlHelperFactory
{
    IHtmlHelper Create();
}
Run Code Online (Sandbox Code Playgroud)

执行:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*Eby 6

我永远无法让 HtmlHelper 扩展方法工作,我总是收到:

“IHtmlHelper”不包含“ MethodName ”的定义,并且找不到接受“IHtmlHelper”类型的第一个参数的扩展方法“ MethodName ”(您是否缺少 using 指令或程序集引用?)

即使我的_ViewImports.cshtml文件中有正确的命名空间。所以我决定现在使用 Razor 页面的能力来支持已经注册为依赖注入的注入服务。例如,我需要将一些值从我的配置文件注入到我的_Layout.cshtml文件中。所以我做了以下事情:

1)定义了一个IConfigurationHelperService接口:

public interface IConfigurationHelperService
{
    string GetApiUrl();
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

3)通过Startup.cs中的ConfigureServices注册注入服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IConfigurationHelperService, ConfigurationHelperService>();
    services.AddMvc();
}
Run Code Online (Sandbox Code Playgroud)

4) 将正确的命名空间作为 using 语句添加到我的_ViewImports.cshtml文件中。

5) 使用@inject关键字来定义它以在_Layout.cshtml文件中使用。

@inject IConfigurationHelperService ConfigHelper
<!DOCTYPE html>
<html>
...
@ConfigHelper.GetApiUrl()
...
</html>
Run Code Online (Sandbox Code Playgroud)

它对我很有用,我可以在更简单的页面上看到更多的用途,在这些页面上定义模型工作量太大。