Я хочу создать свой собственный HTML-помощник, как в MVC, но я не нахожу, как сделать правильный путь.
Я нашел, как создавать пользовательские помощники тегов, но не помощники HTML.
Спасибо за ваше время!
Я хочу создать свой собственный HTML-помощник, как в MVC, но я не нахожу, как сделать правильный путь.
Я нашел, как создавать пользовательские помощники тегов, но не помощники HTML.
Спасибо за ваше время!
Для меня я думал, что мои помощники HTML не работают, пока я не заметил, что метод расширения теперь находится на IHtmlHelper
not HtmlHelper
.
Итак, для .net core:
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) ...
EDIT: Я также обновил тип возвращаемого значения для ядра .net как IHtmlContent, поскольку использование чего-то типа HtmlContentBuilder
- это лучший способ составить HTML-контент и возвращающий, который возвращает IHtmlContent
HTML-помощники ищут поддержку в ядре ASP.NET и ждут документации:
https://docs.microsoft.com/en-au/aspnet/core/mvc/views/html-helpers
Глядя на источник 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
<strong> Hello World </strong>
Это было хорошо объяснено Дэнни ван дер Крааном в своем блоге
С помощью привязки TagHelper это будет выглядеть так:
<a asp-action="Index" asp-controller="Home">Home</a>
PS: Обратите внимание, что asp - это просто соглашение, но об этом позже.
Результат, отображаемый в браузере, одинаковый для обоих:
<a href="/">Home</a>
PS: Если маршрут по умолчанию не изменен.
Для получения дополнительной информации о TagHelpers
Мне никогда не удавалось использовать методы расширения HtmlHelper, я всегда получал:
"IHtmlHelper" не содержит определения для " Имя метода" и не может быть найден метод расширения " Имя метода", принимающий первый аргумент типа "IHtmlHelper" ( у вас отсутствует директива using или ссылка на сборку?)
Несмотря на то, что у меня было собственное пространство имен в файле _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) Зарегистрировал сервис для инъекций через ConfigureServices в Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigurationHelperService, ConfigurationHelperService>();
services.AddMvc();
}
4) Добавлено собственное пространство имен в качестве используемого оператора в файл _ViewImports.cshtml.
5) Используется ключевое слово @inject, чтобы определить его для использования в файле _Layout.cshtml.
@inject IConfigurationHelperService ConfigHelper
<!DOCTYPE html>
<html>
...
@ConfigHelper.GetApiUrl()
...
</html>
Это отлично поработало для меня, и я вижу гораздо больше возможностей для этого на более простых страницах, где определение моделей будет слишком большим.
Ну, я думаю, этот ответ не будет замечен, но вот что я придумал с помощью регистрации услуг:
Надеюсь, это поможет кому-то.
Зарегистрируйте услугу:
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;
}
}
Вот пример для.Net Core 2 с помощью TagBuilders
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);
}