Estoy buscando una manera de resolver un modelo después de entrar en una acción en un controlador, la forma más sencilla de describir el problema sería:
public DTO[] Get(string filterName)
{
//How can I do this
this.Resolve<MyCustomType>("MyParamName");
}
Si está buscando más información sobre por qué estoy tratando de hacerlo, puede continuar leyendo para obtener una imagen completa
TL; DR
Estoy buscando una manera de resolver una solicitud de un modelo, dado un nombre de parámetro que siempre se resolverá a partir de la cadena de consulta ¿Cómo puedo registrar dinámicamente los filtros desde el inicio? Tengo una clase que se encargará de registrar mis filtros.
En mi clase de inicio quiero poder registrar dinámicamente filtros con mis restServices. Tengo una opción que estoy usando para pasar a mi ControllerFeatureProvider personalizado que se ve más o menos así:
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;
});
}
}
Mi controlador hará un seguimiento de las opciones y las usará para proporcionar filtros para puntos finales de paginación y 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>();
}
}
Tengo problemas para descubrir cómo resolver dinámicamente un modelo dado el HttpContext, creo que haría algo como esto para obtener el modelo, pero este es un pseudocódigo que no funciona
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);
}
Después de profundizar en la fuente, vi algunas cosas prometedoras ModelBinderFactory y ControllerActionInvoker Estas clases se usan en la tubería para el enlace de modelos,
Esperaría que exponga una interfaz simple para resolver un nombre de parámetro de QueryString, algo como esto:
ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Sin embargo, la única forma en que veo resolver un modelo desde la carpeta del modelo es crear descriptores de controladores falsos y burlarse de un montón de cosas.
¿Cómo puedo aceptar parámetros enlazados tarde en mi controlador?
fuente
Respuestas:
Estoy de acuerdo con tu pensamiento
¿Por qué escribir un widget / filtro / punto final para cada combinación posible?
Simplemente proporcione operaciones básicas para obtener todos los datos / propiedades. A continuación, utilice GraphQL para permitir que el usuario final para filtro ( modelo ) a sus necesidades.
De 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
.fuente
Hemos hecho esto, nuestro código hace referencia a este sitio: https://prideparrot.com/blog/archive/2012/6/gotchas_in_explicit_model_binding
Específicamente, observando nuestro código, ¿de qué sirve aceptar una FormCollection en su método de controlador y luego usar la carpeta de modelo, el modelo y los datos del formulario:
Ejemplo tomado del enlace:
(Nota: el sitio parece estar inactivo, el enlace es a archive.org)
fuente
this.Resolve<MyCustomType>("MyParamName");
Terminé escribiendo controladores dinámicos. Para resolver el problema como una solución alternativa.
Estoy codificando el func en el método por el momento, pero estoy seguro de que puedes encontrar la manera de transmitirlo si lo necesitas.
fuente