在剃刀页面中实现自定义打字术

在我最近的文章中,我展示 如何创建自定义模型 binder 绑定ISO 8601字符串表示为一周的一周 to a DateTime type in a Razor Pages application. The custom 模型粘合剂在很大程度上倾向于绑定的现有基础设施 字符串到简单类型。自定义模型粘合剂是正确的解决方案 如果要绑定到简单类型,但如果要绑定到a 复杂类型,建议是实施一个 TypeConverter 根据官方文档。但文件不提供一个例子 在模型绑定的上下文中,展示了如何做到这一点。所以这里是 one.

To recap, the HMTL5 week input is supported by a number 浏览器并使用户能够选择一年的一周:

它适用 根据ISO 8601标准格式化的值,在此情况下 week of the year is in the format yyyy-Www, where yyyy is the full year -W is literal, and ww represents the ISO 8601周 the year. In the instance above, the value is set to 2021-W01 - the 2021年的第一周。输入标签助手渲染 input type="week" for properties that have a DataType attribute set to "week".

您有决定在您想要代表的方式方面做出 week in your server code. You could work with it as a string, or a DateTime, or you can create your own custom type to represent the week:

public class Week
{
    public int Year { getset; }
    public int WeekNumber { getset; }
 
    public static Week TryParse(string input)
    {
        var result = input.Split("-W");
        if (result.Length != 2)
        {
            return null;
        }
        if (int.TryParse(result[0], out int year&& int.TryParse(result[1], out int week))
        {
            return new Week { Year = year, WeekNumber = week };
        }
        return null;
    }
 
    public override string ToString()
    {
        return $"{Year}-W{WeekNumber:D2}";
    }
}

The TryParse method takes a string and attempts to generate a valid instance of the Week type. The overridden ToString method generates the correctly formatted value that will be applied to the week input when using the input tag helper. Next, you need a way to call the TryParse method in user input. So, based on the recommendation to use a TypeConverter, here is the WeekConverter:

public class WeekConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext contextType sourceType)
    {
        return sourceType == typeof(string|| base.CanConvertFrom(contextsourceType);
    }
 
    public override object ConvertFrom(ITypeDescriptorContext contextCultureInfo cultureobject value)
    {
        if (value is string input)
        {
            return Week.TryParse(input);
        }
        return base.ConvertFrom(contextculturevalue);
    }
}

The class derives from the TypeConverter and overrides two methods: CanConvertFrom() and ConvertFrom(). The first method returns a bool indicating whether this converter 可以管理指定类型的转换。该转换器是预期的 用于模型绑定,因此它旨在从字符串转换。这 ConvertFrom 方法包含测试是否测试的代码 input is a string, and if so, uses the Week.TryParse method to attempt to return a new Week instance.

Finally, you need to register the WeekConverter. You do this by applying the TypeConverterAttribute to the Week class:

[TypeConverter(typeof(WeekConverter))]
public class Week
{
    ...
}

请注意,此属性不适用于PageModel属性 the ModelBinder attribute. It must be applied to the class 定义。有一个 开放问题 Github that will enable the declaration of the TypeConverterAttribute on model properties and parameters, but in the meantime, it is not supported as part of the model binding infrastructure. The PageModel property has the BindProperty and DataType attributes applied:

[BindPropertyDataType("week")]
public Week CustomWeek { getset; }

Now the TypeConverter takes care of assigning the posted 从输入到PageModel属性的值: 

Summary

As I mentioned at the beginning, the recommendation is to use a TypeConverter when you need to map a single value in a request to a 复杂对象。这样的文章根本不必复杂,因为这篇文章 表演。由于模型绑定系统无论如何都使用类型转换器, 一旦您在课堂上实现了自己并配置了它,它就会“只是 works".