Я ищу способ разрешения модели после входа в действие в контроллере, самый простой способ описать проблему будет:
public DTO[] Get(string filterName)
{
//How can I do this
this.Resolve<MyCustomType>("MyParamName");
}
Если вам нужна дополнительная информация о том, почему я пытаюсь это сделать, вы можете продолжить чтение, чтобы получить полную картину
TL; DR
Я ищу способ разрешить модели запрос, учитывая имя параметра, которое всегда будет разрешаться из строки запроса. Как я могу динамически зарегистрировать фильтры при запуске. У меня есть класс, который собирается обрабатывать мои фильтры.
В моем классе запуска я хочу иметь возможность динамически регистрировать фильтры с помощью моих restServices. У меня есть параметры, которые я использую, чтобы передать свой пользовательский ControllerFeatureProvider, который примерно выглядит так:
public class DynamicControllerOptions<TEntity, TDTO>
{
Dictionary<string, Func<HttpContext, Expression<Func<TEntity, bool>>>> _funcNameToEndpointResolverMap
= new Dictionary<string, Func<HttpContext, Expression<Func<TEntity, bool>>>>();
Dictionary<string, List<ParameterOptions>> _filterParamsMap = new Dictionary<string, List<ParameterOptions>>();
public void AddFilter(string filterName, Expression<Func<TEntity, bool>> filter)
{
this._funcNameToEndpointResolverMap.Add(filterName, (httpContext) => filter);
}
public void AddFilter<T1>(string filterName, Func<T1, Expression<Func<TEntity, bool>>> filterResolver,
string param1Name = "param1")
{
var parameters = new List<ParameterOptions> { new ParameterOptions { Name = param1Name, Type = typeof(T1) } };
this._filterParamsMap.Add(filterName, parameters);
this._funcNameToEndpointResolverMap.Add(filterName, (httpContext) => {
T1 parameter = this.ResolveParameterFromContext<T1>(httpContext, param1Name);
var filter = filterResolver(parameter);
return filter;
});
}
}
Мой контроллер будет отслеживать параметры и использовать их для предоставления фильтров для конечных точек подкачки и OData.
public class DynamicControllerBase<TEntity, TDTO> : ControllerBase
{
protected DynamicControllerOptions<TEntity, TDTO> _options;
//...
public TDTO[] GetList(string filterName = "")
{
Expression<Func<TEntity, bool>> filter =
this.Options.ResolveFilter(filterName, this.HttpContext);
var entities = this._context.DbSet<TEntity>().Where(filter).ToList();
return entities.ToDTO<TDTO>();
}
}
У меня проблемы с выяснением того, как динамически разрешить модель с учетом HttpContext, я думаю, что сделать что-то подобное, чтобы получить модель, но это псевдокод, который не работает
private Task<T> ResolveParameterFromContext<T>(HttpContext httpContext, string parameterName)
{
//var modelBindingContext = httpContext.ToModelBindingContext();
//var modelBinder = httpContext.Features.OfType<IModelBinder>().Single();
//return modelBinder.BindModelAsync<T>(parameterName);
}
Покопавшись в Source, я увидел многообещающие вещи ModelBinderFactory и ControllerActionInvoker. Эти классы используются в конвейере для привязки модели,
Я ожидаю, что будет представлен простой интерфейс для разрешения имени параметра из QueryString, что-то вроде этого:
ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Тем не менее, единственный способ разрешить модель из связывателя модели - создать поддельные дескрипторы контроллера и высмеивать массу вещей.
Как я могу принять параметры с поздней привязкой в мой контроллер?
источник
Ответы:
Я согласен с твоей мыслью
Зачем писать виджет / фильтр / конечную точку для каждой возможной комбинации?
Просто предоставьте основные операции, чтобы получить все данные / свойства. Затем используйте GraphQL, чтобы позволить конечному пользователю отфильтровать ( смоделировать ) его для своих нужд.
Из GraphQL
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools
,источник
Мы сделали это, наш код ссылается на этот сайт: https://prideparrot.com/blog/archive/2012/6/gotchas_in_explicit_model_binding
В частности, взглянув на наш код, что за хитрость заключается в том, чтобы принять FormCollection в методе вашего контроллера и затем использовать связыватель модели, модель и данные формы:
Пример взят по ссылке:
(Примечание: сайт, кажется, не работает, ссылка на archive.org)
источник
this.Resolve<MyCustomType>("MyParamName");
Я закончил писать динамические контроллеры. Чтобы решить проблему как обходной путь.
Сейчас я жестко программирую func в методе, но я уверен, что вы можете понять, как передать его, если вам нужно.
источник