Naigel
Naigel

Reputation: 9644

Posting to ASP.NET WebApi server from AngularJS client

I'm trying to post strings from an AngularJS application (using $http) to a server built on ASP.NET WebApi, but I get 404 as soon as I add a parameter.

The client code is this

$scope.add = function () {
    // ...cut...
    $http({ method: "POST", url: url, data: { fileString: "test string" }}).then(
        function successCallback(response) {
            $log.info(response.data);
        }
    );
}

The server code is

[HttpPost]
public IHttpActionResult UploadExcel(string fileString) {
    // cut
}

I get a 404, but if I remove the parameter on server side it works, so i can use a server side code like this

[HttpPost]
public IHttpActionResult UploadExcel() {
    // cut
}

What is wrong? Should I pass the data in a different way? I tried different combination but I can't get it work.

Upvotes: 4

Views: 904

Answers (3)

Naigel
Naigel

Reputation: 9644

The first error is in the controller, [FromBody] should be used with the input parameter.

public IHttpActionResult UploadExcel([FromBody]string fileString)

Then the data variable on the client should be a single string, so

$http({ method: "POST", url: url, data: "test string" }).then(

Anyway I found some issue with this solution later, it seems the simplest but I suggest to avoid it.


Best solution

Thank to @Squazz answer and this SO answer I strongly suggest a change in the webapi controller, client was correct. Just introduce a class to handle a single string and adapt the input parameter

// new class with a single string
public class InputData {
    public string fileString { get; set; }
}

// new controller 
[HttpPost]
public IHttpActionResult UploadExcel([FromBody] InputData myInput) {
    string fileString = myInput.fileString;
    // cut
}

This way JSON code from the client is automatically parsed and it's easy to change the data input.

Extra tip

$scope.add angular function was correct as in the question, but here is a more complete example

$scope.testDelete = function () {
    var url = "http://localhost/yourAppLink/yourControllerName/UploadExcel";
    var data = ({ fileString: "yourStringHere" });
    $http({ method: "POST", url: url, data: data }).then(
        function successCallback(response) {
            console.log("done, here is the answer: ", response.data);
        }, function errorCallback(response) {
            console.log("an error occurred");
        }
    );
}

Upvotes: 2

Squazz
Squazz

Reputation: 4171

What you want to do is send a string, not a JSON object as you are doing right now with { fileString: "test string" }. When I want to send a string, what I normally do is that I send data from Angular like this:

$http.post("/Search/QuickSearch?searchQuery="+ searchString);

And my controller I make ready to receive a string like this:

[HttpPost]
public IHttpActionResult QuickSearch(string searchQuery)
{
    // cut
}

If I want to send a JSON object, I tell my controller what it should expect, like this:

[HttpPost]
public IHttpActionResult SaveActivity(ActivityEditForm form);
{
    // cut
}

public class ActivityEditForm
{
    public int? Id { get; set; }
    [Required]
    public string Title { get; set; }

    public string Description { get; set; }
}

And then send my JSON from Angular like this:

$http.post("/Activity/SaveActivity", { form: activity });

Upvotes: 5

Eric Zeng
Eric Zeng

Reputation: 135

I suggest you should capture the request send by Angular. By default, Angular send parameters in a json string in request body.

I'm not sure wether Asp.net can parse them from json string in body.

So, you can try to add the below codes (also need jQuery)

angular.module('yourApp').config(function ($httpProvider) {
    $httpProvider.defaults.transformRequest = function(data){
        if (data === undefined) {
            return data;
        }
        return $.param(data);
    }
});

Upvotes: 2

Related Questions