自定义.NET核心标记助手无法正常工作

时间:2017-04-27 14:00:56

标签: asp.net-mvc asp.net-core-mvc tag-helpers asp.net-core-tag-helpers

我创建了一个新的ASP.NET Core Web应用程序项目,现在为了简单起见,我们说 root namespace MyWeb.Mvc ,这也是在项目属性。

在同一个Web应用程序项目中,我创建了一个名为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中,它应该出现在所有页面中。但是,当我编译并运行Web应用程序并查看主页面的源代码时,我发现自定义标记已经呈现为普通HTML标记而没有TagHelper处理。

现在,我原本想考虑使用json-ld NuGet包,但是当我看到它自2016年以来没有更新时我就停止了并且程序员没有花时间记录如何使用它或给出任何示例

更新#1 正如所建议的那样,我明确地设置了TagMode属性。但是整个输出变为HTML编码,因此不会通过JSON + LD验证。

我现在使用HtmlString(“application / json + ld”),现在可以正确呈现类型条目而不编码“+”符号。但是,我尝试对内容使用相同的方法,但

4 个答案:

答案 0 :(得分:1)

默认情况下,剃须刀页面中的代码名称为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>

修改

默认情况下会对所有值进行编码(出于安全原因)。您可以使用SetHtmlContent方法编写Raw html。对于属性值,您必须提供不对值进行编码的自定义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);
        }
    }
}

答案 1 :(得分:0)

您是否尝试过HtmlTargetElement属性?

[HtmlTargetElement("jsonldwebsite")]

答案 2 :(得分:0)

@Meziantou通过修复TagMode和标签命名blooper让我朝着正确的方向前进。

然而,编码输出使JSON + LD失败验证,因为它在SetContent中应用了HTML编码而导致错误。在这里,我必须做两件事来解决它:

  • 在SetAttribute()中我只是用新的HtmlString()包装“application / json + ld”,这样加号就这样输出而不是编码。
  • 但是对于内容,无法使用HtmlString()。但经过一些调查后,我将其更改为使用call(s)替换SetContent()调用output.Content.AppendHtml()

现在处理标签,它有一个结束标记,所有JSON + LD都经过适当格式化,以便通过验证工具。

答案 3 :(得分:0)

对于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