Привязка пользовательских параметров ядра ASP.NET
У меня есть ситуация, в которой я хотел бы сделать привязку пользовательских параметров для контроллера API в ядре ASP.NET. В WebAPI 2.0 было возможно выполнить настраиваемую привязку к типам примитивов, реализовав различные интерфейсы, такие как IValueProvider, и предоставив ValueProviderFactory. Это не похоже на случай с ядром ASP.NET, насколько я понимаю из документации, которую я нашел здесь.
Я заметил этот пост, который привел меня к этой статье, которая переопределяет поведение MutableObjectModelBinder. Казалось бы, я мог бы сделать что-то вроде этого, например:
[HttpGet]
[Route("api/{domain}/[controller]")]
public IEnumerable<string> Get([ModelBinder(BinderType = typeof(MyCustomBinder))]string orderby)
{
//Do stuff here
}
Это не обязательно кажется мне правильным, так как я имею дело только с примитивным типом, однако я не могу найти какую-либо документацию для другого способа сделать это. Любая помощь будет оценена.
РЕДАКТИРОВАТЬ: В случае, если кто-то наткнулся на это, я просто решил пойти с вспомогательным классом для анализа параметра из-за необходимости соблюдения сроков. Как только я получу возможность выяснить это, я вернусь и опубликую решение, касающееся этой проблемы конкретно.
2 ответа
Создайте класс поставщика связывателя для вашего пользовательского типа
public class MyCustomBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType == typeof(MyCustom))
{
return new BinderTypeModelBinder(typeof(MyCustomBinder));
}
return null;
}
}
и зарегистрируй в сервисах
services.AddMvc(c =>
{
c.ModelBinderProviders.Insert(0, new MyCustomBinderProvider());
});
И пользовательский переплет может идти как
public class MyCustomBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(MyCustom))
{
return TaskCache.CompletedTask;
}
var parameters = new Dictionary<string, string>();
foreach (var parameter in bindingContext.ModelType.GetProperties())
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(parameter.Name);
if (valueProviderResult.FirstValue != null)
{
parameters.Add(parameter.Name, valueProviderResult.FirstValue);
}
}
var result = Activator.CreateInstance(bindingContext.ModelType);
//write your custom code to map the result with the parameters
bindingContext.Result = ModelBindingResult.Success(result);
return TaskCache.CompletedTask;
}
}
Ваш пользовательский тип класса
[ModelBinder(BinderType = typeof(MyCustomBinder))]
public class MyCustom
{
public int Page { get; set; }
public int Rows { get; set; }
}
и ваш контроллер может принять пользовательский класс в качестве параметра строки запроса
[HttpGet("data")]
public DataTransferObject GetData(MyCustom query)
{
}
Перенос решения OP с вопроса на ответ с обрезанным метакомментарием:
Я просто решил использовать вспомогательный класс для анализа параметра из-за необходимости уложиться в сроки.