2

JavaScript フレームワークのグリッド コンポーネントによって送信された URL パラメーターをバインドする Web API モデル バインダーを作成しようとしています。Grid は、標準のページ、pageSize、および JSON 形式のソーター、フィルター、グルーパーを示す URL パラメーターを送信します。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 (名前、ステータスを持つ) を持つ Inventory です。ビュー モデル/dto はフラット化されます (InventoryViewModel .Count、.PartName、.PartStatus など)。Dynamic Expression Apiを使用してドメイン モデルにクエリを実行し、結果をビュー モデルにマップして、JSON として送り返します。モデルのバインド中に、使用されているモデルとビュー モデルを調べて式を作成する必要があります。

モデル バインダーを再利用可能な状態に保つために、使用されているモデルとビュー モデル タイプを渡す/指定するにはどうすればよいですか? 有効な並べ替え、フィルター、およびグループ化の expsessions を構築するためにこれが必要です。注: これらをグリッド URL パラメーターの一部として渡したくありません!

私が持っていた 1 つのアイデアは、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;
    }
}
4

1 に答える 1

0

次のようにコントローラーの署名を変更するだけです

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

よろしく

于 2016-07-22T12:09:16.777 に答える