进入控制器后进行后期绑定动态解析模型

joh*_*y 5 9 c# rest model-binding .net-core

我正在寻找一种在控制器中执行动作后解析模型的方法,描述问题的最简单方法是:

public DTO[] Get(string filterName)
{
    //How can I do this
    this.Resolve<MyCustomType>("MyParamName");
}
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找有关我为什么要这样做的更多信息,则可以继续阅读以获取完整信息。

TL; DR

我正在寻找一种解决模型请求的方法,给定一个始终从查询字符串中解析的参数名称,该如何从启动中动态注册过滤器。我有一个要处理注册过滤器的类。

在启动类中,我希望能够向我的restServices动态注册过滤器。我有一个用来传递给我的自定义ControllerFeatureProvider的选项,大致如下所示:

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;
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我的控制器将跟踪选项,并使用它们为分页端点和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>();
    }
}
Run Code Online (Sandbox Code Playgroud)

我在弄清楚如何动态解析给定HttpContext的模型时遇到了麻烦,我想做这样的事情来获取模型,但这是伪代码,不起作用

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);
}
Run Code Online (Sandbox Code Playgroud)

深入研究Source之后,我看到了一些有前途的东西ModelBinderFactoryControllerActionInvoker这些类在管道中用于模型绑定,

我希望公开一个简单的接口来从QueryString解析参数名称,如下所示:

ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");
Run Code Online (Sandbox Code Playgroud)

但是,我看到的从模型绑定器解析模型的唯一方法是创建伪造的控制器描述符并模拟大量内容。

如何将晚绑定参数接受到我的控制器中?

Ωme*_*Man 2

我同意你的想法

服务需要从获取列表中过滤数据,但我不想编写提供过滤器所需的全部服务

为什么要为每种可能的组合编写一个小部件/过滤器/端点?

只需提供基本操作即可获取所有数据/属性。然后使用 GraphQL 允许最终用户根据自己的需求进行过滤(建模) 。

来自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