【问题标题】:How to use DataMember Name for [FromQuery] object Asp.Net core, ModelBinding如何为 [FromQuery] 对象 Asp.Net 核心、ModelBinding 使用 DataMember Name
【发布时间】:2020-02-27 10:37:20
【问题描述】:

对于 [FromBody] 参数,我可以使用 DataMember.Name 设置属性的自定义名称,但它不适用于 [FromQuery]。我想这取决于模型绑定

我想处理像?status=a&status=b&status=c这样的查询

带有查询对象[FromQuery]MyQuery

[DataContract]
class MyQuery {
     [DataMember(Name = "status")
     public IReadOnlyList<string> Statuses { get; set; }
}

我可以这样做

class MyQuery {
     [FromQuery("status")
     public IReadOnlyList<string> Statuses { get; set; }
}

但我想避免来自AspNetCore的模型依赖,有什么解决方案吗?

(有similar question about Web API 2但没有回答)

【问题讨论】:

  • I would like to avoid model dependency from AspNetCore 您的意思是要避免使用 ASP.NET Core 内置模型绑定方法吗?如果你能把你的实际场景说清楚,以便我们更好地理解。

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


【解决方案1】:

我没有找到使用标准属性的方法,所以我使用statuses 名称,对字符串集合使用自定义属性

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
internal class StringCollectionAttribute : Attribute
{
}

并使用自定义模型绑定器

public class StringCollectionBinderProvider : IModelBinderProvider
{
    private static readonly Type BinderType = typeof(StringCollectionBinder);
    private static readonly Type ModelType = typeof(List<string>);

    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        var propertyAttributes = (context.Metadata as DefaultModelMetadata)?.Attributes.PropertyAttributes;

        var isStringCollection =
            propertyAttributes?.Any(x => x is StringCollectionAttribute) == true
            && context.Metadata.ModelType.IsAssignableFrom(ModelType);

        return isStringCollection ? new BinderTypeModelBinder(BinderType) : null;
    }
}

public class StringCollectionBinder : IModelBinder
{
    private const char ValueSeparator = ',';

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var modelName = bindingContext.ModelName;
        var valueCollection = bindingContext.ValueProvider.GetValue(modelName);

        if (valueCollection == ValueProviderResult.None)
        {
            return Task.CompletedTask;
        }

        bindingContext.ModelState.SetModelValue(modelName, valueCollection);

        var stringCollection = valueCollection.FirstValue;

        if (string.IsNullOrEmpty(stringCollection))
        {
            return Task.CompletedTask;
        }

        var collection = stringCollection.Split(ValueSeparator).ToList();
        bindingContext.Result = ModelBindingResult.Success(collection);
        return Task.CompletedTask;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2022-10-13
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2018-09-13
    相关资源
    最近更新 更多