22

I'm using an Angular $resource to post a model to a webapi endpoint, but Angular sends the data in the request payload, rather than a JSON body or form parameters. As a result, the model always ends up as null.

My API is as follows:

public class UserController : APIController {
    [HttpPost]
    public void Disconnect(Models.Users.User model) {
    }
}

The request headers are:

POST /siteapi/User/Disconnect HTTP/1.1
Host: rouge2
Connection: keep-alive
Content-Length: 125
Accept: application/json, text/plain, */*
Origin: http://rouge2
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Content-Type: application/json;charset=UTF-8
Referer: http://rouge2/Users
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: .ASPXAUTH=115C6015BDD5C1A9D111B0A9FBF05294B73287328566F65CB1BCB457DF206EF0916D4615B5914EB443AA567E860742AC14EAA2951B9C327260C4F00649694260A1B3960771FB6675FEE8F3E68B0BB46436020ACAB33ECE0D3E70B50D6569E52B27F69161762C10C19A806A12D3254DF60EF4758DEDCA529A91CB36C74B7FA7F4; __RequestVerificationToken=Rp4Vu8R67ziDNc36DoOLZH7KmEfumig1zFDmYiFWHTsWyf2I037xJQydcmLtOfaJ3ccc8GEZXmHoa8LBRusxKFRYVoy27GuFEfNhKKYS_hUysjwCjmsxw5OCK3RKsiXIAh1Gbi0PxcdqBfzctSJn9g2

And the request payload:

{"Id":3,"FirstName":"Test","LastName":"User","Username":"testuser","IsApproved":true,"IsOnlineNow":true,"IsChecked":true}

If I test in Fiddler, posting the same JSON string in the body, the model is correctly populated, as expected.

Is there a built-in model binder which will work in this scenario, or something pre-built somewhere I can use?

Or can someone please point me in the direction of a working example?

mattdwen
  • 5,288
  • 10
  • 47
  • 61
  • A sample to get started: http://www.codeproject.com/Articles/737030/A-basic-SPA-application-using-AngularJS-WebAPI-and – Braulio Jun 24 '14 at 13:46

2 Answers2

36

You could use the $http module.

Here's an example:

<!DOCTYPE html>

<html ng-app>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div ng-controller="TestController">
        <ul ng-model="person">
            <li>FirstName: {{person.FirstName}}</li>
            <li>LastName: {{person.LastName}}</li>
            <li>UserName: {{person.Username}}</li>
            <li>IsApproved: {{person.IsApproved}}</li>
            <li>IsOnlineNow: {{person.IsOnlineNow}}</li>
            <li>IsChecked: {{person.IsChecked}}</li>
        </ul>
    </div>

    <script type="text/javascript" src="~/scripts/angular.min.js"></script>
    <script type="text/javascript">
        function TestController($scope, $http) {
            var data = { "Id": 3, "FirstName": "Test", "LastName": "User", "Username": "testuser", "IsApproved": true, "IsOnlineNow": true, "IsChecked": true };
            $http.post(
                '/api/values',
                JSON.stringify(data),
                {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }
            ).success(function (data) {
                $scope.person = data;
            });
        }
    </script>
</body>
</html>

Assuming the following controller:

public class ValuesController : ApiController
{
    [HttpPost]
    public User Post(User model)
    {
        return model;
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    It appears that WebAPI also expects the posted data to be wrapped as a 'User' object also, e.g. {User: {data}}. – mattdwen May 21 '13 at 08:15
  • @mattdwen I don't think it will if you use `[FromBody]` although I swear I don't do that and it still works fine without that. – kamranicus Aug 28 '13 at 20:19
  • 1
    What if you wanted or *needed* to use $resource? What would be the cleanest way to "fix" the POST? Using a global filter attribute? – kamranicus Aug 28 '13 at 20:21
0

For me this just worked fine. Below is the server-side code

    [HttpPost]
    public void Disconnect([FromBody] Models.Users.User model) { ... }

and the requesting client code will be,

var dataToPost ={ id : 3, firstName : 'Test', lastName : 'User', username : 'testuser', isApproved : true, isOnlineNow : true, isChecked: true };

            var config = {
                headers : {
                    'Content-Type': 'application/json;charset=utf-8;'
                }
            }
            $http.post(thisIsUrl, dataToPost, config).then(......