Szukam sposobu rozwiązania modelu po uruchomieniu akcji w kontrolerze, najprostszym sposobem opisania problemu byłoby:
public DTO[] Get(string filterName)
{
//How can I do this
this.Resolve<MyCustomType>("MyParamName");
}
Jeśli szukasz więcej informacji o tym, dlaczego próbuję to zrobić, możesz kontynuować czytanie, aby uzyskać pełny obraz
TL; DR
Szukam sposobu na rozwiązanie modelu żądania, biorąc pod uwagę nazwę parametru, która zawsze będzie rozstrzygana z ciągu zapytania. Jak mogę dynamicznie zarejestrować filtry od uruchomienia. Mam zajęcia, które zajmą się rejestracją moich filtrów.
W mojej klasie startowej chcę móc dynamicznie rejestrować filtry w moich usługach restServices. Mam opcje, których używam do przekazania do mojego niestandardowego sterownika ControllerFeatureProvider, który z grubsza wygląda tak:
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;
});
}
}
Mój kontroler będzie śledził opcje i użyje ich do zapewnienia filtrów dla punktów końcowych stronicowania i 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>();
}
}
Mam problem z wymyśleniem, jak dynamicznie rozwiązać model, biorąc pod uwagę HttpContext, pomyślałbym, aby zrobić coś takiego, aby uzyskać model, ale to pseudo-kod, który nie działa
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);
}
Po wkopaniu do źródła zobaczyłem kilka obiecujących rzeczy ModelBinderFactory i ControllerActionInvoker Te klasy są używane w potoku do wiązania modelu,
Spodziewałbym się ujawnić prosty interfejs do rozwiązania nazwy parametru z QueryString, coś takiego:
ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Jednak jedynym sposobem, w jaki widzę rozwiązanie modelu z segregatora modeli, jest tworzenie fałszywych deskryptorów kontrolera i wyśmiewanie mnóstwa rzeczy.
Jak mogę zaakceptować parametry późno związane do mojego kontrolera?
źródło
Odpowiedzi:
Zgadzam się z twoją myślą
Po co pisać widget / filtr / punkt końcowy dla każdej możliwej kombinacji?
Wystarczy zapewnić podstawowe operacje, aby uzyskać wszystkie dane / właściwości. Następnie użyj GraphQL, aby zezwolić użytkownikowi końcowemu na filtrowanie ( modelowanie ) zgodnie z ich potrzebami.
Z 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
.źródło
Zrobiliśmy to, nasz kod odwołuje się do tej witryny: https://prideparrot.com/blog/archive/2012/6/gotchas_in_explicit_model_binding
W szczególności, patrząc na nasz kod, jaka jest sztuczka polegająca na zaakceptowaniu FormCollection w metodzie kontrolera, a następnie użyciu spoiwa modelu, modelu i danych formularza:
Przykład pochodzi z linku:
(Uwaga: strona prawdopodobnie nie działa, link do archive.org)
źródło
this.Resolve<MyCustomType>("MyParamName");
Skończyło się na pisaniu kontrolerów dynamicznych. Aby rozwiązać problem jako obejście.
Na razie ciężko koduję func w metodzie, ale jestem pewien, że możesz dowiedzieć się, jak go przekazać, jeśli potrzebujesz.
źródło