Получение атрибутов свойств в TagHelpers

Некоторые свойства модели имеют аннотацию к данным «Обязательные», которую мне нужно прочитать в классе TagHelper.

public partial class Sale
{
    [Required]
    public string CustomerId { get; set; }
    ...

В представлении продаж я создаю индивидуальный выбор для клиента:

<customer asp-for="CustomerId " value="@Model.CustomerId"></customer>

А в классе CustomerTagHelper есть метод процесса:

public override void Process(TagHelperContext context, TagHelperOutput output)
{

Как мне узнать, есть ли у текущего свойства привязки атрибут «required»? Я использую ядро ​​asp-net.


person Beetlejuice    schedule 09.11.2016    source источник


Ответы (3)


Помощник тега не знает ничего, кроме того, что вы вводите в качестве входных данных для его атрибутов. Итак, вы хотите создать помощник тега, который можно использовать следующим образом:

@model WebApplication4.Models.Sale
...
<customer asp-for="CustomerId" />

Затем вы должны объявить свойство типа ModelSource, связанное с атрибутом asp-for. Это даст вам доступ не только к значению свойства, но и к метаданным, например следующим (и многим другим!):

  • значение свойства: source.Model
  • название свойства: source.Name
  • тип модели контейнера: source.Metadata.ContainerType
  • Флаг IsRequired: source.Metadata.IsRequired

Вы также получите intellisense в VS, чтобы выбрать одно из свойств в вашей модели для модели asp-for, и он выдаст ошибку, если значение не является именем свойства модели.


В качестве примера взгляните на этот помощник тега:

public class CustomerTagHelper: TagHelper
{
    [HtmlAttributeName("asp-for")]
    public ModelExpression Source { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "p";
        output.TagMode = TagMode.StartTagAndEndTag;

        var contents = $@"
            Model name: {Source.Metadata.ContainerType.FullName}<br/>
            Property name: {Source.Name}<br/>
            Current Value: {Source.Model}<br/> 
            Is Required: {Source.Metadata.IsRequired}";

        output.Content.SetHtmlContent(new HtmlString(contents));
    }
}

Тогда, если у вас были эти 2 модели:

public class Sale
{
    [Required]
    public string CustomerId { get; set; }
}
public class Promotion
{        
    public string CustomerId { get; set; }
}

Которые используются в этих двух действиях и представлениях:

public IActionResult Sale()
{
    return View();
}

@model WebApplication4.Models.Sale
...
<customer asp-for="CustomerId" />


public IActionResult Promotion()
{
    return View(new Models.Promotion { CustomerId = "abc-123" });
}

@model WebApplication4.Models.Promotion
...
<customer asp-for="CustomerId" />

Будет производить следующие результаты:

Tag helper for: WebApplication4.Models.Sale
Property name: CustomerId
Current Value: 
Is Required: True

Model name: WebApplication4.Models.Promotion
Property name: CustomerId
Current Value: abc-123
Is Required: False
person Daniel J.G.    schedule 09.11.2016
comment
Вместо Source.Metadata.IsRequired я использую For.Metadata.IsRequired. Работает. - person Beetlejuice; 09.11.2016
comment
Да, какое бы имя вы ни использовали для свойства типа ModelExpression - person Daniel J.G.; 10.11.2016
comment
Как насчет доступа к другим атрибутам? - person HamedH; 16.06.2017
comment
Взгляните на Source.Metadata, поскольку он дает вам доступ к дополнительной информации об этом конкретном свойстве модели, включая его тип и содержащий его тип. - person Daniel J.G.; 17.06.2017

Вы можете получить доступ к настраиваемому атрибуту через ModelExpression.

public class CustomTagHelper : TagHelper
{
    [HtmlAttributeName("asp-for")]
    public ModelExpression For { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {            
        CustomAttribute attribute = For.Metadata
                                       .ContainerType
                                       .GetProperty(For.Name)
                                       .GetCustomAttribute(typeof(CustomAttribute)) 
                                       as CustomAttribute;
        if (attribute != null)
        {
            output.Attributes.Add("some-attr", attribute.Text);
        }
    }
}

А затем просто используйте его в своем шаблоне <custom asp-for="SomeProp"></custom>.

person unsafePtr    schedule 19.09.2017
comment
Похоже, имя атрибута должно быть [HtmlAttributeName("asp-for")] с использованием [HtmlAttributeName("for")]не работает для меня ASP.NET core 2.2 - person AdroitOldMan; 04.01.2019

Сделать это можно так:

    var type = typeof(YOUR_CLASS);
    var property = type.GetProperty("FIELD_NAME");
    var isRequired = Attribute.IsDefined(property, typeof(Required));
person Dawid Rutkowski    schedule 09.11.2016