0

I'm working on some demo examples on how to pass the form data from an Angular Service to a Web API 2 controller POST action. But my object is always null on the controller side. Here is how my code looks like

AngularJS Call to Web API

$http({
            method: 'POST',
            url: MyApp.rootPath + 'api/CustomerSpaSilo/SearchCustomers?nameFilter=' + nameFilter,
            data: $.param({ '': pagingVM }),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        });

The pagingVM is an angular $scope object that contains paging details - SortBy, CurrentPage, ItemsPerPage, SortDesc.

My Web API POST method

[HttpPost]
        [Route("SearchCustomers")]
        public HttpResponseMessage Post(string nameFilter, [FromBody] PagingViewModel pagingVM)
        {
            if (nameFilter == null)
                nameFilter = "";

            //Code Implementation
        }

The PagingViewModel class

public class PagingViewModel
    {
        public string SortBy { get; set; }

        public bool SortDesc { get; set; }

        public int CurrentPage { get; set; }

        public int TotalItems { get; set; }

        public int ItemsPerPage { get; set; }

        public int TotalPages
        {
            get {
                if (this.ItemsPerPage > 0)
                    return (int)Math.Ceiling((decimal)TotalItems / this.ItemsPerPage);
                else
                    return 1;  
            }
        }
    }

The pagingVM parameter is always coming as default object. A quick look in the Chrome's network activity shows that all the values are being passed in the request body as the form data. If I change the parameter type to FormDataCollection, then I can read the values and build my object but I'm looking to Web API bind the incoming request values for me. Am I missing something here?

enter image description here

5
  • I'm pretty sure this '': pagingVM should read 'pagingVM': pagingVM Commented Apr 12, 2016 at 13:37
  • @Kell I have tried that too but no avail. In fact, that's how I initially tried. In the chrome network tab, it shows up as pagingVM[SortBy]:CustomerID and so on. I'm wondering if the square brackets around it is the problem. Commented Apr 12, 2016 at 13:42
  • You probably want to JSON.stringify($.param({ 'pagingVM': pagingVM })), too. Commented Apr 12, 2016 at 13:51
  • @Kell - What worked is data: $.param(pagingVM). Commented Apr 12, 2016 at 17:09
  • Cool, glad you sorted it :) Commented Apr 13, 2016 at 7:54

2 Answers 2

1

controller

    [RoutePrefix("api/CustomerSpaSilo")]
    public class CustomerSpaSiloController : ApiController
    {
        [HttpPost]
        [Route("SearchCustomers")]
        public IHttpActionResult Post(string nameFilter, [FromBody] PagingViewModel pagingVM)
        {
            if (nameFilter == null)
                nameFilter = "";

            //Code Implementation

            return Ok("Result=" + pagingVM.ToString());
        }
    }

model

    public class PagingViewModel
    {
        public string SortBy { get; set; }

        public bool SortDesc { get; set; }

        public int CurrentPage { get; set; }

        public int TotalItems { get; set; }

        public int ItemsPerPage { get; set; }

        public int TotalPages
        {
            get
            {
                if (this.ItemsPerPage > 0)
                    return (int) Math.Ceiling((decimal) TotalItems/this.ItemsPerPage);
                else
                    return 1;
            }
        }

        public override string ToString()
        {
            return string.Format("PagingViewModel(SortBy='{0}',SortDesc='{1}', CurrentPage='{2}', TotalItems='{3}', ItemsPerPage='{4}')",
                SortBy, SortDesc, CurrentPage, TotalItems, ItemsPerPage);
        }
    }

postman screenshot

enter image description here

js client

<!DOCTYPE html>
<html ng-app="app">
<head>
    <title>Home</title>
</head>
<body ng-controller="HomeController">

<button ng-click="post()">post</button>
<p>{{status}}</p>
<pre>{{result | json}}</pre>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script>
    (function() {
        'use strict';

        console.trace('js loaded');

        angular
            .module('app', [])
            .factory('api', apiFactory)
            .controller('HomeController', HomeController);

        function apiFactory($http) {
            var svc = {
                searchCustomers: searchCustomers
            };
            return svc;

            function searchCustomers(nameField, paging) {
                return $http
                    .post('/api/CustomerSpaSilo/SearchCustomers?nameFilter=' + nameField,
                        paging,
                        {
                             headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                             transformRequest: function (obj) {
                                 var str = [];
                                 for (var p in obj)
                                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                                 return str.join("&");
                             }
                        }
                     );
            }
        }

        function HomeController($scope, api) {

            console.trace('HomeController');

            $scope.status = null;
            $scope.result = null;
            $scope.post = function () {

                var paging = {
                    SortBy: 'abc',
                    SortDesc: false,
                    CurrentPage: 3,
                    TotalItems: 52,
                    ItemsPerPage: 10
                };

                api.searchCustomers('ddd', paging)
                    .then(function(response) {
                        $scope.status = 'OK';
                        $scope.result = response.data;
                    }, function(reason) {
                        $scope.status = 'Error';
                        $scope.result = reason;
                    });
            };
        }
    })();
</script>
</body>
</html>

chrome screenshot

enter image description here

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

4 Comments

Thanks for the answer. I will try and let you know how it goes.
The postman part works. It's little helpful. But the js client part is not working. The request payload look like {"SortBy":"abc","SortDesc":false,"CurrentPage":3,"TotalItems":52,"ItemsPerPage":10} which is not right. Are you sure the js client is working for you?
I passed the data as data: $.param(pagingVM) and it seem to have worked. Thanks for the answer, it helped me. I'm still interested in knowing if your js client code is working as expected for you.
You are right. I added transformRequest param to $http. stackoverflow.com/questions/24710503/…
0

you should use your $http service like as -

 $http.post(MyApp.rootPath + 'api/CustomerSpaSilo/SearchCustomers?nameFilter=' + nameFilter, pagingVM ).then(function (result) {
              //success
                }, function (data) {
               //faild
                }); 

1 Comment

It did not work either. The request payload look like {"pagingVM":{"SortBy":"CustomerID","SortDesc":false,"CurrentPage":2,"TotalItems":13,"ItemsPerPage":10,"TotalPages":2}} . Moreover I want to send my data as form data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.