MVC Api Controller error with JSON.stringify

I know how to send a message to the Umbraco Api Controller, this is not a problem.

Question:

Let's say we have (2) Api methods:

    [HttpPost]
    public string Test1(string time, string activityType)
    {
        return time;
    }

    [HttpPost]
    public string Test2(SomeModel model)
    {
        return model.SomeProperty;
    }

      

On the first call to the / ajax method, if I build "time" and "activity type", I get this error:

url: '/Umbraco/api/SomeApi/Test1',
type: 'POST',
dataType: 'json',
data: JSON.stringify({time: '10', activityType: 'test'}),

      

UmbracoApiController - no HTTP resource found matching the request URI


Instead, I have to add parameters (2) as a request and it works. However, in the second Api method, I have a model and I can use the stringify method for JSON and it works.

Why? Is this the same with regular MVC?


We have (2) ajax calls and they both work:

// you can see that I have to append via querystring in this instance
$.ajax({
        url: '/Umbraco/api/SomeApi/Test1?time=' + time + '&activityType=' + activityType,
        type: 'POST',
        dataType: 'json',
        data: '',
        // doesn't work ****
        // url: '/Umbraco/api/SomeApi/Test1',
        // data: JSON.stringify({time: '10', activityType: 'test'}),
        // **********************
        processData: false,
        async: false,
        contentType: 'application/json; charset=utf-8',
        complete: function (data) {
            var test= $.parseJSON(data.responseText);
            console.log(test);
        },
        error: function (response) {
            console.log(response.responseText);
        }
    });

var post = {
   SomeProperty : 'test',
   AnotherProperty: 'blahblah'
};

$.ajax({
        url: '/Umbraco/api/SomeApi/Test2',
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(post),
        processData: false,
        async: false,
        contentType: 'application/json; charset=utf-8',
        complete: function (data) {
            var test= $.parseJSON(data.responseText);
            console.log(test);
        },
        error: function (response) {
            console.log(response.responseText);
        }
    });

      

+3


source to share


2 answers


The default WebAPI model interaction appears in the query string when binding "simple" types such as strings. This is different from MVC. Use the attribute [FromBody]

to tell it what it should look like in the request body.

public string Test1([FromBody]string time, [FromBody]string activityType)

      



Edit: It turns out that the WebAPI reads the body as a stream, rather than caching it like in MVC. This means it [FromBody]

can only be applied to one parameter. You need to either pass one in the URI, or one in the body, or create a complex type that contains both of your parameters.

+4


source


This behavior is by design and well documented

  • If the parameter is a "simple" type, the Web API tries to get the value from the URI . Simple types include .NET primitive types (int, bool, double, etc.) as well as TimeSpan, DateTime, Guid, decimal, and string, as well as any type with a type converter that can convert from a string. (More on type converters later.)
  • For complex types, the Web API tries to read the value from the message body using the media type format.


To make the web API look in body for simple types, you can decorate the parameters with the [FromBody] attribute , for example

public string Test1([FromBody]string time, [FromBody]string activityType)

      

+2


source







All Articles