ASP.NET MVC 4 Web API has limited support to map POST form variables to simple parameters of a Web API method. Web API does not deal with multiple posted content values, you can only post a single content value to a Web API Action method. This post explains the different ways to pass multiple parameters to Web API method.

Suppose You have following Web API method:

public HttpResponseMessage PostProduct(int Id,String Name,String Category, decimal Price)
{
		//...
}

and you are trying to call using jQuery:

  $.ajax({

  url: 'api/products',
  type: 'POST',
  data: { Id: 2012, Name: 'test', Category: 'My Category', Price: 99.5 },
  dataType: 'json',
  success: function (data) {
 alert(data);
 }

 }); 

Unfortunately, Web API can’t handle this request and you’ll get error. But if you pass parameters using query string, It’ll work:

 $.ajax({

  url: 'api/products?Id=2012&Name=test&Category=My%20Category&Price=99.5',
  type: 'POST',                
  dataType: 'json',
  success: function (data) {
  alert(data);
   }

  }); 

But it’s not good solution and not applicable for complex objects. So here are the different ways to do it.

Using Model Binding:

Model: Create a model having all parameters to be passed

 public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }

Controller: Use the model as argument type in the method

public HttpResponseMessage PostProduct(Product item)
 {
     item = repository.Add(item);
     var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
     string uri = Url.Link("DefaultApi", new { id = item.Id });
     response.Headers.Location = new Uri(uri);
     return response;
 }

jQuery:

 $.ajax({
  url: 'api/products',
  type: 'POST',
  data: { Id: 2012, Name: 'test', Category: 'My Category', Price: 99.5 },
  dataType: 'json',
  success: function (data) {
                    ...
   }
 }); 

OR

  var product = {
             Id: 2012, Name: 'test', Category: 'My Category', Price: 99.5 
 }

 $.ajax({
  url: 'api/products',
  type: 'POST',
  data: JSON.stringify(product),
  dataType: 'json',
  contentType: "application/json",
  success: function (data) {

  }
 });

Using Custom Parameter Binding:

ASP.NET Web API provides to create a custom Parameter Binding to extend the functionality and allows you to intercept processing of individual parameters. Check Rick’s Post to implement it.

JObject:

Web API now uses JSON.NET for it’s JSON serializer, So you can use the JObject class to receive a dynamic JSON result, cast it properly or parse it into strongly typed objects.

 public HttpResponseMessage PostProduct(JObject data)
        {
            dynamic json = data;
            Product item = new Product() { 
                Id = json.Id, 
                Name = json.Name, 
                Category = json.Category, 
                Price =json.Price 
            }; 
            item = repository.Add(item);
            var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
            string uri = Url.Link("DefaultApi", new { id = item.Id });
            response.Headers.Location = new Uri(uri);
            return response;
        }

OR

You can directly parse it into strongly typed class:

 public HttpResponseMessage PostProduct(JObject data)
        {

            Product item = data.ToObject<Product>();  
            item = repository.Add(item);
            var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
            string uri = Url.Link("DefaultApi", new { id = item.Id });
            response.Headers.Location = new Uri(uri);
            return response;
        }

FormDataCollection:

You can define FormDataCollection type argument and read parameter one by one manually using .Get() or .GetValues() methods (for multi-select values).

data: { Id: 2012, Name: ‘test’, Category: ‘My Category’, Price: 99.5 },

For above data:

 public HttpResponseMessage PostProduct(FormDataCollection data)
        {
            Product item = new Product() { 
                Id = Convert.ToInt32(data.Get("Id")), 
                Name = data.Get("Name"), 
                Category = data.Get("Category"), 
                Price = Convert.ToDecimal(data.Get("Price")) 
            }; 
            item = repository.Add(item);
            var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
            string uri = Url.Link("DefaultApi", new { id = item.Id });
            response.Headers.Location = new Uri(uri);
            return response;
        }

Query String:

We have seen to access multiple parameters from query string easily. It’s very helpful when you have to pass Model with additional parameters. So the additional parameters can be passed using query string.

Controller:

   public HttpResponseMessage PostProduct(Product item, string criteria)
        {
		//...
		}

jQuery:

 $.ajax({
   url: 'api/products?criteria=full',
   type: 'POST',
   data: JSON.stringify(product),
   dataType: 'json',
   contentType: "application/json",
   success: function (data) {
                }
            });

You can parse your query string explicitly in method If you have too many query string values to push into parameters.

  public HttpResponseMessage PostProduct(Product item)
        {           
            var queryItems = Request.RequestUri.ParseQueryString();
            string criteria = queryItems["criteria"];
			//...
	}

Return Multiple Parameters:

Now, the next question is how to return multiple parameters. First thing is to use Model having all parameters and return its instance, but each time we can’t create model for each return type. If all parameters have same data-type then we can create and return a collection. But it might be different data-types. The simplest solution is use dynamic return type.

 public dynamic GetProducts()
        {
            var products = repository.GetAll() as IEnumerable<Product>; 
            return new
            {
               Products = products,
               Criteria = "full"
            };
        }

Here is the response:

multiple return type Passing Multiple Parameters to ASP.NET Web API With jQuery

Share your opinion how you are passing multiple parameters to Web API. Hopefully, this behavior can be enabled in future release without being a breaking change.

Comments:  7

  • Sapozhnikov Alexey

    Very helpful post! Thanks for sharing your knowledge. Now I understand how to post complex objects to WebApi controller.

  • Pradeep

    Nice One!

  • Hallgeir Engen

    Very good article :-)

  • Brett Bullard

    Great Article. In my particular scenario, I needed to post a complex datatype, a complex array, and an array of strings all at once. I found creating a “dummy” class in my model, that is really never used was the best way. My dummy class included all the datatypes I needed, and it worked great.

  • Muhammad Naveed

    Is there possible to POST multiple Complex type parameter to Controller from your AJAX?

  • Amir Hosein Jelodari

    thanx for your awesome post :X … It’s very helpful

  • vgs naidu

    Good one