Post参数始终为null

ian*_*one 195 .net c# asp.net-web-api asp.net-web-api-routing

自从升级到RC for WebAPI后,我在WebAPI上调用POST时遇到了一些奇怪的问题.我甚至回到了新项目生成的基本版本.所以:

public void Post(string value)
{
}
Run Code Online (Sandbox Code Playgroud)

并从Fiddler打来电话:

Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29

Body:
{
    "value": "test"
}
Run Code Online (Sandbox Code Playgroud)

当我调试时,字符串"value"永远不会被分配给.它总是为NULL.谁有这个问题?

(我第一次看到更复杂类型的问题)

问题不仅仅是绑定到ASP.NET MVC 4,在安装RC后,新的ASP.NET MVC 3项目也会出现同样的问题

Jim*_*rte 101

由于您只有一个参数,您可以尝试使用该[FromBody]属性进行装饰,或者更改方法以接受具有值作为属性的DTO,如我在此建议:MVC4 RC WebApi参数绑定

更新:官方ASP.NET站点今天更新了一个很好的解释:http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-1

简而言之,当在正文中发送单个简单类型时,只发送前缀为等号(=)的值,例如body:

=test

  • 这是如此愚蠢和烦人,以至于我不知道是否支持或帮助我解决问题的答案......为什么它必须采用这种格式呢?(抱歉这种态度,只是浪费了太多时间在这上面,它没有任何意义......`:(`).你应该真正添加对人们期望它接受的格式的支持. (13认同)
  • 根据http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding,只传递值(即不作为JSON对象)它应该可以工作的.aspx (10认同)
  • 前面的追加`=`从来没有为我工作过,直到我在他的评论(而不是JSON对象)中遵循Jim的建议并且它起作用.这是关键!我真的不喜欢挑剔的WebAPI. (8认同)
  • 我确实给了[FromBody]一个旋转但它没有变化 (7认同)
  • 谢谢!我们怎么知道在发送一个参数时我们必须删除参数名称?哪个小鸟提出了这个想法? (4认同)
  • `[FromBody]`适合我们,但在我们看来,这是倒退一步.使用beta我们可以有多个简单的类型参数,它们对我们的`ApiController中的方法绑定得很好.因此,虽然您参考的解释确实解释了,但我强烈不同意:-) (3认同)
  • 这太愚蠢了.我想在决定从旧的json或对象方式切换到使用=符号的脸上打开开发人员.现在我必须将=附加到变量.曾经说过是的让我们这样做,应该在微软解雇. (3认同)

Oce*_*rop 101

今天我一直在摸不着头脑.

我的解决方案是将a更改[FromBody]为a HttpRequestMessage,从根本上提升HTTP堆栈.

在我的情况下,我通过电线发送数据,这是拉链json,然后base64'd.这一切都来自Android应用程序.

我的Web端点的原始签名看起来像这样(使用[FromBody]):

我原来的终点

我对此问题的解决方法是恢复使用a HttpRequestMessage作为我的端点的签名.

在此输入图像描述

然后,您可以使用以下代码行访问帖子数据:

在此输入图像描述

这有效,并允许您访问原始未触及的后期数据.你不必乱搞fiddler在你的字符串的开头添加一个=符号或更改内容类型.

顺便说一句,我首先尝试按照上面的一个答案将内容类型更改为:"Content-Type:application/x-www-form-urlencoded".对于原始数据,这是一个糟糕的建议,因为它剥离了+字符.

所以像这样开始的base64字符串:"MQ0AAB + LCAAAAAA"就像这样的"MQ0AAB LCAAAAAA"!不是你想要的.

使用的另一个好处HttpRequestMessage是您可以访问端点中的所有http标头.

  • 只是旁注,你不需要方法签名中的`HttpRequestMessage请求',因为你已经拥有了它.在方法体中,可以在`Request`对象上访问它.例如`Request.Content.ReadAsStringAsync().结果;` (7认同)
  • 优秀的解决方案...花了我9个小时来找到这个,在我删除[FromBody]字符串值并用HttpRequestMessage替换它之后排除了我的问题 (5认同)

Kir*_*rst 71

我刚刚使用Fiddler发生了这种情况.问题是我没有指明Content-Type.

尝试Content-Type在POST请求中包含标题.

Content-Type: application/x-www-form-urlencoded
Run Code Online (Sandbox Code Playgroud)

或者,根据下面的评论,您可能需要包含JSON标头

Content-Type: application/json
Run Code Online (Sandbox Code Playgroud)

  • 我遇到了类似的问题,除了我需要设置Content-Type:application/json (11认同)
  • 正如帖子中所指定的那样 - 我已经添加了Content-Type:application/json (2认同)
  • application/x-www-form-urlencoded对我来说不起作用,Content-Type:application/json. (2认同)
  • 无论内容类型如何,如果只有一个参数,则必须仅发送请求正文中不包含参数名称的值。所以 id=13 不起作用。您需要单独发送 13 个。请参阅吉姆的回答。 (2认同)

Geo*_*rge 56

我也遇到过这个问题,这就是我解决问题的方法

webapi代码:

public void Post([FromBody] dynamic data)
{
    string value = data.value;
    /* do stuff */
}
Run Code Online (Sandbox Code Playgroud)

客户代码:

$.post( "webapi/address", { value: "some value" } );
Run Code Online (Sandbox Code Playgroud)


Jer*_*yal 37

我正在使用Postman,我也犯了同样的错误..传递valuejson对象而不是字符串

{
    "value": "test"
}
Run Code Online (Sandbox Code Playgroud)

显然,当api参数是string类型时,上面的错误.

所以,只需在api体中用双引号传递字符串:

"test"
Run Code Online (Sandbox Code Playgroud)

  • 这是我的问题,可能是问题的真正解决方案.JSON编码的字符串有引号 (2认同)

Des*_*tar 18

尝试创建一个类作为数据模型,然后发送一个JSON对象,其属性与数据模型类的属性相匹配.(注意:我已对此进行了测试,它与我刚刚下载的最新MVC 4 RC 2012一起使用).

public HttpResponseMessage Post(ValueModel model)
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, "Value Recieved: " + model.Value);
}

public class ValueModel
{
    public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

下面的JSON对象在HTTP-POST主体中发送,content-type是application/json

{ "value": "In MVC4 Beta you could map to simple types like string, but testing with RC 2012 I have only been able to map to DataModels and only JSON (application/json) and url-encoded (application/x-www-form-urlencoded body formats have worked. XML is not working for some reason" }
Run Code Online (Sandbox Code Playgroud)

我相信您必须创建数据模型类的原因是因为假设简单值来自url参数,并且假设单个复杂值来自正文.他们确实拥有[FromBody][FromUrl]属性,但使用[FromBody] string value仍然不适合我.看起来他们仍然在制造很多错误,所以我相信这将在未来发生变化.

编辑: 让XML在正文中工作.默认的XML序列化程序已更改为DataContractSerializer而不是XmlSerializer.将以下行放在我的Global.asax文件中修复了此问题(参考)

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Run Code Online (Sandbox Code Playgroud)


Leo*_*eon 13

经过一些尝试,我认为默认行为是正确的,没有什么可以破解.

唯一的技巧是:如果你的post方法参数string如下所示,你应该在正文中发送一个带双引号的普通字符串(当使用ajax或postman时),例如,

//send "{\"a\":1}" in body to me, note the outer double quotes
[HttpPost("api1")]
public String PostMethod1([FromBody]string value)
{
    return "received " + value; //  "received {\"a\":1}"
}
Run Code Online (Sandbox Code Playgroud)

否则,如果你在帖子体中发送一个没有外部双引号和转义内部引号的json字符串,那么它应该能够被解析为模型类(参数类型),例如,{"a":1, "b":2}

public class MyPoco{
    public int a;
    public int b;
}

//send {"a":1, "b":2} in body to me
[HttpPost("api2")]
public String PostMethod2([FromBody]MyPoco value)
{
    return "received " + value.ToString();  //"received your_namespace+MyPoco"
}
Run Code Online (Sandbox Code Playgroud)


chr*_*rjs 11

我现在正在寻找这个问题的解决方案几分钟,所以我将分享我的解决方案.

如果发布模型,模型需要有一个空/默认构造函数,否则显然无法创建模型.重构时要小心.;)


Big*_*n73 8

这对我有用:

  1. 创建一个C#DTO类,其中包含要从jQuery/Ajax传递的每个属性的属性

    public class EntityData
    {
        public string Attr1 { get; set; }
        public string Attr2 { get; set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 定义web api方法:

    [HttpPost()]
    public JObject AddNewEntity([FromBody] EntityData entityData)
    {
    
    Run Code Online (Sandbox Code Playgroud)
  3. 像这样调用web api:

    var entityData = {
        "attr1": "value1",
        "attr2": "value2"
    };
    
    $.ajax({
        type: "POST",
        url: "/api/YOURCONTROLLER/addnewentity",
        async: true,
        cache: false,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            ...
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)


dvc*_*ior 7

对于那些像我一样遇到SwaggerPostman的问题的人,如果您将简单的属性作为字符串传递给帖子,即使指定了“ ContentType”,您仍将获得null值。

仅通过:

我的价值

将作为空值进入控制器。

但是,如果您通过:

“我的价值”

该值将正确。

引号在这里有所不同。当然,这仅适用于Swagger和Postman。例如,在使用Angular的前端应用程序中,此问题应由框架自动解决。


小智 5

我有同样的问题,发现当将内容类型更改为"application/json"时没有解决问题.但是"application/json; charset = utf-8"起作用了.