C# 将TagHelper绑定到以数据开头的属性-

C# 将TagHelper绑定到以数据开头的属性-,c#,asp.net-core,asp.net-core-mvc,asp.net-core-tag-helpers,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core Tag Helpers,我目前正在开发一个ASP.NETCore3.0预发行版8MVC应用程序。我创建了一个自定义标记帮助器,它看起来类似于以下内容,基本上与现有的asp append version属性相同,但是使用data src属性而不是src: [HtmlTargetElement( “img”, Attributes=AppendVersionAttributeName+“,”+SrcAttributeName, TagStructure=TagStructure.WithoutEndTag)] 公共类Ima

我目前正在开发一个ASP.NETCore3.0预发行版8MVC应用程序。我创建了一个自定义标记帮助器,它看起来类似于以下内容,基本上与现有的
asp append version
属性相同,但是使用
data src
属性而不是
src

[HtmlTargetElement(
“img”,
Attributes=AppendVersionAttributeName+“,”+SrcAttributeName,
TagStructure=TagStructure.WithoutEndTag)]
公共类ImageTagHelper:UrlResolutionTagHelper
{
私有常量字符串AppendVersionAttributeName=“asp append version lazy”;
私有常量字符串srcadributeName=“数据src”;
[ActivatorUtilitiesConstructor]
公共ImageTagHelper(
IFilerVersionProvider文件版本提供程序,
HtmlEncoder HtmlEncoder,
IUrlHelperFactory urlHelperFactory)
:base(urlHelperFactory、htmlEncoder)
{
FileVersionProvider=FileVersionProvider;
}
公共覆盖整数顺序=>-1000;
[HtmlAttributeName(SrcAttributeName)]
公共字符串?Src{get;set;}
[HtmlAttributeName(AppendVersionAttributeName)]
公共bool AppendVersion{get;set;}
内部IFilerVersionProvider FileVersionProvider{get;private set;}
公共覆盖无效进程(TagHelperContext上下文,TagHelperOutput输出)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
if(输出==null)
{
抛出新ArgumentNullException(nameof(output));
}
CopyHtmlAttribute(SrcAttributeName,context);
ProcessUrlAttribute(SrcAttributeName,输出);
如果(附录版本)
{
EnsureRefleverionProvider();
Src=output.Attributes[SrcAttributeName]。值为字符串;
output.Attributes.SetAttribute(SrcAttributeName,FileVersionProvider.AddFileVersionPath(ViewContext.HttpContext.Request.PathBase,Src));
}
}
private void EnsurefleverionProvider()
{
如果(FileVersionProvider==null)
{
FileVersionProvider=ViewContext.HttpContext.RequestServices.GetRequiredService();
}
}
}
无论如何,重要的一点是我想要的属性是
data src
,但当我尝试在任何视图中使用标记帮助器时,它会给我以下错误:

标记帮助程序绑定属性“..”无效。标记帮助程序无法绑定到名为“data src”的HTML属性,因为该名称以“data-”开头

实际问题 这是什么原因,还有什么办法可以“绕过”呢

根据,这就是原因:

data-*
属性明确不是由用户代理实现的,也不打算在服务器上使用;因此标记帮助程序绑定到它们是无效的

因此,我们的想法是明确地防止
数据-
属性在服务端被评估,作为它们仅为了客户端评估而传输数据的一种手段

此限制无法规避,因为它内置于Razor SDK中,用于编译使用标记助手的Razor视图

仔细想想,有这样的限制是有意义的,特别是当您完全可以自由地在标记帮助器上使用您想要的任何属性时。如果您想使用
数据-
属性,因为您想在标记帮助程序运行后公开它们,那么实际上没有什么可以阻止您这样做,因为您可以始终添加附加属性作为标记帮助程序执行的一部分:包括
数据-
属性。

根据,这就是原因:

data-*
属性明确不是由用户代理实现的,也不打算在服务器上使用;因此标记帮助程序绑定到它们是无效的

因此,我们的想法是明确地防止
数据-
属性在服务端被评估,作为它们仅为了客户端评估而传输数据的一种手段

此限制无法规避,因为它内置于Razor SDK中,用于编译使用标记助手的Razor视图


仔细想想,有这样的限制是有意义的,特别是当您完全可以自由地在标记帮助器上使用您想要的任何属性时。如果您想使用
数据-
属性,因为您想在标记助手运行后公开它们,实际上,没有什么可以阻止您这样做,因为您可以始终添加附加属性作为标记助手执行的一部分:包括
数据-
属性。

不能在服务器端使用
数据-*
属性,然后在客户端进行更改

1.自定义ImageTagHelper代码:

using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Text.Encodings.Web;

namespace YourAssemblyName.TagHelpers
{
    [HtmlTargetElement(
        "img",
        Attributes = AppendVersionAttributeName + "," + SrcAttributeName,
        TagStructure = TagStructure.WithoutEndTag)]
    public class ImageTagHelper : UrlResolutionTagHelper
    {
        private const string AppendVersionAttributeName = "asp-append-version-lazy";
        private const string SrcAttributeName = "lazy-src";

        [ActivatorUtilitiesConstructor]
        public ImageTagHelper(
            IFileVersionProvider fileVersionProvider,
            HtmlEncoder htmlEncoder,
            IUrlHelperFactory urlHelperFactory)
            : base(urlHelperFactory, htmlEncoder)
        {
            FileVersionProvider = fileVersionProvider;
        }

        public override int Order => -1000;

        /// <summary>
        /// Source of the image.
        /// </summary>
        /// <remarks>
        /// Passed through to the generated HTML in all cases.
        /// </remarks>
        [HtmlAttributeName(SrcAttributeName)]
        public string Src { get; set; }

        /// <summary>
        /// Value indicating if file version should be appended to the src urls.
        /// </summary>
        /// <remarks>
        /// If <c>true</c> then a query string "v" with the encoded content of the file is added.
        /// </remarks>
        [HtmlAttributeName(AppendVersionAttributeName)]
        public bool AppendVersion { get; set; }

        internal IFileVersionProvider FileVersionProvider { get; private set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.CopyHtmlAttribute(SrcAttributeName, context);
            ProcessUrlAttribute(SrcAttributeName, output);

            if (AppendVersion)
            {
                EnsureFileVersionProvider();

                // Retrieve the TagHelperOutput variation of the "src" attribute in case other TagHelpers in the
                // pipeline have touched the value. If the value is already encoded this ImageTagHelper may
                // not function properly.
                Src = output.Attributes[SrcAttributeName].Value as string;

                output.Attributes.SetAttribute(SrcAttributeName, FileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, Src));
            }
        }

        private void EnsureFileVersionProvider()
        {
            if (FileVersionProvider == null)
            {
                FileVersionProvider = ViewContext.HttpContext.RequestServices.GetRequiredService<IFileVersionProvider>();
            }
        }
    }
}
@addTagHelper *, YourAssemblyName
<img class="lazyload" lazy-src="/logos/searchsolar-console.png" asp-append-version-lazy="true" />
var images = document.querySelectorAll(".lazyload");
new LazyLoad(images, {
    src: "lazy-src"
});
只有程序集名,而不是
yoursamblyName.TagHelpers这样的命名空间

3.HTML代码:

using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Text.Encodings.Web;

namespace YourAssemblyName.TagHelpers
{
    [HtmlTargetElement(
        "img",
        Attributes = AppendVersionAttributeName + "," + SrcAttributeName,
        TagStructure = TagStructure.WithoutEndTag)]
    public class ImageTagHelper : UrlResolutionTagHelper
    {
        private const string AppendVersionAttributeName = "asp-append-version-lazy";
        private const string SrcAttributeName = "lazy-src";

        [ActivatorUtilitiesConstructor]
        public ImageTagHelper(
            IFileVersionProvider fileVersionProvider,
            HtmlEncoder htmlEncoder,
            IUrlHelperFactory urlHelperFactory)
            : base(urlHelperFactory, htmlEncoder)
        {
            FileVersionProvider = fileVersionProvider;
        }

        public override int Order => -1000;

        /// <summary>
        /// Source of the image.
        /// </summary>
        /// <remarks>
        /// Passed through to the generated HTML in all cases.
        /// </remarks>
        [HtmlAttributeName(SrcAttributeName)]
        public string Src { get; set; }

        /// <summary>
        /// Value indicating if file version should be appended to the src urls.
        /// </summary>
        /// <remarks>
        /// If <c>true</c> then a query string "v" with the encoded content of the file is added.
        /// </remarks>
        [HtmlAttributeName(AppendVersionAttributeName)]
        public bool AppendVersion { get; set; }

        internal IFileVersionProvider FileVersionProvider { get; private set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.CopyHtmlAttribute(SrcAttributeName, context);
            ProcessUrlAttribute(SrcAttributeName, output);

            if (AppendVersion)
            {
                EnsureFileVersionProvider();

                // Retrieve the TagHelperOutput variation of the "src" attribute in case other TagHelpers in the
                // pipeline have touched the value. If the value is already encoded this ImageTagHelper may
                // not function properly.
                Src = output.Attributes[SrcAttributeName].Value as string;

                output.Attributes.SetAttribute(SrcAttributeName, FileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, Src));
            }
        }

        private void EnsureFileVersionProvider()
        {
            if (FileVersionProvider == null)
            {
                FileVersionProvider = ViewContext.HttpContext.RequestServices.GetRequiredService<IFileVersionProvider>();
            }
        }
    }
}
@addTagHelper *, YourAssemblyName
<img class="lazyload" lazy-src="/logos/searchsolar-console.png" asp-append-version-lazy="true" />
var images = document.querySelectorAll(".lazyload");
new LazyLoad(images, {
    src: "lazy-src"
});

或者,您可以修改jquery.lazyload.js,将所有
数据src
更改为
惰性src
,然后像以前一样调用
lazyload()

不能在服务器端使用
数据-*
属性,然后在客户端进行更改

1.自定义ImageTagHelper代码:

using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Text.Encodings.Web;

namespace YourAssemblyName.TagHelpers
{
    [HtmlTargetElement(
        "img",
        Attributes = AppendVersionAttributeName + "," + SrcAttributeName,
        TagStructure = TagStructure.WithoutEndTag)]
    public class ImageTagHelper : UrlResolutionTagHelper
    {
        private const string AppendVersionAttributeName = "asp-append-version-lazy";
        private const string SrcAttributeName = "lazy-src";

        [ActivatorUtilitiesConstructor]
        public ImageTagHelper(
            IFileVersionProvider fileVersionProvider,
            HtmlEncoder htmlEncoder,
            IUrlHelperFactory urlHelperFactory)
            : base(urlHelperFactory, htmlEncoder)
        {
            FileVersionProvider = fileVersionProvider;
        }

        public override int Order => -1000;

        /// <summary>
        /// Source of the image.
        /// </summary>
        /// <remarks>
        /// Passed through to the generated HTML in all cases.
        /// </remarks>
        [HtmlAttributeName(SrcAttributeName)]
        public string Src { get; set; }

        /// <summary>
        /// Value indicating if file version should be appended to the src urls.
        /// </summary>
        /// <remarks>
        /// If <c>true</c> then a query string "v" with the encoded content of the file is added.
        /// </remarks>
        [HtmlAttributeName(AppendVersionAttributeName)]
        public bool AppendVersion { get; set; }

        internal IFileVersionProvider FileVersionProvider { get; private set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.CopyHtmlAttribute(SrcAttributeName, context);
            ProcessUrlAttribute(SrcAttributeName, output);

            if (AppendVersion)
            {
                EnsureFileVersionProvider();

                // Retrieve the TagHelperOutput variation of the "src" attribute in case other TagHelpers in the
                // pipeline have touched the value. If the value is already encoded this ImageTagHelper may
                // not function properly.
                Src = output.Attributes[SrcAttributeName].Value as string;

                output.Attributes.SetAttribute(SrcAttributeName, FileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, Src));
            }
        }

        private void EnsureFileVersionProvider()
        {
            if (FileVersionProvider == null)
            {
                FileVersionProvider = ViewContext.HttpContext.RequestServices.GetRequiredService<IFileVersionProvider>();
            }
        }
    }
}
@addTagHelper *, YourAssemblyName
<img class="lazyload" lazy-src="/logos/searchsolar-console.png" asp-append-version-lazy="true" />
var images = document.querySelectorAll(".lazyload");
new LazyLoad(images, {
    src: "lazy-src"
});
只有程序集名,而不是
yoursamblyName.TagHelpers这样的命名空间

3.HTML代码:

using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Text.Encodings.Web;

namespace YourAssemblyName.TagHelpers
{
    [HtmlTargetElement(
        "img",
        Attributes = AppendVersionAttributeName + "," + SrcAttributeName,
        TagStructure = TagStructure.WithoutEndTag)]
    public class ImageTagHelper : UrlResolutionTagHelper
    {
        private const string AppendVersionAttributeName = "asp-append-version-lazy";
        private const string SrcAttributeName = "lazy-src";

        [ActivatorUtilitiesConstructor]
        public ImageTagHelper(
            IFileVersionProvider fileVersionProvider,
            HtmlEncoder htmlEncoder,
            IUrlHelperFactory urlHelperFactory)
            : base(urlHelperFactory, htmlEncoder)
        {
            FileVersionProvider = fileVersionProvider;
        }

        public override int Order => -1000;

        /// <summary>
        /// Source of the image.
        /// </summary>
        /// <remarks>
        /// Passed through to the generated HTML in all cases.
        /// </remarks>
        [HtmlAttributeName(SrcAttributeName)]
        public string Src { get; set; }

        /// <summary>
        /// Value indicating if file version should be appended to the src urls.
        /// </summary>
        /// <remarks>
        /// If <c>true</c> then a query string "v" with the encoded content of the file is added.
        /// </remarks>
        [HtmlAttributeName(AppendVersionAttributeName)]
        public bool AppendVersion { get; set; }

        internal IFileVersionProvider FileVersionProvider { get; private set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.CopyHtmlAttribute(SrcAttributeName, context);
            ProcessUrlAttribute(SrcAttributeName, output);

            if (AppendVersion)
            {
                EnsureFileVersionProvider();

                // Retrieve the TagHelperOutput variation of the "src" attribute in case other TagHelpers in the
                // pipeline have touched the value. If the value is already encoded this ImageTagHelper may
                // not function properly.
                Src = output.Attributes[SrcAttributeName].Value as string;

                output.Attributes.SetAttribute(SrcAttributeName, FileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, Src));
            }
        }

        private void EnsureFileVersionProvider()
        {
            if (FileVersionProvider == null)
            {
                FileVersionProvider = ViewContext.HttpContext.RequestServices.GetRequiredService<IFileVersionProvider>();
            }
        }
    }
}
@addTagHelper *, YourAssemblyName
<img class="lazyload" lazy-src="/logos/searchsolar-console.png" asp-append-version-lazy="true" />
var images = document.querySelectorAll(".lazyload");
new LazyLoad(images, {
    src: "lazy-src"
});
或者,您可以修改jquery.lazyload.js,将所有
数据src
更改为
惰性src
,然后像以前一样调用
lazyload()