Typeconverter не работает в ядре asp.net

У меня Amount хранится в базе данных как decimal. Я хочу показать это значение в пользовательском интерфейсе с разделителем тысяч. Я могу добавить атрибут [DisplayFormat(DataFormatString = "{0:N2}", ApplyFormatInEditMode = true)] в свойство amount, и это будет отображать число с разделителем тысяч, однако, когда я отправляю значение обратно на сервер, привязка модели MVC не будет работать из-за запятых.

Я создал специальный преобразователь типов, который преобразует из decimal в string, а затем из string в decimal

public class NumberConverter : TypeConverter
{
    public override bool CanConvertFrom(
        ITypeDescriptorContext context,
        Type sourceType)
    {
        if (sourceType == typeof(decimal))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context,
        CultureInfo culture, object value)
    {
        if (value is decimal)
        {
            return string.Format("{0:N2}", value);
        }
        return base.ConvertFrom(context, culture, value);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context,
        Type destinationType)
    {
        if (destinationType == typeof(decimal))
        {
            return true;
        }
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context,
        CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(decimal) && value is string)
        {
            return Scrub(value.ToString());
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }

    private decimal Scrub(string modelValue)
    {
        NumberStyles _currencyStyle = NumberStyles.Currency;
        CultureInfo _culture = new CultureInfo("en-US");

        var modelDecimal = 0M;
        decimal.TryParse(
           modelValue,
           _currencyStyle,
           _culture,
           out modelDecimal
       );

        return modelDecimal;
    }
}

а затем я применил его к одному из свойств модели. Обратите внимание, что модель может иметь другие десятичные свойства, которые могут не требовать этого преобразования.

public class MyModel
{

    [TypeConverter(typeof(NumberConverter))]
    [Display(Name = "Enter Amount")]
    public decimal Amount { get; set;}

    public string Name { get; set; }
}

Index.cshtml

<form asp-action="submit" asp-controller="home">
    @Html.EditorFor(m => m.Amount)
    <button type="submit" class="btn btn-primary">Save</button>
</form>

Однако код конвертера никогда не запускается. Когда я помещаю точку останова в NumberConverter, ни одна из точек останова не попадает. Нужно ли где-нибудь регистрировать конвертер типов? Я использую ядро ​​asp.net.


person LP13    schedule 12.04.2017    source источник
comment
Я заметил, что TypeConverter работает с Json.net сериализацией, но не с System.Text.Json, который используется по умолчанию в ASP.NET Core. Мы используем настраиваемую структуру Date в качестве поля в контракте данных и ожидаем получить ее в теле метода POST. Сериализатору .NET Core по умолчанию не удалось связать содержимое запроса, поэтому класс контракта данных был null. Переход на Json.net решил проблему.   -  person Bulat    schedule 19.02.2020


Ответы (1)


По моим наблюдениям asp.net core не принимает во внимание свойства, оформленные TypeConverters.

Таким образом, он поддерживает только TypeConverters, которые украшают объявление класса фактического типа.

Работает

[TypeConverter(typeof(MyModelStringTypeConverter))]
public class MyModel
{

}

Не работает

public class OtherModel
{
    [TypeConverter(typeof(MyModelStringTypeConverter))]
    public MyModel MyModel { get;set; }
}
person bot_insane    schedule 13.06.2018
comment
Я столкнулся с той же проблемой - внутри модели у меня есть коллекция / набор значений, которые я хочу проанализировать из строки - до сих пор я придумал написать простой преобразователь и зарегистрировать его из Startup таким образом: TypeDescriptor.AddAttributes( typeof(IReadOnlyCollection<string>),new TypeConverterAttribute( typeof(FooTypeConverter))); ... но я не совсем как этот подход :( - person Zdeněk; 23.08.2018