Je cherche un moyen de résoudre un modèle après avoir entré une action dans un contrôleur, la manière la plus simple de décrire le problème serait:
public DTO[] Get(string filterName)
{
//How can I do this
this.Resolve<MyCustomType>("MyParamName");
}
Si vous cherchez plus d'informations sur les raisons pour lesquelles j'essaie de le faire, vous pouvez continuer à lire pour obtenir l'image complète
TL; DR
Je cherche un moyen de résoudre un modèle d'une demande, étant donné un nom de paramètre qui sera toujours résolu à partir de la chaîne de requête Comment puis-je enregistrer dynamiquement des filtres depuis le démarrage. J'ai une classe qui va gérer l'enregistrement de mes filtres.
Dans ma classe de démarrage, je veux pouvoir enregistrer dynamiquement des filtres avec mes restServices. J'ai une option que j'utilise pour passer à mon ControllerFeatureProvider personnalisé qui ressemble à peu près à ceci:
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;
});
}
}
Mon contrôleur gardera une trace des options et les utilisera pour fournir des filtres pour les points de terminaison de pagination et 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>();
}
}
J'ai du mal à trouver comment résoudre dynamiquement un modèle avec le HttpContext, je penserais à faire quelque chose comme ça pour obtenir le modèle mais c'est un pseudo-code qui ne fonctionne pas
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);
}
Après avoir creusé dans la source, j'ai vu des choses prometteuses ModelBinderFactory et ControllerActionInvoker Ces classes sont utilisées dans le pipeline pour la liaison de modèle,
Je m'attendrais à ce que l'expose une interface simple pour résoudre un nom de paramètre à partir de QueryString, quelque chose comme ceci:
ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Cependant, la seule façon que je vois pour résoudre un modèle à partir du classeur de modèles est de créer de faux descripteurs de contrôleur et de se moquer d'une tonne de choses.
Comment puis-je accepter des paramètres liés tardivement dans mon contrôleur?