2012-10-15 29 views
2

我正在尝试创建Web API模型绑定器,该绑定器将绑定由JavaScript框架的网格组件发送的URL参数。 网格发送指示标准页面,pageSize和JSON格式的分类器,过滤器和石斑的URL参数。 URL字符串看起来是这样的:将参数传递给Web API模型绑定器

http://localhost/api/inventory?page=1&start=0&limit=10sort=[{"property":"partName","direction":"desc"},{"property":"partStatus","direction":"asc"}]&group=[{"property":"count","direction":"asc"}] 

有问题的模型是库存它具有简单,计数(INT)财产和参考部分,(部分)peoperty(这反过来名称,状态)。 查看模型/ dto被展平(InventoryViewModel .Count,.PartName,.PartStatus等等) 然后我使用Dynamic Expression Api查询域模型,将结果映射到查看模型并将其作为JSON发回。 在模型绑定过程中,我需要通过检查正在使用的模型和视图模型来构建表达式。

为了保持模型联编程序可重用,我如何传递/指定模型和视图模型类型被使用? 我需要这个为了构建有效的排序,筛选和分组experssions 注意:我不想传递这些作为网格url params的一部分!

我的一个想法是让StoreRequest成为通用的(例如StoreRequest),但我不确定模型绑定器是否可行或如何工作。

样品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; 
    } 
} 

回答

0

只是改变你的控制器的签名像

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

问候