如何用ASP.NET Core1WebAPI(隐式或显式)中的GET绑定来自URI的数组?
在ASP.NET 1中,这是有效的:
[HttpGet]
public void Method([FromUri] IEnumerable<int> ints) { ... }您是如何在ASP.NET Web核心1 (又名ASP.NET 5又名ASP.NET vNext)中做到这一点的?医生什么都没有。
发布于 2016-04-29 14:41:38
FromUriAttribute类组合了FromRouteAttribute和FromQueryAttribute类。根据发送的路由/请求的配置,您应该能够将属性替换为其中之一。
然而,有一个可用的空间,它将为您提供FromUriAttribute类。通过package安装"Microsoft.AspNet.Mvc.WebApiCompatShim“NuGet包,或者将其直接添加到project.json文件中:
"dependencies": {
"Microsoft.AspNet.Mvc.WebApiCompatShim": "6.0.0-rc1-final"
}虽然它有点旧,但我发现这篇文章在解释一些更改方面做得很好。
绑定
如果您希望绑定数组的逗号分隔值(“/api/value?ints=1,2,3”),您将需要一个与前面一样的自定义绑定器。这是一个适合于在姆尔奇(氏)解核心中使用的ASP.NET版本。
public class CommaDelimitedArrayModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.IsEnumerableType)
{
var key = bindingContext.ModelName;
var value = bindingContext.ValueProvider.GetValue(key).ToString();
if (!string.IsNullOrWhiteSpace(value))
{
var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
var converter = TypeDescriptor.GetConverter(elementType);
var values = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => converter.ConvertFromString(x.Trim()))
.ToArray();
var typedValues = Array.CreateInstance(elementType, values.Length);
values.CopyTo(typedValues, 0);
bindingContext.Result = ModelBindingResult.Success(typedValues);
}
else
{
// change this line to null if you prefer nulls to empty arrays
bindingContext.Result = ModelBindingResult.Success(Array.CreateInstance(bindingContext.ModelType.GetElementType(), 0));
}
return TaskCache.CompletedTask;
}
return TaskCache.CompletedTask;
}
}您可以为Startup.cs中的所有集合指定要使用的模型绑定。
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc().AddMvcOptions(opts =>
{
opts.ModelBinders.Insert(0, new CommaDelimitedArrayModelBinder());
});
}或者在API调用中指定一次:
[HttpGet]
public void Method([ModelBinder(BinderType = typeof(CommaDelimitedArrayModelBinder))] IEnumerable<int> ints)发布于 2017-04-27 11:06:03
ASP.NET核心1.1答案
@WillRay的回答有点过时。我写了一个'IModelBinder‘和'IModelBinderProvider’。第一个可以与[ModelBinder(BinderType = typeof(DelimitedArrayModelBinder))]属性一起使用,而第二个可以用于全局应用模型绑定,如下所示。
.AddMvc(options =>
{
// Add to global model binders so you don't need to use the [ModelBinder] attribute.
var arrayModelBinderProvider = options.ModelBinderProviders.OfType<ArrayModelBinderProvider>().First();
options.ModelBinderProviders.Insert(
options.ModelBinderProviders.IndexOf(arrayModelBinderProvider),
new DelimitedArrayModelBinderProvider());
})
public class DelimitedArrayModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsEnumerableType && !context.Metadata.ElementMetadata.IsComplexType)
{
return new DelimitedArrayModelBinder();
}
return null;
}
}
public class DelimitedArrayModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
var values = valueProviderResult
.ToString()
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
if (values.Length == 0)
{
bindingContext.Result = ModelBindingResult.Success(Array.CreateInstance(elementType, 0));
}
else
{
var converter = TypeDescriptor.GetConverter(elementType);
var typedArray = Array.CreateInstance(elementType, values.Length);
try
{
for (int i = 0; i < values.Length; ++i)
{
var value = values[i];
var convertedValue = converter.ConvertFromString(value);
typedArray.SetValue(convertedValue, i);
}
}
catch (Exception exception)
{
bindingContext.ModelState.TryAddModelError(
modelName,
exception,
bindingContext.ModelMetadata);
}
bindingContext.Result = ModelBindingResult.Success(typedArray);
}
return Task.CompletedTask;
}
}发布于 2019-12-11 11:22:52
.NET核心3中有一些更改。
微软已经将功能从AddMvc方法(来源)中分离出来。
由于AddMvc还包括对视图控制器、Razor视图等的支持。如果您不需要在项目中使用它们(就像在API中一样),您可以考虑使用Web控制器的services.AddControllers()。
因此,更新的代码如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddMvcOptions(opt =>
{
var mbp = opt.ModelBinderProviders.OfType<ArrayModelBinderProvider>().First();
opt.ModelBinderProviders.Insert(opt.ModelBinderProviders.IndexOf(mbp), new DelimitedArrayModelBinderProvider());
});
}https://stackoverflow.com/questions/36794586
复制相似问题