Post参数始终为空

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

public void Post(string value) { } 

并从小提琴手打电话来:

 Header: User-Agent: Fiddler Host: localhost:60725 Content-Type: application/json Content-Length: 29 Body: { "value": "test" } 

当我debugging时,string“值”永远不会被分配给。 它只是总是NULL。 任何人有这个问题?

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

这个问题不仅仅局限于ASP.NET MVC 4,RC安装后新的ASP.NET MVC 3项目也会出现同样的问题

既然你只有一个参数,你可以尝试使用[FromBody]属性来装饰它,或者改变方法来接受一个值作为属性的DTO,正如我在这里所build议的那样: MVC4 RC WebApi参数绑定

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

简而言之,当在主体中发送一个简单的types时,只发送前缀为等号(=)的值,例如body:

=test

今天我一直在挠头。

我的解决scheme是将[FromBody]更改为HttpRequestMessage ,实质上移动了HTTP堆栈。

在我的情况下,我正在发送数据通过压缩JSON然后base64'd的电线。 所有这一切从一个Android应用程序。

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

我原来的终点

我对这个问题的修复是恢复使用HttpRequestMessage作为我的端点的签名。

在这里输入图像描述

然后,您可以使用以下这行代码访问发布数据:

在这里输入图像描述

这可以工作,并允许您访问原始的原始数据。 你不必在小提琴手的string开始处加上=号,或者改变内容types。

顺便说一下,我首先尝试了上面的答案之一,将内容types更改为:“Content-Type:application / x-www-form-urlencoded”。 对于原始数据,这是不好的build议,因为它会去掉+字符。

所以一个像这样开始的base64string:“MQ0AAB + LCAAAAAA”就像这样“MQ0AAB LCAAAAAA”! 不是你想要的。

使用HttpRequestMessage另一个好处是你可以从你的端点访问所有的http头文件。

我刚刚发生这种情况使用提琴手。 问题是我没有指定Content-Type

尝试在您的POST请求中包含Content-Type的标题。

 Content-Type: application/x-www-form-urlencoded 

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

 Content-Type: application/json 

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

webapi代码:

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

客户代码:

 $.post( "webapi/address", { value: "some value" } ); 

尝试创build一个类作为数据模型,然后发送一个JSON对象,其属性与您的数据模型类的属性匹配。 (注意:我已经testing了这个版本,它可以和我刚刚下载的最新的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; } } 

下面的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" } 

我相信你必须创build一个数据模型类的原因是因为简单的值被假定为来自url参数,并且假定一个复数值来自于body。 他们有[FromBody][FromUrl]属性,但使用[FromBody] string value仍然不适用于我。 似乎他们仍然在研究大量的错误,所以我相信这一点在将来会改变。

编辑:得到的XML在身体工作。 默认的XML序列化器改为DataContractSerializer而不是XmlSerializer。 把我的Global.asax文件中的以下行解决了这个问题( 参考 )

 GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true; 

我正在使用Postman ,我也犯了同样的错误。传递value json对象,而不是string

 { "value": "test" } 

当api参数是stringtypes的时候,显然上面的错误错误的。

所以,只需在双引号中的string在api身体:

 "test" 

我正在寻找解决这个问题几分钟,所以我会分享我的解决scheme。

如果你发布一个模型,你的模型需要有一个空的/默认的构造函数,否则显然不能创build模型。 重构时要小心。 ;)

我有同样的问题,发现当更改内容types为“application / json”没有解决问题。 然而“application / json; charset = utf-8”工作。

我有一个类似的问题,我的Web API方法的请求对象始终为空。 我注意到,由于控制器操作名称的前缀为“Get”,Web API将此视为HTTP GET而不是POST。 重命名控制器动作后,现在按预期工作。

在我的情况下,问题是参数是一个string,而不是一个对象,我改变了参数为JOBject的Newsoft.Json和它的作品。

这对我工作:

  1. 创build一个C#DTO类,为每个要从jQuery / Ajax传递的属性提供一个属性

     public class EntityData { public string Attr1 { get; set; } public string Attr2 { get; set; } } 
  2. 定义web api方法:

     [HttpPost()] public JObject AddNewEntity([FromBody] EntityData entityData) { 
  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) { ... } }); 

添加线

  ValueProviderFactories.Factories.Add(new JsonValueProviderFactory()); 

在ASP.NET MVC3中为Global.asax.cs中的protected void Application_Start()修复了类似的问题。

借助Angular,我能够以这种格式传递数据:

  data: '=' + JSON.stringify({ u: $scope.usrname1, p: $scope.pwd1 }), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' } 

而在Web API控制器中:

  [HttpPost] public Hashtable Post([FromBody]string jsonString) { IDictionary<string, string> data = JsonConvert.DeserializeObject<IDictionary<string, string>>(jsonString); string username = data["u"]; string pwd = data["p"]; ...... 

另外,我也可以发布这样的JSON数据:

  data: { PaintingId: 1, Title: "Animal show", Price: 10.50 } 

而且,在控制器中,接受这样一个类的types:

  [HttpPost] public string POST(Models.PostModel pm) { .... } 

无论哪种方式工作,如果你有在API中build立的公共类,然后张贴JSON,否则后'='+ JSON.stringify({..:…,..:…})

如果您正在为您的Xml格式化程序或JSON格式化程序使用DataContractSerializer ,则需要清除它。 我在我的WebApiConfig文件中有这个:

 public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); jsonFormatter.UseDataContractJsonSerializer = true; } 

只是我注释掉jsonFormatter.UseDataContractJsonSerializer = true; 和我的input参数不是null了。 感谢“Despertar”给我一个线索。

我知道这不是对这个问题的回答,但是当我寻找解决scheme时遇到了这个问题。

在我的情况下,复杂types没有被绑定,但我没有做一个POST,我正在做一个GET查询string参数。 解决方法是将[FromUri]添加到arg中:

 public class MyController : ApiController { public IEnumerable<MyModel> Get([FromUri] MyComplexType input) { // input is not null as long as [FromUri] is present in the method arg } } 

我在提琴手中也有同样的问题。 我已经有了Content-Type: application/json; charset=utf-8 请求头中的Content-Type: application/json; charset=utf-8Content-Type: application/json

我的请求身体也是一个普通的string,在小提琴手我写了: {'controller':'ctrl'} 。 这使得我的POST方法中的string参数为null

修复 :请记住使用引号,从而指示一个string。 也就是说,我通过写"{'controller':'ctrl'}" 。 (注意:在编写JSON的时候,一定要用撇号或者像下面这样引号: "{\"controller\":\"ctrl\"}" )。

我发现处理传递给MVC 6的简单JSON对象的最简单的方法是获取像NewtonSoft jObject这样的post参数的types:

 public ActionResult Test2([FromBody] jObject str) { return Json(new { message = "Test1 Returned: "+ str }); ; } 

如果你确定你发送的JSON,那么你必须仔细地跟踪你的API:

  1. 安装Microsoft.AspNet.WebApi.Tracing
  2. 添加config.EnableSystemDiagnosticsTracing();WebApiConfig类的Register方法里面。

现在看看Debug输出,你可能会发现一个无效的ModelState日志条目。

如果ModelState是无效的,你可能会发现Errors的真正原因:

没有人能猜到这样的例外:

 Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) 

对于复杂types,Web API尝试使用媒体格式化程序从消息正文中读取值。

请检查是否有任何装饰你的模型类的[Serializable]属性。

删除属性,看它是否工作。 这对我有效。

对于像Swagger或Postman一样的问题,如果你在post中传递一个简单的属性作为string,即使指定了“ContentType”,你仍然会得到一个空值。

传递只是:

myvalue的

将作为null进入控制器。

但是,如果你通过:

“myvalue的”

价值会得到正确的。

报价在这里有所不同。 当然,这只适用于Swagger和Postman。 例如,在使用Angular的Frontend应用程序中,应该由框架自动解决。

我对聚会有点晚了,但是任何在使用控制器时都经过了NULL值的人只要在你的POST请求的前面添加“=”即可。

当我使用application / json Content-Type时,控制器也传递了一个NULL值。 请注意下面的“application / x-www-form-urlencoded”Content-Type。 然而,API的返回types是“application / json”。

  public static string HttpPostRequest(string url, Dictionary<string, string> postParameters) { string postData = "="; foreach (string key in postParameters.Keys) { postData += HttpUtility.UrlEncode(key) + "=" + HttpUtility.UrlEncode(postParameters[key]) + ","; } HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); myHttpWebRequest.Method = "POST"; byte[] data = System.Text.Encoding.ASCII.GetBytes(postData); myHttpWebRequest.ContentType = "application/x-www-form-urlencoded"; myHttpWebRequest.ContentLength = data.Length; Stream requestStream = myHttpWebRequest.GetRequestStream(); requestStream.Write(data, 0, data.Length); requestStream.Close(); HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); Stream responseStream = myHttpWebResponse.GetResponseStream(); StreamReader myStreamReader = new StreamReader(responseStream, System.Text.Encoding.Default); string pageContent = myStreamReader.ReadToEnd(); myStreamReader.Close(); responseStream.Close(); myHttpWebResponse.Close(); return pageContent; } 

正确的将正文中的单个parameter passing给WebAPI运行此代码$.post(url, { '': productId }

并捕捉它在行动[HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)

关键是使用魔术字“价值”。 它也可能是int或者一些原始types。 不pipe是内容types还是标题更正乱码是这个代码在mvc post操作中不起作用。

对我来说最好的解决scheme是完整的HTTP如下:

 [Route("api/open")] [HttpPost] public async Task<string> open(HttpRequestMessage request) { var json = await request.Content.ReadAsStringAsync(); JavaScriptSerializer jss = new JavaScriptSerializer(); WS_OpenSession param = jss.Deserialize<WS_OpenSession>(json); return param.sessionid; } 

然后将string反序列化到您期望在post正文中的对象。 对我来说,WS_OpenSession是一个包含sessionid,user和key的类。

你可以从那里使用param对象并访问它的属性。

非常非常有效。

我确实说来自这个url:

http://bizcoder.com/posting-raw-json-to-web-api

不pipe你希望发布什么types的值,只要把它放在引号内就可以得到它的string。 不适用于复杂的types。

JavaScript的:

  var myData = null, url = 'api/' + 'Named/' + 'NamedMethod'; myData = 7; $http.post(url, "'" + myData + "'") .then(function (response) { console.log(response.data); }); myData = "some sentence"; $http.post(url, "'" + myData + "'") .then(function (response) { console.log(response.data); }); myData = { name: 'person name', age: 21 }; $http.post(url, "'" + JSON.stringify(myData) + "'") .then(function (response) { console.log(response.data); }); $http.post(url, "'" + angular.toJson(myData) + "'") .then(function (response) { console.log(response.data); }); 

C#:

  public class NamedController : ApiController { [HttpPost] public int NamedMethod([FromBody] string value) { return value == null ? 1 : 0; } } 

问题是你的动作方法期待一个简单的types,即一个string参数值。 你提供的是一个对象。

有两个解决你的问题。

  1. 使用“ value ”属性创build一个简单的类,然后使用该类作为参数,在这种情况下,Web API模型绑定将从请求中读取JSON对象,并将其绑定到您的param对象的“values”属性。

  2. 只要通过string值“ testing ”,它会工作。

如果你把[FromBody]注解,你有一个Dto对象作为你的方法的参数,仍然无法获取数据通过,开始寻找你的DTO的属性和领域。

我有同样的问题,我的DTO是空的。 我发现原因是其中一个属性指向了一个无法序列化对象 :(这将导致媒体格式化器无法parsing数据,因此该对象总是空的,希望它也能帮助其他人

仔细检查你的数据types。 dotnet模型联编程序不会将浮点数转换为整数(我假设其他相关的概念)。 这将导致整个模型被拒绝。

如果你有这样的json:

 { "shoeSize": 10.5 } 

但是你的c#模型看起来像这样:

 class Shoe{ public int shoeSize; } 

模型联编程序将拒绝该模型,您将得到空值。

在我的情况下,用Newtonsoft中的[JsonObject(MemberSerialization.OptOut)]属性来装饰参数类就行了。

例如:

 [HttpPost] [Route("MyRoute")] public IHttpActionResult DoWork(MyClass args) { ... } [JsonObject(MemberSerialization.OptOut)] public Class MyClass { ... } 

API:

 [HttpPost] public bool UpdateTicketStatus(Ticket t) { string Id=t.Id; } 

模型:

 public class Ticket { public int Id { get; set; } public string AssignedTo { get; set; } public string State { get; set; } public string History { get; set; } } 

使用Post man工具将内容作为json发送,如下所示。 有用

{“Id”:“169248”,“AssignedTo”:“xxxx”,“State”:“Committed”,“History”:“test1”}

请确保您已启用Cors。

 [EnableCors(origins: "*", headers: "*", methods: "*")] public class TicketController : ApiController { } 

这个链接帮助了我: http : //encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

基本上它说你应该使用一个空的名字作为参数:

 public string Post([FromBody]string myParameter){ ... } $.post("/api/dosomething", { '' : "myvalue" });