MVC Api 控制器与 JSON.stringify 混淆

MVC Api Controller confusion with JSON.stringify

我知道如何 post Umbraco 的 Api 控制器,这不是问题。

问题:

假设我们有 (2) Api 个方法:

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

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

在第一个 method/ajax 调用中,如果我将 "time" 和 "activityType" 字符串化,我会收到此错误:

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

UmbracoApi控制器 - 未找到与请求 URI 匹配的 HTTP 资源


相反,我必须将 (2) 参数附加为查询字符串,并且它有效。然而,在第二个 Api 方法中,我有一个模型,我可以使用 JSON 的 stringify 方法,并且它有效。

为什么?这与常规 MVC 一样吗??


我们有 (2) 个 ajax 次调用,这些都有效:

// 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);
        }
    });

WebAPI 的模型绑定器在绑定 "simple" 类型(如字符串)时默认查找查询字符串。这与 MVC 不同。使用 [FromBody] 属性告诉它应该查看请求正文。

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

编辑:事实证明,WebAPI 将正文作为流读取,而不是像在 MVC 中那样对其进行缓存。这意味着 [FromBody] 只能应用于一个参数。您需要在 URI 中传递一个,在正文中传递一个,或者创建一个包含这两个参数的复杂类型。

此行为是设计使然 documented

  • If the parameter is a “simple” type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
  • For complex types, Web API tries to read the value from the message body, using a media-type formatter.

要强制 Web API 在正文中查找简单类型,您可以使用 [FromBody] 属性修饰参数,例如

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