C# 将参数传递给Web API模型绑定器

C# 将参数传递给Web API模型绑定器,c#,asp.net-web-api,model-binding,C#,Asp.net Web Api,Model Binding,我正在尝试创建WebAPI模型绑定器,它将绑定javascript框架的网格组件发送的URL参数。 网格发送URL参数,指示标准页面、页面大小和JSON格式的分类器、过滤器和分组。 URL字符串如下所示: http://localhost/api/inventory?page=1&start=0&limit=10sort=[{"property":"partName","direction":"desc"},{"property":"partStatus","direction"

我正在尝试创建WebAPI模型绑定器,它将绑定javascript框架的网格组件发送的URL参数。 网格发送URL参数,指示标准页面、页面大小和JSON格式的分类器、过滤器和分组。 URL字符串如下所示:

http://localhost/api/inventory?page=1&start=0&limit=10sort=[{"property":"partName","direction":"desc"},{"property":"partStatus","direction":"asc"}]&group=[{"property":"count","direction":"asc"}]
所讨论的模型是库存,它具有简单的Count(int)属性和引用Part(Part)peoperty(反过来又具有名称、状态)。 视图模型/dto被展平(InventoryViewModel.Count、.PartName、.PartStatus等) 我使用then查询域模型,将结果映射到视图模型,并将其作为JSON发送回。 在模型绑定期间,我需要通过检查正在使用的模型和视图模型来构建表达式

为了保持模型绑定器的可重用性,我如何传递/指定正在使用的模型和视图模型类型? 我需要它来构建有效的排序、筛选和分组会话 注意:我不想将这些作为网格url参数的一部分传递

我的一个想法是使StoreRequest通用(例如StoreRequest),但我不确定model binder是否或如何工作

API控制器示例

// 1. model binder is used to transform URL params into StoreRequest. Is there a way to "pass" types of model & view model to it?
    public HttpResponseMessage Get(StoreRequest storeRequest)
    {
            int total;
            // 2. domain entites are then queried using StoreRequest properties and Dynamic Expression API (e.g. "Order By Part.Name DESC, Part.Status ASC")
            var inventoryItems = _inventoryService.GetAll(storeRequest.Page, out total, storeRequest.PageSize, storeRequest.SortExpression); 
            // 3. model is then mapped to view model/dto
            var inventoryDto = _mapper.MapToDto(inventoryItems);
            // 4. response is created and view model is wrapped into grid friendly JSON
            var response = Request.CreateResponse(HttpStatusCode.OK, inventoryDto.ToGridResult(total));
            response.Content.Headers.Expires = DateTimeOffset.UtcNow.AddMinutes(5);
            return response;
    }
StoreRequestModelBinder

public class StoreRequestModelBinder : IModelBinder
{
    private static readonly ILog Logger = LogManager.GetCurrentClassLogger();

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        Logger.Debug(m => m("Testing model binder for type: {0}", bindingContext.ModelType));
        if (bindingContext.ModelType != typeof(StoreRequest))
        {
            return false;
        }
        var storeRequest = new StoreRequest();
        // ----------------------------------------------------------------
        int page;
        if (TryGetValue(bindingContext, StoreRequest.PageParameter, out page))
        {
            storeRequest.Page = page;
        }
        // ----------------------------------------------------------------
        int pageSize;
        if (TryGetValue(bindingContext, StoreRequest.PageSizeParameter, out pageSize))
        {
            storeRequest.PageSize = pageSize;
        }
        // ----------------------------------------------------------------
        string sort;
        if (TryGetValue(bindingContext, StoreRequest.SortParameter, out sort))
        {
            try
            {
                storeRequest.Sorters = JsonConvert.DeserializeObject<List<Sorter>>(sort);
                // TODO: build sort expression using model and viewModel types
            } 
            catch(Exception e)
            {
               Logger.Warn(m=>m("Unable to parse sort parameter: \"{0}\"", sort), e);
            }
        }
        // ----------------------------------------------------------------
        bindingContext.Model = storeRequest;
        return true;
    }

    private bool TryGetValue<T>(ModelBindingContext bindingContext, string key, out T result)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(key);
        if (valueProviderResult == null)
        {
            result = default(T);
            return false;
        }
        result = (T)valueProviderResult.ConvertTo(typeof(T));
        return true;
    }
}
公共类StoreRequestModelBinder:IModelBinder
{
私有静态只读ILog Logger=LogManager.GetCurrentClassLogger();
public bool BindModel(HttpActionContext actionContext,ModelBindingContext bindingContext)
{
Debug(m=>m(“为类型{0}测试模型绑定器”,bindingContext.ModelType));
if(bindingContext.ModelType!=typeof(StoreRequest))
{
返回false;
}
var storeRequest=newstorerequest();
// ----------------------------------------------------------------
整版;
if(TryGetValue(bindingContext,StoreRequest.PageParameter,out page))
{
storeRequest.Page=Page;
}
// ----------------------------------------------------------------
int页面大小;
if(TryGetValue(bindingContext、StoreRequest.PageSizeParameter、out pageSize))
{
storeRequest.PageSize=页面大小;
}
// ----------------------------------------------------------------
字符串排序;
if(TryGetValue(bindingContext,StoreRequest.SortParameter,out-sort))
{
尝试
{
storeRequest.Sorters=JsonConvert.DeserializeObject(排序);
//TODO:使用模型和视图模型类型生成排序表达式
} 
捕获(例外e)
{
Warn(m=>m(“无法分析排序参数:\“{0}\”,sort),e);
}
}
// ----------------------------------------------------------------
bindingContext.Model=storeRequest;
返回true;
}
私有bool TryGetValue(ModelBindingContext、字符串键、out T结果)
{
var valueProviderResult=bindingContext.ValueProvider.GetValue(键);
if(valueProviderResult==null)
{
结果=默认值(T);
返回false;
}
结果=(T)valueProviderResult.ConvertTo(typeof(T));
返回true;
}
}

只需更改控制器签名,如

public HttpResponseMessage Get([ModelBinder(typeof(StoreRequestModelBinder)]StoreRequest storeRequest)

关于

只需更改控制器签名,如

public HttpResponseMessage Get([ModelBinder(typeof(StoreRequestModelBinder)]StoreRequest storeRequest)
问候