web-dev-qa-db-fra.com

Créer une assistance HTML personnalisée dans ASP.Net Core

Je souhaite créer mon propre assistant HTML personnalisé, similaire à ceux utilisés dans ASP.NET MVC, mais je n'ai pas trouvé le moyen de les implémenter correctement.

J'ai trouvé comment créer des assistants de balises personnalisés, mais pas des assistants HTML. Comment créer mes propres assistants HTML personnalisés?

31
Duefectu

Pour moi, je pensais que mes assistants HTML ne fonctionnaient pas tant que je n'avais pas remarqué que la méthode d'extension était maintenant sur IHtmlHelper pas HtmlHelper.

Donc pour . Net net:

public static IHtmlContent CheckboxListFor<TModel>(this IHtmlHelper<TModel> html,
            Expression<Func<TModel, List<CheckboxListItem>>> expression) ...

Au lieu de pour . Net:

public static HtmlString CheckboxListFor<TModel>(this HtmlHelper<TModel> html,
            Expression<Func<TModel, List<CheckboxListItem>>> expression) ...

EDIT: J'ai également mis à jour le type de retour pour .net core afin qu'il soit IHtmlContent comme utiliser quelque chose comme HtmlContentBuilder est un moyen plus agréable de composer du contenu HTML et retournant qui retourne IHtmlContent

41
dougajmcdonald

Les assistants HTML semblent être pris en charge dans ASP.NET Core et attendent la documentation:

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

[Edit:] Depuis la réponse, la page ci-dessus n'existe plus. Je dirais que les assistants HTML, bien qu'ils fonctionnent, ne sont plus "pris en charge" dans ASP.NET Core.

En ce qui concerne le code source ASP.NET, leur fonctionnement est assez similaire à celui des versions antérieures d’ASP.NET MVC:

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


Exemple

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 (la deuxième ligne est le changement important):

@using MyApp
@using MyApp.Helpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

MyView.cshtml:

<div>@Html.HelloWorldHTMLString()</div>
<div>@Html.HelloWorldString()</div>

Les sorties:

Bonjour tout le monde

<strong> Bonjour tout le monde </ strong>

36
Akaoni

Cela a été bien expliqué par Danny van der Kraan dans son article de blog ici . La réponse ci-dessous est un extrait de ce post:

ASP.NET Core 1.0 [MVC 6] Est livré avec une nouvelle fonctionnalité intéressante appelée TagHelpers. Dans ASP.Net Core 1.0, Il n'y a pas de concept de HTML Helper comme dans MVC.

Que sont les TagHelpers?

TagHelpers peut être vu comme l'évolution des helpers HTML introduits avec le lancement du premier framework MVC. Pour fournir un contexte, vous devez imaginer qu'avec classic ASP, le seul moyen d'automatiser la génération de HTML est d'utiliser des sous-routines personnalisées. Après cela, ASP.NET est venu avec des contrôles serveur, avec les états d'affichage les plus importants. de plus, pour simuler l’apparence des applications de bureau et faciliter la transition des développeurs, mais nous savons tous ce qui se passe lorsque nous essayons d’encombrer des carrés. Nous avons dû faire face au fait que le développement Web n’est en rien un ordinateur de bureau. Pour être en phase avec le développement web approprié, le framework ASP.NET MVC a été lancé avec des assistants HTML pour automatiser la sortie HTML, mais les assistants HTML ne se sont jamais vraiment gélifiés, en particulier les développeurs et les concepteurs frontaux. Le principal problème, c'est que cela vous a fait passer beaucoup de crochets (HTML, CSS) à C# (Razor syntax) pendant le travail sur les vues, ce qui a rendu l'expérience inutilement inconfortable. [MVC 6] veut résoudre le problème. ceci et quelques petits problèmes en introduisant TagHelpers. Exemple H Aide LML:

@Html.ActionLink(”Home”, ”Index”, ”Home”)

Avec l'ancre TagHelper, cela ressemblerait à:

<a asp-action="Index" asp-controller="Home">Home</a>

PS: Veuillez noter que asp- n'est qu'une convention, mais nous en parlerons plus tard.

La sortie rendue dans le navigateur est la même pour les deux:

<a href="/">Home</a>

PS: Sous réserve que la route par défaut n'ait pas été modifiée.

Pour plus d'informations sur TagHelperscliquez ici

4

Je n'ai jamais réussi à faire fonctionner les méthodes d'extension HtmlHelper, j'ai toujours reçu:

'IHtmlHelper' ne contient pas de définition pour 'MethodName' et aucune méthode d'extension 'MethodName' acceptant un premier argument de type 'IHtmlHelper'. utilisant une directive ou une référence d'assemblée?)

Même si j'avais le nom de l'espace approprié dans mon fichier _ ViewImports.cshtml. J'ai donc décidé d'utiliser la capacité des pages Razor pour prendre en charge les services d'injection enregistrés pour l'injection de dépendance. A titre d'exemple, j'ai besoin d'injecter certaines valeurs de mon fichier de configuration dans mon fichier _ Layout.cshtml. Alors j'ai fait ce qui suit:

1) Défini une IConfigurationHelperService interface:

public interface IConfigurationHelperService
{
    string GetApiUrl();
}

2) Défini une implémentation de cette interface dans une classe ConfigurationHelperSerivce (qui utilise elle-même l'injection de dépendance pour obtenir la classe de configuration standard):

 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) Enregistré le service pour l'injection via ConfigureServices dans Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IConfigurationHelperService, ConfigurationHelperService>();
    services.AddMvc();
}

4) Ajout de l’espace de nom approprié en tant qu’instruction using dans mon fichier _ ViewImports.cshtml.

5) Utilisez le mot clé @ inject pour le définir et l'utiliser dans le fichier _ Layout.cshtml.

@inject IConfigurationHelperService ConfigHelper
<!DOCTYPE html>
<html>
...
@ConfigHelper.GetApiUrl()
...
</html>

Cela a très bien fonctionné pour moi et je peux voir beaucoup plus d'utilisations de ce type sur des pages plus simples où la définition de modèles demanderait trop de travail.

4
James Eby

Eh bien, je suppose que cette réponse ne sera pas remarquée, mais voici ce que j’ai proposé d’utiliser les enregistrements de service:

J'espère que ça aide quelqu'un.

enregistrer le service:

services.AddTransient<IHtmlHelperFactory, HtmlHelperFactory>();

tilisez le service:

var helper = HttpContext.RequestServices.GetRequiredService<IHtmlHelperFactory>().Create();

Interface:

public interface IHtmlHelperFactory
{
    IHtmlHelper Create();
}

mise en œuvre:

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;
    }
}
2
Dbl

Voici un exemple pour .Net Core 2 utilisant 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);
}
1
René