1
votes

It maybe a dumb question, but I can't get it right. I've searched all on stackoverflow questions, and google of course.

So, I got this class on my webapi

public partial class TaskList
{
    public int id { get; set; }
    public string task { get; set; }
}

Then my webapi controller

[HttpPost]
public HttpResponseMessage Post([FromBody] TaskList tasklistModel)
{
    return Request.CreateResponse(HttpStatusCode.OK, tasklistModel);
}

My angularJS controller

angular.module('ReminderDude.controllers', [])

.controller('HomeController', function($scope, dudeService) {
    $scope.CreateNewTask = function(tasklistModel){
        tasklistModel.id = '1';

        dudeService.store({
            data: JSON.stringify(tasklistModel)
        }).then(function(resp) {
            console.log(resp);
         },function(err) {
            console.error('Controller: Error', err);
        });
    }
})

My angularJS service

angular.module('ReminderDude.services', [])

.factory('dudeService', function($http) {
    var baseUrl = 'http://localhost:1142/api/values';
    return {
        store: function (tasklistModel){
            return $http({  
                        url: baseUrl,
                        method: 'POST',  
                        data: tasklistModel,  
                        headers: {  
                            "Content-Type": "application/json"  
                        }  
                    });
        }
    };
})

And lastly, the HTML

<ion-view view-title="Reminder Dude">
    <ion-content class="padding">
        <form ng-Submit="CreateNewTask(model)">
            <div class="list card">
                <div class="item item-divider">Hello! Please input your task below</div>
                <div class="item item-input">
                    <input type="text" ng-model="model.task" placeholder="Write Here" />
                </div>
            </div>
            <center>
                <button type="submit" class="button button-positive button-large">Save</button>
            </center>
        </form>
    </ion-content>
</ion-view>

I made a breakpoint on my webapi controller, it hits but the model i passed on is null. Here's the returned data from my webapi controller:

Object {data: Object, status: 200, config: Object, statusText: "OK"}
config: Object    
data: Object       
headers: Object    
method: "POST"    
transformRequest: Array[1]
transformResponse : Array[1]
url : "http://localhost:1142/api/values"
__proto__ :
    Object: data
    Object:
        id: 0
        task: null
__proto__ :
    Object
    headers: function(name)
    status: 200
    statusText: "OK"
__proto__ :
    Object

Here's the list of what i've tried:

  • use or remove the [FromBody] tag on my webapi controller
  • use or remove JSON.stringify on my angularJS controller before sending my data to webapi controller
  • change the "public HttpResponseMessage Post" to "public TaskList Post"
  • console.log the data sent from my angularJS controller: {"task":"testTask","id":"1"}

Why it doesn't send correctly to my webapi? Any answers and helps would be appreciated.

FYI: CORS is not a problem in my opinion, i've enabled it. Because if the CORS isn't enabled, it won't hit the breakpoint wouldn't it? If it's a CORS related problem, please correct me.

Thank you

UPDATE:

After a quite long discussion with @Mahesh Chand, i've successfully send the data to my webapi controller. here's what i've done:

change the angularjs controller to this:

angular.module('ReminderDude.controllers', [])

.controller('HomeController', function($scope, dudeService) {   
    $scope.CreateNewTask = function(tasklistModel){
        tasklistModel.id = 1;

        //before
        dudeService.store({
            data: tasklistModel
        }).then(function(resp) {
        console.log('response from api:'))
        console.log(resp);

        //after
        dudeService.store(tasklistModel).then(function(resp) {
            console.log('response from api:');
            console.log(resp);
            //ignore the console.log, it just my code to test the response from the api

Big thanks to @Mahesh Chand, thanks for noticing the 'data' that was unnecessary one. (that was a hell of dumb mistake)

Note for @Mahesh Chand: in my case, we really need the ng-model instead of ng-bind. if i use ng-bind, i won't get the value that i passed on from the view.

Hope this will help the others that have the same problem as me.

1

1 Answers

1
votes

[FromBody] is used only when post request has form data but in your case you are submitting data in the request only. Thus, you've to remove [FromBody] in your Action of API controller

 [Route("save"), HttpPost]
 public HttpResponseMessage Post(TaskList tasklistModel)

Just for a good practice, use RoutePrefix attribute on Api Controller and Route attribute on Action as mentioned below:

 [RoutePrefix("api/my")]
 public class MyController : ApiController
 {
    [Route("save")]
    [HttpPost]
    public HttpResponseMessage Post(TaskList tasklistModel)
    {
       //Your code here
    }
 }

Requests are serialized automatically. Thus, you have to remove Json.Stringify. You should use id of model in controller as an integer not a character/string.

angular.module('ReminderDude.controllers', [])
.controller('HomeController', function($scope, dudeService) {
    //initialize the model here
    $scope.tasklistModel = {};
    //No need to pass it in parameter since it is directly accessible to View
    $scope.CreateNewTask = function(){
         $scope.tasklistModel.id = 1;

        dudeService.store($scope.tasklistModel).then(function(resp) {
            console.log(resp);
         },function(err) {
            console.error('Controller: Error', err);
        });
    }
})

Your Angular service also need one change. You should use post function avilable in $http as mentioned below:

angular.module('ReminderDude.services', [])

.factory('dudeService', function($http) {
    var baseUrl = 'http://localhost:1142/api/values';
    return {
        store: function (tasklistModel){
            //url will be baseUrl + api controller route prefix + action route
            console.log(tasklistModel)
            return $http.post(baseUrl+'api/my/save',tasklistModel);
        }
    };
})

Try ng-bind and your HTML would be

<ion-view view-title="Reminder Dude">
    <ion-content class="padding">
        <form ng-Submit="CreateNewTask()">
            <div class="list card">
                <div class="item item-divider">Hello! Please input your task below</div>
                <div class="item item-input">
                    <input type="text" ng-bind="tasklistModel.task" placeholder="Write Here" />
                </div>
            </div>
            <center>
                <button type="submit" class="button button-positive button-large">Save</button>
            </center>
        </form>
    </ion-content>
</ion-view>