Привязка пользовательских параметров ядра 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 с вопроса на ответ с обрезанным метакомментарием:

Я просто решил использовать вспомогательный класс для анализа параметра из-за необходимости уложиться в сроки.

Другие вопросы по тегам