我希望为我的请求对象属性的名称加上别名,以便这些请求都可以工作并且都转到同一个控制器:
myapi/cars?colors=red&colors=blue&colors=green
和myapi/cars?c=red&c=blue&c=green
对于请求对象:
public class CarRequest {
Colors string[] { get; set; }
}
有没有人能够使用新的ModelBinder解决此问题而不必从头开始编写ModelBindings?
Here is a similar problem for an older version of asp.net和also here
答案 0 :(得分:0)
好的。我写了一个模型活页夹。并且必须在客户端库中包含或引用一个属性,并将其放置在该属性上。改进后,我将对其进行更新。我尚未对此进行正确的测试。
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//using my models
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
namespace Mynamespaceforthewebproject
{
public class AliasModelBinder : ComplexTypeModelBinder
{
public AliasModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory)
: base(propertyBinders, loggerFactory)
{
}
protected override Task BindProperty(ModelBindingContext bindingContext)
{
var containerType = bindingContext.ModelMetadata.ContainerType;
if (containerType != null)
{
var propertyType = containerType.GetProperty(bindingContext.ModelMetadata.PropertyName);
var attributes = propertyType.GetCustomAttributes(true);
var aliasAttribute = attributes.SingleOrDefault(attr => attr is BindingAliasAttribute) as BindingAliasAttribute;
if (aliasAttribute != null)
{
bindingContext.ValueProvider = new AliasValueProvider(bindingContext.ValueProvider,
new Alias {OriginalPropertyName = bindingContext.ModelName, AliasName = aliasAttribute.Alias});
}
}
return base.BindProperty(bindingContext);
}
}
public class AliasValueProvider : IValueProvider
{
private readonly IValueProvider _provider;
private readonly Alias _alias;
public AliasValueProvider(IValueProvider provider, Alias alias)
{
_provider = provider;
_alias = alias;
}
public bool ContainsPrefix(string prefix)
{
if (prefix == _alias.OriginalPropertyName)
{
return _provider.ContainsPrefix(_alias.OriginalPropertyName) ||
_provider.ContainsPrefix(_alias.AliasName);
}
return _provider.ContainsPrefix(prefix);
}
public ValueProviderResult GetValue(string key)
{
if (key == _alias.OriginalPropertyName)
{
var original = _provider.GetValue(_alias.OriginalPropertyName);
return original.Values.Any() ? original : _provider.GetValue(_alias.AliasName);
}
return _provider.GetValue(key);
}
}
public class Alias
{
public string OriginalPropertyName { get; set; }
public string AliasName { get; set; }
}
public class AliasModelBinderProvider<T> : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType == typeof(T))
{
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
for (var i = 0; i < context.Metadata.Properties.Count; i++)
{
var property = context.Metadata.Properties[i];
propertyBinders.Add(property, context.CreateBinder(property));
}
return new AliasModelBinder(propertyBinders,
(ILoggerFactory)context.Services.GetService(typeof(ILoggerFactory)));
}
return null;
}
}
}
并在客户项目中
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class BindingAliasAttribute : Attribute
{
public string Alias { get; }
public BindingAliasAttribute(string alias)
{
Alias = alias;
}
}
和一个看起来像这样的对象:
public class SomeRequest
{
[BindingAlias("id")]
public long[] SomeFooIdsForFooing{ get; set; }
}
导致请求看起来像这样:
api/controller/action?SomeFooIdsForFooing=1&SomeFooIdsForFooing=2
或
api/controller/action?id=1&id=2