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?
la source
Réponses:
Je suis d'accord avec votre idée
Pourquoi écrire un widget / filtre / point de terminaison pour chaque combinaison possible?
Fournissez simplement des opérations de base pour obtenir toutes les données / propriétés. Utilisez ensuite GraphQL pour permettre à l'utilisateur final de le filtrer ( modéliser ) selon ses besoins.
Depuis 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
.la source
Nous l'avons fait, notre code fait référence à ce site: https://prideparrot.com/blog/archive/2012/6/gotchas_in_explicit_model_binding
Plus précisément, en examinant notre code, qu'est-ce que l'astuce consiste à accepter une FormCollection dans votre méthode de contrôleur, puis à utiliser le classeur de modèle, le modèle et les données de formulaire:
Exemple tiré du lien:
(Remarque: le site semble être en panne, le lien est vers archive.org)
la source
this.Resolve<MyCustomType>("MyParamName");
J'ai fini par écrire des contrôleurs dynamiques. Pour résoudre le problème en guise de solution.
Je suis en train de coder durement la fonction dans la méthode mais je suis sûr que vous pouvez comprendre comment la transmettre si vous en avez besoin.
la source