Пользовательский помощник тегов .NET Core не работает

Я создал новый проект веб-приложения ASP.NET Core, теперь для простоты скажем, что его корневое пространство имен - это MyWeb.Mvc, которое также является именем сборки, указанным в свойствах проекта.

В том же проекте веб-приложения я создал папку с названием TagHelpers и добавил в нее такой класс:

namespace MyWeb.Mvc.TagHelpers {
   public abstract class JsonLdBase : TagHelper
   {
      protected string addKeyValue(string key, string value, bool noClosing = true)
      {
         return string.Format("\"{0}\": \"{1}\"{2}{3}", key, value, noClosing ? "," : "", Environment.NewLine);
      }
    }

    public class JsonLdWebsiteTagHelper : JsonLdBase
    {
      public string Name { get; set; }
      public string Alt { get; set; }
      public string Url { get; set; }

      public override void Process(TagHelperContext context, TagHelperOutput output) {
          output.TagName = "script";
          output.TagMode = TagMode.StartTagAndEndTag;
          output.Attributes.SetAttribute("type", new HtmlString("application/ld+json"));
          output.Content.SetContent(
              "{" + Environment.NewLine +
              addKeyValue("@context", "http://schema.org") + 
              addKeyValue("@type", "WebSite") +
              addKeyValue("name", Name) + 
                addKeyValue("alternateName", Alt) +
                addKeyValue("url", Url) +
            "}"
          );
      }
    }

}

Затем в _ViewImports.cshtml у меня есть это:

@using MyWeb.Mvc.TagHelpers
@addTagHelper MyWeb.Mvc.TagHelpers.*, MyWeb.Mvc

А в _Layout.cshtml я использую это так:

<jsonldwebsite name="Panama Vibes" alt="Panama Vibes" url="PanamaVibes.com"/>

Поскольку он был помещен в _Layout.cshtml, он должен отображаться на всех страницах. Но когда я компилирую и запускаю веб-приложение и просматриваю исходный код главной страницы, я вижу, что настраиваемый тег был отображен как обычный тег HTML без обработки TagHelper.

Изначально я думал об использовании пакета NuGet json-ld, но я воздержался, когда увидел, что он не обновлялся с 2016 года и что программист не нашел времени, чтобы задокументировать, как его можно использовать, или привести какие-либо примеры.

ОБНОВЛЕНИЕ №1. Как и было предложено, я явно устанавливаю свойство TagMode. Однако весь вывод становится HTML-кодированным и, следовательно, не проходит проверку JSON + LD.

Теперь я использую HtmlString ("application / json + ld"), и запись типа теперь правильно отображается без кодирования знака "+". Однако я попытался использовать тот же подход для Контента, но там


person Lord of Scripts    schedule 27.04.2017    source источник


Ответы (4)


По умолчанию имя тега на странице razor json-ld-website:

<json-ld-website name="Panama Vibes" alt="Panama Vibes" url="PanamaVibes.com" />

Вы можете изменить имя, используя HtmlTargetElementAttribute:

[HtmlTargetElement("jsonldwebsite")]
public class JsonLdWebsiteTagHelper : JsonLdBase
{
    public string Name { get; set; }
    public string Alt { get; set; }
    public string Url { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "script";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Attributes.SetAttribute("type", "application/ld+json");
        output.Content.SetContent(
            "{" + Environment.NewLine +
            addKeyValue("@context", "http://schema.org") +
            addKeyValue("@type", "WebSite") +
            addKeyValue("name", Name) +
              addKeyValue("alternateName", Alt) +
              addKeyValue("url", Url) +
          "}"
        );
    }
}

Кроме того, вам следует изменить имя тега на script, который не является самозакрывающимся тегом. Это означает, что вы должны использовать output.TagMode = TagMode.StartTagAndEndTag;, чтобы убедиться, что есть закрывающий тег. Таким образом, ваш образец сгенерирует следующий html:

<script type="application/ld&#x2B;json">{&#xD;&#xA;&quot;@context&quot;: &quot;http://schema.org&quot;,&#xD;&#xA;&quot;@type&quot;: &quot;WebSite&quot;,&#xD;&#xA;&quot;name&quot;: &quot;Panama Vibes&quot;,&#xD;&#xA;&quot;alternateName&quot;: &quot;Panama Vibes&quot;,&#xD;&#xA;&quot;url&quot;: &quot;PanamaVibes.com&quot;,&#xD;&#xA;}</script>

ИЗМЕНИТЬ

Все значения закодированы по умолчанию (в целях безопасности). Вы можете написать Raw html, используя метод SetHtmlContent. Для значений атрибутов вам нужно будет предоставить настраиваемый IHtmlContent, который не кодирует значение. Однако любой допустимый синтаксический анализатор HTML должен расшифровывать значение атрибута.

public class JsonLdWebsiteTagHelper : JsonLdBase
{
    public string Name { get; set; }
    public string Alt { get; set; }
    public string Url { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "script";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Attributes.Add(new TagHelperAttribute("type", new HtmlContent("application/ld+json")));
        output.Content.SetHtmlContent(
            "{" + Environment.NewLine +
            addKeyValue("@context", "http://schema.org") +
            addKeyValue("@type", "WebSite") +
            addKeyValue("name", Name) +
              addKeyValue("alternateName", Alt) +
              addKeyValue("url", Url) +
          "}"
        );
    }

    private class HtmlContent : IHtmlContent
    {
        private string _value;
        public HtmlContent(string value)
        {
            _value = value;
        }
        public void WriteTo(TextWriter writer, HtmlEncoder encoder)
        {
            writer.Write(_value);
        }
    }
}
person meziantou    schedule 27.04.2017
comment
это действительно так! Однако почему вывод закодирован? как ld & # 2B; son вместо ld + json и то же самое со всем кодом JSON. Это приводит к неправильной форме всего json + ld и, следовательно, не прохождению инструмента проверки JSON + LD. - person Lord of Scripts; 27.04.2017
comment
Я отредактировал свой ответ примером без кодировки - person meziantou; 27.04.2017

Вы пробовали атрибут HtmlTargetElement?

[HtmlTargetElement("jsonldwebsite")]
person Michel Amorosa    schedule 27.04.2017

@Meziantou направил меня в правильном направлении, исправив TagMode и ошибку именования тегов.

Однако закодированный вывод приводил к тому, что JSON + LD не прошел проверку, потому что он был искажен из-за кодировки HTML, примененной в SetContent. Здесь мне пришлось сделать две вещи, чтобы решить эту проблему:

  • в SetAttribute () я просто обернул «application / json + ld» новым HtmlString (), чтобы знак плюс выводился как таковой, а не закодирован.
  • Однако для содержимого нельзя было использовать HtmlString (). Но после некоторого расследования я изменил его, чтобы заменить вызов SetContent () вызовом (ами) для output.Content.AppendHtml ()

Теперь тег обработан, у него есть закрывающий тег, и весь JSON + LD правильно отформатирован, чтобы он прошел инструмент проверки.

person Lord of Scripts    schedule 27.04.2017

Для Microsoft.AspNetCore версии 2.0 или выше

  • Вспомогательная функция настраиваемого тега в файлах CS в собственном проекте

Чтобы включить помощник настраиваемого тега из папки TagHelper вашего проекта, используйте приведенный ниже код в файле _ViewImports.cshtml

@using MyProjectNameSpaceInWeb
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MyProjectNameSpaceInWeb



  • импортировать вспомогательную функцию настраиваемого тега из другого проекта

Включив последнюю строку, вы включите всех помощников тегов в ваш основной проект.

Если вы создаете помощники тегов в качестве другого проекта, сначала включите проект в список зависимостей и используйте приведенный ниже код в файле _ViewImports.cshtml.

@using MyProjectNameSpaceInWeb
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MyCustomTagHelperProjectNameSpace



  • импорт встроенных помощников по тегам

Чтобы включить встроенный помощник тегов в папку TagHelper ваших проектов, используйте приведенный ниже код в файле _ViewImports.cshtml.

@using MyProjectNameSpaceInWeb
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
person Justin Jose    schedule 29.06.2018