Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular POST to Web API doesn't pass data

I've been writing code against ASP.NET Web API for a while now with jQuery and I'm starting something new in Angular (writing against the same Web API backend.)

I'm POSTing to a method that will return some search results for an entity in the system. It looks like this:

public IEnumerable<dynamic> Post(string entity, FormDataCollection parameters)
{
    // entity is passed on the route.
    // parameters contains all the stuff I'm trying to get here.
}

If I call the method using jQuery.post:

$.post('api/search/child', {where : 'ParentID = 1'}, function(d){ foo = d });

it works just right and returns what I would expect.

I've made a service in my angular application that makes a similar call:

$http.post('api/search/child', { where: 'parentID = ' + parent.ID })
.success(function (data, status, headers, config) {
    // etc.
})

But when it hits my "Post" method on the server, "paramters" is null.

After some googling I've tried adding a content-type header to ensure it's passed as JSON, and trying JSON.stringify-ing and $.param()-ing the "data" argument, but that didn't do anything (and from what I've read that shouldn't be necessary.) What am I doing wrong here? Thanks for your help!

UPDATE: Here's the raw request from the (working) jQuery example:

POST http://localhost:51383/api/search/child HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:51383
Content-Length: 23
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: (etc)
Authorization: (etc)

where=ParentID+%3D+1

And the raw request from the (failing) Angular sample:

POST http://localhost:51383/api/search/parent HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json, text/plain, */*
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 27
DNT: 1
Host: localhost:51383
Pragma: no-cache
Cookie: (etc)

{"where":"ScorecardID = 1"}

Very weird. Even when I add the 'json' data type parameter to the end of the jQuery call, it still creates the www-form-urlencoded request. And that's the one that works. My Web API application is already set up for JSON (but thank-you Dalorzo).

like image 802
James Orr Avatar asked May 29 '14 04:05

James Orr


3 Answers

Check if you have included the JSON Formatter in your configuration. It should be something like :

    System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
    config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());

The Content-Type=application/json only will work if you set the proper formatter.

You can also try using [FromBody] next to your parameter type.

like image 117
Dalorzo Avatar answered Sep 22 '22 18:09

Dalorzo


Solved! Discovered this question:

AngularJs $http.post() does not send data

Pointing to this lovely article:

http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

Turns out Angular doesn't post data the same way jQuery does but you can override it with some tweaking.

like image 35
James Orr Avatar answered Sep 23 '22 18:09

James Orr


I solved this by below codes:

Client Side:

     $http({
                url: me.serverPath,
                method: 'POST',
                data: data,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }).
                success(function (serverData) {
                    console.log("ServerData:", serverData);
    ......

Notice that data is an object.

On the server (ASP.NET MVC):

[AllowCrossSiteJson]
        public string Api()
        {
            var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
            if (data == null) return "Null Request";
            var bl = Page.Bl = new Core(this);

            return data.methodName;
        }

and 'AllowCrossSiteJsonAttribute' is needed for cross domain requests:

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }
like image 26
pixparker Avatar answered Sep 24 '22 18:09

pixparker