Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Passing multiple POST parameters to Web API Controller Methods


:P
On this page:

ASP.NET Web API introduces a new API for creating REST APIs and making AJAX callbacks to the server. This new API provides a host of new great functionality that unifies many of the features of many of the various AJAX/REST APIs that Microsoft created before it - ASP.NET AJAX, WCF REST specifically - and combines them into a whole more consistent API. Web API addresses many of the concerns that developers had with these older APIs, namely that it was very difficult to build consistent REST style resource APIs easily.

While Web API provides many new features and makes many scenarios much easier, a lot of the focus has been on making it easier to build REST compliant APIs that are focused on resource based solutions and HTTP verbs. But  RPC style calls that are common with AJAX callbacks in Web applications, have gotten a lot less focus and there are a few scenarios that are not that obvious, especially if you're expecting Web API to provide functionality similar to ASP.NET AJAX style AJAX callbacks.

RPC vs. 'Proper' REST

RPC style HTTP calls mimic calling a method with parameters and returning a result. Rather than mapping explicit server side resources or 'nouns' RPC calls tend simply map a server side operation, passing in parameters and receiving a typed result where parameters and result values are marshaled over HTTP. Typically RPC calls - like SOAP calls - tend to always be POST operations rather than following HTTP conventions and using the GET/POST/PUT/DELETE etc. verbs to implicitly determine what operation needs to be fired.

RPC might not be considered 'cool' anymore, but for typical private AJAX backend operations of a Web site I'd wager that a large percentage of use cases of Web API will fall towards RPC style calls rather than 'proper' REST style APIs. Web applications that have needs for things like live validation against data, filling data based on user inputs, handling small UI updates often don't lend themselves very well to limited HTTP verb usage. It might not be what the cool kids do, but I don't see RPC calls getting replaced by proper REST APIs any time soon.  Proper REST has its place - for 'real' API scenarios that manage and publish/share resources, but for more transactional operations RPC seems a better choice and much easier to implement than trying to shoehorn a boatload of endpoint methods into a few HTTP verbs.

In any case Web API does a good job of providing both RPC abstraction as well as the HTTP Verb/REST abstraction. RPC works well out of the box, but there are some differences especially if you're coming from ASP.NET AJAX service or WCF Rest when it comes to multiple parameters.

Action Routing for RPC Style Calls

If you've looked at Web API demos you've probably seen a bunch of examples of how to create HTTP Verb based routing endpoints. Verb based routing essentially maps a controller and then uses HTTP verbs to map the methods that are called in response to HTTP requests. This works great for resource APIs but doesn't work so well when you have many operational methods in a single controller. HTTP Verb routing is limited to the few HTTP verbs available (plus separate method signatures) and - worse than that - you can't easily extend the controller with custom routes or action routing beyond that.

Thankfully Web API also supports Action based routing which allows you create RPC style endpoints fairly easily:

RouteTable.Routes.MapHttpRoute(
    name: "AlbumRpcApiAction",
    routeTemplate: "albums/**{action}**/{title}",
    defaults: new {
        title = RouteParameter.Optional,
        controller = "AlbumApi",
        **action =** **"GetAblums"** }
);

This uses traditional MVC style method routing which is different from the HTTP verb based routing you might have read a bunch about in conjunction with Web API. Action based routing like above lets you specify an end point method in a Web API controller either via the parameter in the route string or via a default value for custom routes.

Using routing you can pass multiple parameters either on the route itself or pass parameters on the query string, via ModelBinding or content value binding. For most common scenarios this actually works very well. As long as you are passing either a single complex type via a POST operation, or multiple simple types via query string or POST buffer, there's no issue. But if you need to pass multiple parameters as was easily done with WCF REST or ASP.NET AJAX things are not so obvious.

Web API has no issue allowing for single parameter like this:

RouteTable.Routes.MapHttpRoute(
    name: "AlbumRpcApiAction",
    routeTemplate: "albums/**{action}**/{title}",
    defaults: new {
        title = RouteParameter.Optional,
        controller = "AlbumApi",
        **action =** **"GetAblums"** }
);

There are actually two ways to call this endpoint:

albums/PostAlbum

Using the Model Binder with plain POST values

In this mechanism you're sending plain urlencoded POST values to the server which the ModelBinder then maps the parameter. Each property value is matched to each matching POST value. This works similar to the way that MVC's  ModelBinder works. Here's how you can POST using the ModelBinder and jQuery:

$.ajax(
{
    url: "albums/PostAlbum",
    **type: "POST",**
    **data: { AlbumName: "Dirty Deeds", Entered: "5/1/2012" },
**  success: function (result) {
  alert(result);
    },
    error: function (xhr, status, p3, p4) {
        var err = "Error " + " " + status + " " + p3;
        if (xhr.responseText && xhr.responseText[0] == "{")
            err = JSON.parse(xhr.responseText).message;
        alert(err);
    }
});

Here's what the POST data looks like for this request:

FireBug

The model binder and it's straight form based POST mechanism is great for posting data directly from HTML pages to model objects. It avoids having to do manual conversions for many operations and is a great boon for AJAX callback requests.

Using Web API JSON Formatter

The other option is to post data using a JSON string. The process for this is similar except that you create a JavaScript object and serialize it to JSON first.

album = {
    AlbumName: "PowerAge",
    Entered: new Date(1977,0,1)
}
$.ajax(
{
    url: "albums/PostAlbum",
    type: "POST",
    **contentType: "application/json",
**    **data: JSON.stringify(album),
**    success: function (result) {
        alert(result);
    }
});

Here the data is sent using a JSON object rather than form data and the data is JSON encoded over the wire.

JsonPost

The trace reveals that the data is sent using plain JSON (Source above), which is a little more efficient since there's no UrlEncoding that occurs.

BTW, notice that WebAPI automatically deals with the date. I provided the date as a plain string, rather than a JavaScript date value and the Formatter and ModelBinder both automatically map the date propertly to the Entered DateTime property of the Album object.

Passing multiple Parameters to a Web API Controller

Single parameters work fine in either of these RPC scenarios and that's to be expected. ModelBinding always works against a single object because it maps a model. But what happens when you want to pass multiple parameters?

Consider an API Controller method that has a signature like the following:

[HttpPost]
public string PostAlbum(Album album, string userToken)

Here I'm asking to pass two objects to an RPC method. Is that possible? This used to be fairly straight forward either with WCF REST and ASP.NET AJAX ASMX services, but as far as I can tell this is not directly possible using a POST operation with WebAPI.

There a few workarounds that you can use to make this work:

Use both POST and QueryString Parameters in Conjunction

If you have both complex and simple parameters, you can pass simple parameters on the query string. The above would actually work with:

/album/PostAlbum?userToken=sekkritt

but that's not always possible. In this example it might not be a good idea to pass a user token on the query string though. It also won't work if you need to pass multiple complex objects, since query string values do not support complex type mapping. They only work with simple types.

Use a single Object that wraps the two Parameters

If you go by service based architecture guidelines every service method should always pass and return a single value only. The input should wrap potentially multiple input parameters and the output should convey status as well as provide the result value. You typically have a xxxRequest and a xxxResponse class that wraps the inputs and outputs.

Here's what this method might look like:

public PostAlbumResponse PostAlbum(PostAlbumRequest request)
{
    var album = request.Album;
    var userToken = request.UserToken;

    return new PostAlbumResponse()
    {
         IsSuccess = true,
         Result = String.Format("{0} {1:d} {2}", album.AlbumName, album.Entered,userToken)
    };
}

with these support types:

public class PostAlbumRequest {
    public Album Album { get; set; }
    public User User { get; set; }
    public string UserToken { get; set; }
}

public class PostAlbumResponse {
    public string Result { get; set; }
    public bool IsSuccess { get; set; }
    public string ErrorMessage { get; set; }
}

To call this method you now have to assemble these objects on the client and send it up as JSON:

var album = {
    AlbumName: "PowerAge",
    Entered: "1/1/1977" }
var user = {
    Name: "Rick" }
var userToken = "sekkritt";

$.ajax(
{
    url: "samples/PostAlbum",
    type: "POST",
    contentType: "application/json",
    **data: JSON.stringify({ Album: album, User: user, UserToken: userToken }),**
    success: function (result) {
        alert(result.Result);
    }
});

I assemble the individual types first and then combine them in the data: property of the $.ajax() call into the actual object passed to the server, that mimics the structure of PostAlbumRequest server class that has Album, User and UserToken properties.

This works well enough but it gets tedious if you have to create Request and Response types for each method signature. If you have common parameters that are always passed (like you always pass an album or usertoken) you might be able to abstract this to use a single object that gets reused for all methods, but this gets confusing too: Overload a single 'parameter' too much and it becomes a nightmare to decipher what your method actual can use.

Use JObject to parse multiple Property Values out of an Object

If you recall, ASP.NET AJAX and WCF REST used a 'wrapper' object to make default AJAX calls. Rather than directly calling a service you always passed an object which contained properties for each parameter:

{ parm1: Value, parm2: Value2 }

WCF REST/ASP.NET AJAX would then parse this top level property values and map them to the parameters of the endpoint method.

This automatic type wrapping functionality is no longer available directly in Web API, but since Web API now uses JSON.NET for it's JSON serializer you can actually simulate that behavior with a little extra code. You can use the JObject class to receive a dynamic JSON result and then using the dynamic cast of JObject to walk through the child objects and even parse them into strongly typed objects.

Here's how to do this on the API Controller end:

var album = {
    AlbumName: "PowerAge",
    Entered: "1/1/1977" }
var user = {
    Name: "Rick" }
var userToken = "sekkritt";

$.ajax(
{
    url: "samples/PostAlbum",
    type: "POST",
    contentType: "application/json",
    **data: JSON.stringify({ Album: album, User: user, UserToken: userToken }),**
    success: function (result) {
        alert(result.Result);
    }
});

This is clearly not as nice as having the parameters passed directly, but it works to allow you to pass multiple parameters and access them using Web API.

JObject is JSON.NET's generic object container which sports a nice dynamic interface that allows you to walk through the object's properties using standard 'dot' object syntax. All you have to do is cast the object to dynamic to get access to the property interface of the JSON type.

Additionally JObject also allows you to parse JObject instances into strongly typed objects, which enables us here to retrieve the two objects passed as parameters from this jquery code:

var album = {
    AlbumName: "PowerAge",
    Entered: "1/1/1977" }
var user = {
    Name: "Rick" }
var userToken = "sekkritt";

$.ajax(
{
    url: "samples/PostAlbum",
    **type: "POST",
    contentType: "application/json",**
    data: JSON.stringify({ Album: album, User: user, UserToken: userToken }),
     success: function (result) {
        alert(**result**);
    }
});

Summary

ASP.NET Web API brings many new features and many advantages over the older Microsoft AJAX and REST APIs, but realize that some things like passing multiple strongly typed object parameters will work a bit differently. It's not insurmountable, but just knowing what options are available to simulate this behavior is good to know.

Now let me say here that it's probably not a good practice to pass a bunch of parameters to an API call. Ideally APIs should be closely factored to accept single parameters or a single content parameter at least along with some identifier parameters that can be passed on the querystring. But saying that doesn't mean that occasionally you don't run into a situation where you have the need to pass several objects to the server and all three of the options I mentioned might have merit in different situations.

For now I'm sure the question of how to pass multiple parameters will come up quite a bit from people migrating WCF REST or ASP.NET AJAX code to Web API. At least there are options available to make it work.

Posted in Web Api  

The Voices of Reason


 

Paul Speranza
May 09, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Thanks Rick. I haven't worked with Web API yet but I'll bet you just saved me a lot of hair pulling.

magellings
May 09, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

JObject in particular looks very handy. I love how the client/server interaction is so simple with this new Web API. It doesn't get much easier than passing a JSON string and then parsing it out. It also really promotes cross-platform/language interoperability (as HTTP REST naturally does).

BackToFuture
May 09, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

For me the JSON.Stringify does not work it returns null movie and 01/01/0001 as date

Rick Strahl
May 09, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@BackToTheFuture - what browser are you using? If you're running older browsers you'll have to add json2.js to your script includes. Newer browsers (IE9, FF, Chrome, Opera) all support native JSON conversion. Note it's also case sensitive so the method JSON.stringify().

Jonathan
May 15, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

How would you make a call to this type of Web API from a WinForms app? Is that even possible. Thanks.

Jonathan

Rick Strahl
May 15, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@Jonathan - sure. You need to be able to JSON encode - meaning you need Json.net or System.Json to provide the parsing. The new System.Net.Http library also includes a host of methods that make it easy to call JSON and XML endpoints and provide the type marshalling required to use the data sent and returned more easily.

Tim VanFosson
May 23, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

What about using the [FromBody] attribute on the method signature to indicate that the UserToken is coming from the body instead of the url?

public string PostAlbum(Album album, [FromBody]string userToken) { ... }


I've used the [FromUri] attribute to indicate that a complex model is being passed as query parameters. I don't know why it wouldn't work the other way around.

Rick Strahl
May 23, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@Tim - unfortunately no. You can't mix strong parameters and from body parameters because thecontent types would be mixed up. You can do either or, but not both AFAIK. [FromBody] looks for POST variables OR a JSON object with parameters, but you can't pass both.

Chris
May 25, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Nice article, love the AC/DC test data, keep on rockin!

Srinivas Korvi
July 31, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Thanks Rick. I have recently started working on web api. Now, i have a question on how to pass custom object to a web api Get method(basically for filtering the data based on the input criteria).

What would be the right approach for this scenario?

Currently, i am passing custom data in the body using the request type post. if i pass the same thing in the Url querystring (but i think querystring has a length limit?).

Please suggest?

Rick Strahl
July 31, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Ah, but that's the beauty of Web API. You can create a single method that takes an object input and pass data to it in a variety of ways: ModelBinding via POST or QueryString data, or via a complete JSON POST operation from jQuery et al.

So a method like this:

[HttpGet,HttpPost]
public HttpResponseMessage PostAlbum(Album album)


can receive data as a JSON object or POST or QueryString Modelbinding data that matches the property names (including child objects) of the Album object.

For an introduction on how you can pass data to Web API check out my Code Magazine Intro Article at: http://www.code-magazine.com/Article.aspx?quickid=1206081.

David
August 04, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Rick,

thanks for the article - just a few ideas:

1. How about passing the security token as a cookie along with the request..?

2. Using compound objects - the equivalent of ViewModels in MVC.

3. My confusion about Web API is really where it fits into a layered architecture - e.g. separate DAL, Business Object Layer, Business Service Layer (contains all Business Logic), Service Layer (traditionally I would use WCF so it could expose multiple endpoints in different formats as required), then UI with MVC.

At first sight it seems that the most proposed use of Web API is essentially moving the Model away from MVC - MVC just serves HTML and JavaScript, then the data is sent and received via Web API, not calls to Controllers / Actions. So why use Strongly Typed Views with all the server side model Validation etc etc built in, when you are just going to send it to WEB API and use whatever validation methods are available there. It looks to me that you would end up ignoring a lot of MVC functionality just to use WEB API...

I am new to WEB API - so any comments and constructive criticism are greatly appreciated...

Rick Strahl
August 04, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@David - I think everything stays the same as with MVC except the output is no HTML view. You're still using Models, and Controllers to return the... data, or HTTP 'view'.

I agree though. I've been trying to find the right place where Web API fits myself *in typical Web applications*. So far I've often ended up continuing to use MVC instead of Web API in HTML/AJAX applications, simply because it's easier to produce HTML when you need it (using Razor - I still use a lot of HTML feeds to the client in AJAX calls today).

I think where Web API really shines though is with 'real' APIs - services that need to serve only REST data which is becoming more and more common. SOAP still has its place but it's importance is starting to wane going forward I think. WCF provides the SOAP pieces but the HTTP pieces from WCF were not very good - and that's what Web API really addresses. The downside though is that it doesn't fit with WCFs pluggability - but then neither did WCF REST.

Ultimately I think Web API is best for two purposes:

* Full scale REST based Web APIs
* Single Page AJAX applications that essentially treat the server as a data service
* Quick way to create generic HTTP endpoints that simplify what HTTP Handlers do

Rick Strahl
August 04, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@David - Security token via Cookie. You can do that - Cookies are fully supported and you can access cookies via headers (or HttpContext if necessary for a few non-exposed HTTP props). ViewModels - again this is the same as MVC, all you're doing is skipping the 'View' in lieu of either the raw data or a custom HTTP message (HttpResponseMessage/HttpResponseMessage<T>). I don't think the code logic changes much regardless of whether you send API or HTML data using Web API or MVC respectively. What is different is that the real 'View' most likely lives on the client of the consuming application with Web API typically.

David
August 05, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@Rick,

Perhaps we are both seeing the same aspects of Web API that don't quite 'fit' neatly into an enterprise architecture that delivers both a web site and a consumable API, where you don't want to duplicate code.

I see a lot of merit in the combination of Knockout.js, client side templates and view models, calling Web API for a responsive UI, but sometimes late at night that still leaves me wondering why I would no longer be using some of the nice tooling and features that have evolved in MVC ;-)

But it's essential to explore and evaluate the different approaches to architecting an application.

So, I am reworking some of my custom View templates to include data-bind attributes for Knockout to work with. I keep my server side View Models in a separate project that can be referenced by the MVC UI and the Web API (which is now my *Service Layer*), and both of these are pretty 'dumb' and use ValueInjecter to map the View Models to Domain Objects, and call methods exposed by the *Business Service Layer* that work with these. That is essentially what I was doing before with an MVC Controller that simply spoke Json and passed any work on to the BSL.

But I'm still not completely happy with this.. Typically I have exposed a tightly defined set of interfaces for my Service Layer (e.g. one for integration with Dynamics AX, one for the Web UI, etc.), and then depending on the physical architecture, they are either called by a direct assembly reference or via WCF with endpoints that expose the relevant interface and are easily consumed. I could still do this, but it feels like it is getting messy...

I'll be following your posts with interest :-)

David
August 05, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

And apologies to all if I am spamming this thread! - shout at me if you must, and I will desist :-)

@Rick

Something else I have been looking at is unified authentication / authorisation (as well as all the other things such as unified error handling, logging etc) in an architecture that involves a consumable API for broad reach, and yet also a Web UI for 'core usage'. Now, in my 'ideal world' architecture, I want client side validation (dont get me started on localisation), but server side authentication, authorisation and validation is also of course a must-have.

With some sort of membership and profile backend - so far I have used either a custom provider or used Code First Membership with some extra properties - this was good enough to provide security on the MVC side and any exposed WCF service that was normally consumed by say, BizTalk or Dynamics.

But with the Web API / Web UI combined approach, it is more appropriate to use a claims-based security approach.

Just another area where I see a slight mismatch between Web API and more common traditional MVC web sites that needs some thought to implement.

David

Rick Strahl
August 05, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@David - I'll be posting a separate post on where Web API fits. FWIW, I don't have all the answers, I'm still trying to figure out where and when it fits best myself. I think there are a few slam-dunk scenarios (like true 'APIs', or pure SPA style application backends), but for mixed Web AJAX/Service apps it gets a bit wishy washy. For mainly HTML based sites that use some AJAX functionality I often prefer to keep my service calls with the MVC controllers precisely because they can share the same logic and eco-system with the rest of the application. Using Web API would duplicate a lot of that (which might be OK in some cases, but not worth it for me).

The other glaring issue for me is that I occasionally serve HTML via AJAX rather than raw data and for that Web API currently is not so good, especially again if you need to share Views with plain MVC. You can use RazorEngine or something like it, but it's not integrated in the same way and the syntax varies from what's plugged directly into MVC.

As to authentication - what you use in MVC should also work with Web API. Assuming you have a way on the client to track cookies/authentication tokens in headers (typically by capture and forward) you don't have to reinvent the wheel. Claims based security (oAuth) can be nice but IMHO is often a pain in the ass for both users and developers. The only advantage I see in that is that it lets users use existing account info rather than having to set up yet another security id.

Be interesting to hear where we're headed with this after RTM.

Rick Strahl
August 07, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@David -

>> I see a lot of merit in the combination of Knockout.js, client side templates and view models, calling Web API for a responsive UI, but sometimes late at night that still leaves me wondering why I would no longer be using some of the nice tooling and features that have evolved in MVC ;-) <<

I can totally relate to that. In fact so much so that in the last mobile app I worked on we decided to serve HTML partials to the client for many things rather than sending down raw data to inject into the DOM on the client using templating etc. While there's more data going over the wire with this it's not enormously more, especially if you build atomic views and your can do initial compositional rendering server side.

The thing is that you get so much better infrastructure support on the server without having to screw around with 20 mismatched client libraries. With MVC and partials it's pretty easy to break out your HTML logic into small chunks so it's actually easy to create small rendering islands either via composition on the server, or by AJAX calls to small, tight partials called and injected by the client. It worked really well for the app we built and took a fraction of the time it would have took to build using pure JavaScript on the client. There's still plenty of jQuery and AJAX logic happening on the client but it's more manageable in small doses rather than trying to do the entire UI with JavaScript or creaky client script engines/templates that are hard to debug.

I don't think this is a solution for every app, but for many read-mostly apps that I build this type of approach seems to work very well.

David
August 08, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@Rick

I agree...

I did combine these approaches on a recent project that included a product configurator, with descriptions in multiple languages, product variations etc. Many items were optional, but if they were added, they had several fields that then needed validation (client side too). Product configurators with full create / update / delete options in multiple languages and currencies etc. are a good test of an architecture!

I created a single page wizard, which had multiple jQuery templates defined simply as JavaScript functions and variables, and then the actual HTML content of the template was rendered from a strongly typed Partial - not via AJAX but at the time the page was rendered.

The client side script was then mostly reacting to button clicks such as 'Add Variation' which then rendered the template with a unique GUID created client side as an identifier, and the unobtrusive JavaScript validation still worked on a per item and per field basis, thanks to a server side Collection extension written by someone smarter than me :-) I used some LinQ extension methods with custom comparers to find out which of the possible combinations of items was added, updated or deleted.

The combination did work well, and I could see the effort being worthwhile for high volume sites / limited bandwidth clients, where a lot of client side interactions are only submitted once completed.

It still leaves me guessing why Web API would add anything to this... time to write some code and see what happens ;-)

Ricardo
November 18, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

Hi,
I'm working with ASP.NET MVC 4 and the last browser of chrome.
I define mi function:
data: JSON.stringify({ Persona: persona, Modo: modo }),
persona is a object and modo is string
but in the controller:
[HttpPost]
public ActionResult Grabar(Persona mPersona, string modo)
{

mPersona the value is null but I have data for modo.

Why I have null in mPersona>

Regards
Ricardo

Rick Strahl
November 18, 2012

# re: Passing multiple POST parameters to Web API Controller Methods

@Ricardo - You cannot post an object with any other parameters. Either you pass only a single object, or - using the formatter discussed here - you can pass multiple simple value parameters that are mapped to POST values.

WebAPI only allows for a single object parameter (and that's what you are actually passing in your JSON parameter - one object with two properties). Your object on the server should have a top level object that has Persona and Modo properties - it needs to match the JSON signature.

IOW, you need to create a wrapper object like this:

public class GrabarMessage
{
     public Persona mPersona { get; set;}
     public string modo {get; set; }
}


then your method should be:

public ActionResult Grabar(GrabarMessage message)
{
     Persona mPersona = message.mPersona;
     string modo = message.modo;
     ...
}


I believe the same is true in ASP.NET MVC 4 and JSON inputs. Note: It *does not* work like it did in MS AJAX (ASMX or WCF Web Services), which created wrapped parameter objects automatically.

Harald Mühlhoff
February 01, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

Thank you, Rick, for another useful article! I came up with solution #1 (use a single Object) but couldn't believe there wasn't a better way. Still not happy with solution #2 (JObject) but at least I know now what my options are ... Greetings to beautiful Maui - I've been lucky enough to have been there twice in my life.

Steve
April 09, 2013

# re: Passing multiple POST parameters to Web API Controller Methods


Thank you for the article, I think I'm close...

Trying to pass an object using GET:


    mwm_Request = {
        State: stateCode,
        checkYear: checkYear,
        payRate: payRate,
        payHours: payHours,
        totalTips: totalTips
    };
 
    $.ajax({
        url: "http://localhost:2781/api/mwm/CalcMWM",
        type: "GET",
        contentType: "application/json",
        data: JSON.stringify(mwm_Request),
        success: function (result) {
            alert(result)
        },
        error: function(xhr, ajaxOptions, thrownError){
            console.log("calc ERROR");
            showAlert(xhr.statusText + ":" + thrownError, "Error Calc Mofos");
        }
    }) ;


and,

            config.Routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "api/{controller}/{action}",
                defaults: new { id = RouteParameter.Optional }
            );


and finally (just testing here)...

        public CalcMWM_Response CalcMWM(CalcMWM_Request mwm_Request)
        {
            CalcMWM_Response mwm_Response = new CalcMWM_Response();
 
            mwm_Response.stateCode = mwm_Request.stateCode;
            mwm_Response.checkYear = mwm_Request.checkYear;
            mwm_Response.payRate = mwm_Request.payRate;
            mwm_Response.totalTips = mwm_Request.totalTips; 
            mwm_Response.makeUpAmt = 2.50;
            mwm_Response.payHours = mwm_Request.payHours;
 
            return mwm_Response;
 
        }


but no love. Get this:

http://localhost:2781/api/mwm/CalcMWM?{%22State%22:%22CA%22,%22checkYear%22:%222013%22,%22payRate%22:1,%22payHours%22:1,%22totalTips%22:1}

Steve
April 10, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

Progress:

Changed AJAX call to a POST.

Changed Route to:

            config.Routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "calc/{controller}/{action}",
                defaults: new 
                { controller = "MWM",
                  action = "CalcMWM"                                  
                }
            );


Added the following to web.config to make Chrome happy:

    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>


CalcMWM() is called, however, get the following in my console log:

"Failed to load resource: the server responded with a status of 405 (Method Not Allowed)."

Andy
June 25, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

Steve,

I know this is a little back, but you need to uninstall Webdav or your server has allow put in webdav.

If you don't need webdav, then uninstalling it is the quicker and better method to go!

James Fallaw
August 26, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

What about if you want to issue a POST to a REST service that has a resource hierarchy, such as
http://blah.com/api/orders/7/items
with a post body that specifies the item to add to order 7. In that case, when the function would have to be something like
Post (int ordered, itemmodel item)

I can't make this work. I've seen some posts elsewhere on the net that indicate this can't be done with WebAPI without some really complex workaround. Has anyone got this working?

Rick Strahl
August 26, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

@James -  I think you need to do Post([FromUri] int orderId, Item item). You then should be able to capture both the route parm and the POST data for the item.

Melody
October 25, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

Hi,
Thanks for the article.
Cant we use multiple complex object with combined into single object to pass into WebAPI method?

Rick Strahl
October 25, 2013

# re: Passing multiple POST parameters to Web API Controller Methods

@Melody - No you can't at least not without writing custom message parsers.

Question is why would you? You can always use object composition to do this. REST isn't meant to be 'RPC' style messaging but document style messaging so you can pass in a 'message' that has two properties that are your two objects instead.

Milos
August 29, 2014

# re: Passing multiple POST parameters to Web API Controller Methods

I have problem with these example, where I pass multiple arguments into Controller, I get error "System.MissingMethodException: Cannot create an abstract class."
I use asp.net 4.5, Google Chorme browser.

Uikrosoft
May 05, 2015

# re: Passing multiple POST parameters to Web API Controller Methods

Hello Rick, how do you apply validation when passing multiple POST parameters to Web API Controller Methods?

Rick Strahl
May 05, 2015

# re: Passing multiple POST parameters to Web API Controller Methods

I do it in my business layer. I assign the values from parameters to data model and then the business layer validates before saving. If you're using Entity Framework there's a validation API that can be used and my business layer automatically checks any model validations at that time.

If you don't have that you'll have this level of abstraction you have to hook validation up manually. I suppose if you are explicitly passing POST values the assumption is that you don't have a lot of parameters - otherwise a model object makes a lot more sense. If there are just a few it's not difficult to do manual validation if your business layer doesn't already do it for you.

Personally I believe that validation should always go into the business layer and it just happens that MVC/Web API provide model validation externally. But ultimately not all data comes in through a full model update in an application, so you can't rely on that for all of your validation anyway, so a business layer that provides the validation is valuable.

FWIW, I'm using Westwind.Data (http://www.nuget.org/packages/Westwind.Data/) which is a thin layer around EF to provide simpler CRUD abstractions and Validation management for me. It's more of an internal library (meaning there's not a lot of documentation), but it's worked very well for me in a variety of projects large and small.

Keith
October 26, 2015

# re: Passing multiple POST parameters to Web API Controller Methods

I extended Rick's code to support parameters of any type, including custom complex objects. See here: https://github.com/keith5000/MultiPostParameterBinding

Thanks to Rick for this really informative blog post and for a great explanation of how parameter binding works.

prasanna
March 20, 2016

# re: Passing multiple POST parameters to Web API Controller Methods

Hi,
I want to pass model values to webclient.in a model there are nested model
like 1-{2-{3}}..i am trying to pass
DWMedicationDetails dwMedicationDetails = new DWMedicationDetails();
DWDoseModel dwDoseModelInfo = new DWDoseModel();
DWDoseIntakeRoasterModel dwDoseIntakeRoasterModelInfo = new DWDoseIntakeRoasterModel();
dwMedicationDetails.RowId = Guid.NewGuid();
dwMedicationDetails.Name = Name;
dwMedicationDetails.Note = Note;
dwMedicationDetails.UserId = UserId;
dwMedicationDetails.CreatedById = UserId;
dwMedicationDetails.CreatedOn = System.DateTime.Now;

dwDoseModelInfo.dwDoseIntakeRoasterModel = dwDoseIntakeRoasterModelInfo;
dwMedicationDetails.dwDoseModel = dwDoseModelInfo;
but at controller side i could get only dwMedicationDetails except nested model properties.
Please help me.

Arun
March 06, 2017

# re: Passing multiple POST parameters to Web API Controller Methods

Hi, Lovely post. I was searching for this for infinity. I made a tweek in getting the data as I had a model to receive one of the inputs. Changed var album = jalbum.ToObject(); To List jalbum1 = json.Input1.ToObject<List>();


Sudhanshu Shekhar
October 28, 2017

# re: Passing multiple POST parameters to Web API Controller Methods

Awesome post, Accessing post parameters with JObject resolved my issue.

Thanks


Ivan
February 13, 2018

# re: Passing multiple POST parameters to Web API Controller Methods

Which is the best way to handle a post to the webapi passing multiple parameters where one of them is a file?


Engin
February 14, 2018

# re: Passing multiple POST parameters to Web API Controller Methods

It's saying "Here's how to do this on the API Controller end:" but showing javascript code. I'm not seeing anywhere in the post how to set controller action parameters to utilize JObject.


Sundar
February 21, 2018

# re: Passing multiple POST parameters to Web API Controller Methods

Awesome, I was struggling to send string and a strongly typed param together to POST, thanks for your suggestion that POST can send simple string data as querystring and remaining model/entity as POST variable. I use ODATAController and this works for POST and PATCH to


Jaans
September 27, 2019

# re: Passing multiple POST parameters to Web API Controller Methods

We'll be moving to AspNet Core 2.x/3.x soon. Will this still be relevant / needed?


Rick Strahl
September 30, 2019

# re: Passing multiple POST parameters to Web API Controller Methods

@Jaans - yes the core APIs for all of this haven't changed, so this will still be applicable.


Bob Baldwin
May 19, 2020

# re: Passing multiple POST parameters to Web API Controller Methods

Hi Rick,

I know this is an old post, but I'm seeing the same thing that Engin is. This is an otherwise excellent post, but it currently is listing JavaScript code when you meant to list dynamic based C# Web API controller code. I'm pretty sure it uses dynamic and then uses JObject to parse it out. However, your code is the JavaScript side not the C# side. Can you list the C# code for the JObject based controller here or update the post above?

Thanks for your excellent help with us normal's

Bob Baldwin aka VSDotNetGuy


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024