ASP.NET Core 2自定义模型Binder单字段模型验证

时间:2018-06-11 21:10:54

标签: c# asp.net-core-2.0 model-binding

我已经设置了应用于单个字段的自定义模型绑定器,如下所示:

public class EnumerationBinder<T> : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        var value = valueProviderResult.FirstOrDefault(); // get the value as string
        if (value == null)
        {
            bindingContext.Result = ModelBindingResult.Success(new List<T>());
            return Task.CompletedTask;
        }

        var options = value.Split(",");

        var potentials = Enum.GetNames(typeof(T));

        var formats = options
            .Where(c => potentials.Any(x => x.Equals(c,StringComparison.OrdinalIgnoreCase)))
            .Select(c => (T)Enum.Parse(typeof(T), c, true))
            .ToList();

        bindingContext.Result = ModelBindingResult.Success(formats);

        return Task.CompletedTask;
    }
}

这需要一个字符串并将其映射到我的模型中的Enum列表,如下所示:

    [EnumDataType(typeof(RequestedFormat))]
    [JsonConverter(typeof(StringEnumConverter))]
    [BindProperty(BinderType = typeof(EnumerationBinder<RequestedFormat>))]
    public IEnumerable<RequestedFormat> Formats { get; set; }

不幸的是,每当我传递一个正确绑定的字符串值(例如&amp; formats = foo,bar)时,我的ModelState对此属性始终无效

我在活页夹结束时检查了模型状态,没有错误。我还添加了一个自定义模型验证属性,但这会在模型绑定器之后进行调用,如果它返回&#34;无效&#34;然后我在我的模型状态错误集合中为此属性获得2个条目,如果它返回&#34;有效&#34;然后我在错误集合中得到了相同的原始错误。

我错过了什么?

完整模型是:

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

    [Required]
    public Guid UserId { get; set; }

    [EnumDataType(typeof(RequestedState))]
    [JsonConverter(typeof(StringEnumConverter))]
    public RequestedState State { get; set; }

    [EnumDataType(typeof(RequestedFormat))]
    [JsonConverter(typeof(StringEnumConverter))]
    [BindProperty(BinderType = typeof(EnumerationBinder<RequestedFormat>))]
    public IEnumerable<RequestedFormat> Formats { get; set; }

    /// <summary>
    /// An optional sort of the items to return. To sort descending, prefix the value with '-'. For example &amp;sort=-duedate or use the direct value
    /// &amp;sort=duedatedescending. The default is by descending borrow date and then by title. If sorted by a specific attribute then the sort order is always by that
    /// attribute and then by ascending title sequence
    /// </summary>
    [EnumDataType(typeof(RequestedSort))]
    [JsonConverter(typeof(StringEnumConverter))]
    [BindProperty(BinderType = typeof(SortOrderBinder))]
    public RequestedSort Sort { get; set; }

    [EnumDataType(typeof(BooleanRequest))]
    [JsonConverter(typeof(StringEnumConverter))]
    public BooleanRequest Favorite { get; set; }

    [EnumDataType(typeof(BooleanRequest))]
    [JsonConverter(typeof(StringEnumConverter))]
    public BooleanRequest Read { get; set; }

    [EnumDataType(typeof(BooleanRequest))]
    [JsonConverter(typeof(StringEnumConverter))]
    public BooleanRequest Bagged { get; set; }
    public int Segment { get; set; }
    public int SegmentSize { get; set; }

    public AccountItemRequest()
    {
        Read = BooleanRequest.Any;
        Favorite = BooleanRequest.Any;
        Bagged = BooleanRequest.Any;
        State = RequestedState.Any;
        Formats = new List<RequestedFormat>() { RequestedFormat.Any };
        Sort = RequestedSort.BorrowedDateDescending;
        Segment = 1;
        SegmentSize = 20;
    }
}

public enum BooleanRequest
{
    Any = 0,
    Yes = 5,
    No = 10
}

    public enum RequestedState
{
    Any = 0,
    StateA = 5,
    StateB= 15,
    StateC= 20,
    StageD= 25
}

public enum RequestedFormat
{
    Any = 0,
    Format1= 5,
    Format2= 10,
    Format3= 15
}

public enum RequestedSort
{
    DueDateDescending = 5,
    DueDateAscending = 10,
    TitleDescending = 15,
    TitleAscending = 20,
}

0 个答案:

没有答案