Ich suche nach einer Möglichkeit, ein Modell nach Eingabe einer Aktion in einem Controller aufzulösen. Die einfachste Möglichkeit, das Problem zu beschreiben, ist:
public DTO[] Get(string filterName)
{
//How can I do this
this.Resolve<MyCustomType>("MyParamName");
}
Wenn Sie weitere Informationen darüber suchen, warum ich das versuche, können Sie weiterlesen, um das vollständige Bild zu erhalten
TL; DR
Ich suche nach einer Möglichkeit, eine Anforderung eines Modells mit einem Parameternamen aufzulösen, der immer aus der Abfragezeichenfolge aufgelöst wird. Wie kann ich Filter vom Start dynamisch registrieren? Ich habe eine Klasse, die sich um die Registrierung meiner Filter kümmert.
In meiner Startklasse möchte ich Filter dynamisch bei meinen restServices registrieren können. Ich habe eine Option, die ich verwende, um sie an meinen benutzerdefinierten ControllerFeatureProvider zu übergeben, die ungefähr so aussieht:
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;
});
}
}
Mein Controller verfolgt die Optionen und verwendet sie, um Filter für Paging-Endpunkte und OData bereitzustellen.
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>();
}
}
Ich habe Probleme herauszufinden, wie ein Modell angesichts des HttpContext dynamisch aufgelöst werden kann. Ich würde denken, etwas Ähnliches zu tun, um das Modell zu erhalten, aber dies ist Pseudocode, der nicht funktioniert
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);
}
Nachdem ich mich in die Quelle vertieft hatte , sah ich einige vielversprechende Dinge, ModelBinderFactory und den ControllerActionInvoker Diese Klassen werden in der Pipeline für die Modellbindung verwendet.
Ich würde erwarten, dass das eine einfache Schnittstelle verfügbar macht, um einen Parameternamen aus dem QueryString aufzulösen, ungefähr so:
ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Die einzige Möglichkeit, ein Modell aus dem Modellordner aufzulösen, besteht darin, gefälschte Controller-Deskriptoren zu erstellen und eine Menge Dinge zu verspotten.
Wie kann ich spät gebundene Parameter in meinen Controller übernehmen?