Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC WebApi HttpGet with complex object

I have an existing WebApi action, that I want to switch from HttpPost to HttpGet. It currently takes a single complex object as parameter.

The model:

public class BarRequest
{
    [JsonProperty("catid")]
    public int CategoryId { get; set; }
}

The controller:

public class FooController : ApiController
{
    //[HttpPost]
    [HttpGet]
    [ActionName("bar")]
    public void Bar([FromUri] BarRequest request)
    {
        if (request != null)
        {
            // CategoryId should be 123, not 0
            Debug.WriteLine("Category ID :: {0}", request.CategoryId);
        }
    }
}

Now when I send the following request, everything works as expected.

GET /foo/bar?CategoryId=123

Also the old POST request worked as expected.

POST /foo/bar {"catid":123}

But now I need the following request to work:

GET /foo/bar?catid=123

How can I accomplish this?

like image 212
Daniel Kuppitz Avatar asked Mar 25 '13 19:03

Daniel Kuppitz


People also ask

How do I pass complex objects to Web API?

Best way to pass multiple complex object to webapi services is by using tuple other than dynamic, json string, custom class. No need to serialize and deserialize passing object while using tuple. If you want to send more than seven complex object create internal tuple object for last tuple argument.

Can we use HTTPPost instead of HttpGet?

HTTPGet method is default whereas you need to specify HTTPPost attribute if you are posting data using HTTPPost method. 2. HTTPGet method creates a query string of the name-value pair whereas HTTPPost method passes the name and value pairs in the body of the HTTP request.

Can we use FromBody with HttpGet?

Please note that we are able to send [FromBody] parameter in HTTP GET Request input.

Can we declare FromBody attribute on multiple parameters?

The [FromBody] attribute can be applied on only one primitive parameter of an action method. It cannot be applied to multiple primitive parameters of the same action method.


2 Answers

Thanks for suggestions, but the only solution that works for me, is the following.

Before:

var data = {
    catid: 123,
    // <snip>
};
var json = JSON.stringify(data);
$.post('/foo/bar', json, callback);
public class FooController : ApiController
{
    [HttpPost, ActionName("bar")]
    public void Bar(BarRequest request)
    {
        // use request.Category to process request
    }
}

After:

var data = {
    catid: 123,
    // <snip>
};
var json = JSON.stringify(data);
$.get('/foo/bar?data=' + encodeURIComponent(json), callback);
public class FooController : ApiController
{
    [HttpGet, ActionName("bar")]
    public void Bar(string data)
    {
        var request = JsonConvert.DeserializeObject<BarRequest>(data);
        // use request.Category to process request
    }
}

This way I don't need to touch any model, validator, etc. on the client or server. Additionally every other solution required me to change the naming conventions on either the server or the client side.

like image 158
Daniel Kuppitz Avatar answered Oct 22 '22 02:10

Daniel Kuppitz


you can do it by using datacontracts and datamember attribute:

http://msdn.microsoft.com/en-us/library/ms733127.aspx

[DataContract]
public class BarRequest{  

   [DataMember(Name="catid")]  
    public int CategoryId { get; set; }
}

if it's a Post method

but with get method this is an example of structure for complex objects :

api/Bar?request.CategoryId =1&request.AnotherProp=foo
like image 25
Joan Caron Avatar answered Oct 22 '22 04:10

Joan Caron