4

When I have this method in an MVC Controller

[HttpPost]
public async Task<ActionResult> MyMethod(int param1, string param2)
{
   //....
}

I can send a Json object {param1:1, param2:"str"} it works just fine and parameters are resolved. However when I do this for a WebApi 2 it doesn't work. Because [FromBody] can only be used by 1 parameter according to following example on documentation.

At most one parameter is allowed to read from the message body
    // Caution: Will not work!    
    public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

How can we obtain the same behavior of MVC controller from WebApi controller?

Edit: Creating corresponding classes and replacing parameters is not an option, because a messaging tool checks these methods for maintenance. Signatures should remain the same.

3
  • You edit provides not possible task - max one parameter can be read from body as: "The reason for this rule is that the request body might be stored in a non-buffered stream that can only be read once." Commented Sep 16, 2016 at 10:00
  • @VadimLevkovsky You are absolutely right.However, since the signature stays the same, I just made the method accept both GET and POST. When we send GET with paramters in url, it works. Commented Sep 16, 2016 at 10:04
  • 1
    not being able to do this is a pain in the bum Commented Mar 8, 2018 at 12:55

3 Answers 3

6

Try to compose one object from these values:

public class Foo
{
    public int id {get;set;}
    public int name {get;set;}
}

public HttpResponseMessage Post([FromBody] Foo foo) 
{
    //some stuff...
}

If signature should remain the same, you can try to specify params in url, like that: myurl?id=1&name=Tom still via POST verb.

Sign up to request clarification or add additional context in comments.

1 Comment

Signature should remain the same because a messaging infrastructure checks those controller methods time to time. I'll edit my question with this detail.
4

You can try like this:

public HttpResponseMessage Post([FromBody]dynamic value)
{
    int id= value.id.ToString();
    string name = value.name.ToString();
}

And pass json like following

{
  "id":"1",
  "name":"abc"
}

3 Comments

Don't use dynamic for such things, as you usually know what data you get from front-end.
Yes, but if you don't wont to create new class for just passing value to the one method, and you have many methods in a controller, so what will you do?
I do create classes. All requests/responses are something that may have semantical (or even physical) value - domain objects. Why don't expose them explicitly as classes? If there are lot of classes that has no meaning - I'd treat it as code smell and think about API refactoring .
1

If you have to pass multiple parameter please use class object:

public class PortalClass
{
    public ApplicationModel applicationModel { get; set; }
    public string user_id { get; set; }
    public string id { get; set; }
    public object pageCollection { get; set; }
}

public object GetApplication(PortalClass data)
{
    JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, PreserveReferencesHandling = PreserveReferencesHandling.None };
    var myObject=JsonConvert.DeserializeObject<PageCollection>(data.pageCollection.ToString(), settings)
    return null;
}

Client Side:

var data = {
    user_id: userId,
    id: id
};

http.post(url, data).then(
   function (response) {

}, function (err) {
   callback.reject(err);
});

1 Comment

Signature should remain the same because a messaging infrastructure checks those controller methods time to time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.