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?