How to receive the view model in a GET request WebAPI?

2

Well, I have here a problem with my API and would like to ask for your help. I have a form here in Knockout JS, I do serialize from a constructor which in turn returns me a querystring so

  

API = Page = 1 & MinPrice = 185 & MaxPrice = 694

My problem is that the API does not understand what this is and returns it to me

{"message":"An error has occurred.","exceptionMessage":"Multiple actions were found that match the request: \r\nGet on type SiteMvc.Controllers.ProductAPIController\r\nGet on type SiteMvc.Controllers.ProductAPIController","exceptionType":"System.InvalidOperationException","stackTrace":"   em System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n   em System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   em System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}

ListVM

public class ListVM 
{

    public decimal? MinPrice { get; set; }

    public decimal? MaxPrice { get; set; }

    public int? CategoryID { get; set; }

    public int ProductType { get; set; }

}

API Controller

   public HttpResponseMessage Get(int page, [FromUri]ListVM vm)
            {

                CompanyManager m = new CompanyManager();
                HttpResponseMessage r = CheckEntryJson(m);
                if (r != null)
                    return r;

                ProductsBL bl = new ProductsBL(m.CompanyID);

                var query = bl.GetProducts();

                if (vm.MinPrice.HasValue)
                    query = query.Where(x => x.ProductStore.Price >= vm.MinPrice);
                if (vm.MaxPrice.HasValue)
                    query = query.Where(x => x.ProductStore.Price <= vm.MaxPrice);

                if (vm.CategoryID.HasValue)
                    query = query.Where(x => x.CategoryID == vm.CategoryID);




                Func<ProductType, string> getProductTypeName = x => x.ToName();

                var result = query.Select(x => new ProductAPIModel
                {

                    Name = x.Name,
                    TotalPrice = x.ProductStore == null ? 0 : x.ProductStore.TotalPrice,
                    ID = x.ProductID,
                    ProductType = getProductTypeName(x.ProductType),
                    Reference = x.Reference,
                    Description = x.Description

                });
     if (result == null) return Request.CreateResponse(HttpStatusCode.NotFound);

                var json = new
                {
                    Items = result.Skip(pageSize * (page - 1)).Take(pageSize).ToList(),
                    TotalItems = result.Count()
                };

                return Request.CreateResponse(HttpStatusCode.OK, json);
            }


        }

My goal is to make the API realize that these are model fields without having to resort to putting all the fields in hand as parameters and / or messing with the routes

Thank you in advance!

    
asked by anonymous 16.03.2016 / 13:21

2 answers

2

For those who have doubts, to solve this problem, I decided to abandon the RESTful of the API and to specify actions within them, I use gets, however in the specific razor in Url.Route to action and thus mvc already decipher the query string and compare it with the model

Routes

      config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{company}/{controller}/{action}/{id}",
        defaults: new { action = "Default", id = RouteParameter.Optional },
        constraints: new { company = @"\d+" } //Obriga a que o company seja um valor númerico
        );
    
16.03.2016 / 19:21
1

If you are using API 2+, you should use annotations in your actions. It looks more elegant and simpler to set up.

[RoutePrefix("/api/product")]
public class ProductApiController : ApiController
{
    [HttpGet] // Sempre é bom ser explícito
    [Route("{page}")]
    public HttpResponseMessage Get([FromUri] int page, [FromUri] ListVM vm) {...}
}
    
27.06.2016 / 15:14