1

I want to submit a form post via AJAX to my API. I have already set up my WebApiConfig.cs class as follows to enable multiple GETs:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
    name: "ApiById",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = RouteParameter.Optional },
     constraints: new { id = @"^[0-9]+$" }
);
config.Routes.MapHttpRoute(
    name: "ApiByName",
    routeTemplate: "api/{controller}/{action}/{name}",
    defaults: null,
    constraints: new { name = @"^[a-z]+$" }
);

config.Routes.MapHttpRoute(
    name: "ApiByAction",
    routeTemplate: "api/{controller}/{action}",
    defaults: new { action = "Get" }
);

Here is the controller action:

[HttpPost]
[ActionName("ChangeStuff")]
public string ChangeStuff(int val1, int val2, int val3)
{
    //Code
}

And this is where I make the request:

var url = window.location.protocol + "//" + window.location.host + "/api" + "@Url.Action("ChangeStuff", "ApiControllerName")";
        $.ajax({
            url: url,
            type: "POST", //Works with GET
            data: { val1: val1, val2: val2, val3: val3 },
            contentType: "application/json:; charset=utf-8",
            dataType: "json",
            success: function (msg) {
            },
            failure: function (msg) {
            }
        });

However, I get this error back when making the post:

POST http://localhost:50627/api/ApiControllerName/ChangeStuff 404 (Not Found) 

I am thinking this is because of an issue with my API routing defaulting to GET requests and then failing to accept POST types (even though it is made explicit in the AJAX call). It works just fine when making GET requests.

EDIT: Neither of the following attempts worked:

data: JSON.stringify( { currentobject } )
data: { data: { currentobject } }

Is it assured that the issue is not with the modified API routes?

jokul
  • 1,269
  • 16
  • 37
  • What is the name of your controller? – Nix Dec 30 '13 at 20:49
  • I think there's something wrong with the way you are passing the `JSON` in your Ajax call. i.e. here => `data: { val1: val1, val2: val2, val3: val3 }`. I believe you have to use something like `JSON.stringify(data)` after constructiong the `data` string properly. See example here: http://stackoverflow.com/a/17371494/325521 – Shiva Dec 30 '13 at 20:53
  • @Nix I don't own the code I'm working on and thus cannot distribute the name, but I can verify that the names are identical via copy-paste (and Visual Studio isn't complaining). I'll try stringifying the data, I had been under the impression you didn't have to do this but i'll give it a shot. EDIT: I just tried using Stringify, still no dice, but I will try wrapping it in an object such as { data: (current data object) } – jokul Dec 30 '13 at 21:15
  • Would a [FromBody] attribute help on the parameters? – Steen Tøttrup Dec 30 '13 at 21:33
  • Adding [FromBody] to each parameter caused a 500 error, not sure if that's a step in the right or wrong direction though lol. It didn't hit the breakpoint I had set in the first line of the controller's execution though. – jokul Dec 30 '13 at 21:36
  • Did you check to see if the `stringify` created the proper `JSON` string? Try assigning `JSON.stringify( { currentobject } )` to a variable in your javascript file before making the ajax call, and inspect it in debugger / `F12` in the browser (Chrome or IE9+) to see if it has the correct string expected by the Action method. – Shiva Dec 30 '13 at 23:12

1 Answers1

2

Try defining an object with the values you want to pass then telling your API Post action to expect that object instead of a list of individual values.

public class ApiPostModel
{
    public int Val1 { get; set; }
    public int Val2 { get; set; }
    public int Val3 { get; set; }
}

Then in your controller:

[HttpPost]
[ActionName("ChangeStuff")]
public string ChangeStuff(ApiPostModel model)
{
    //Code
}

As long as the names of the keys you pass in your data{} block match up with the attribute names you should be good to go.

Either that or pass the values to the controller as querystrings.

Dan S.
  • 173
  • 1
  • 14