POSTstring到ASP.NET Web Api应用程序 – 返回null

我试图从客户端传递一个string到ASP.NET MVC4应用程序。

但是我不能接收string,要么是null,要么post方法找不到(404错误)

客户端代码传输string(控制台应用程序):

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:49032/api/test"); request.Credentials = new NetworkCredential("user", "pw"); request.Method = "POST"; string postData = "Short test..."; byte[] byteArray = Encoding.UTF8.GetBytes(postData); request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = byteArray.Length; Stream dataStream = request.GetRequestStream(); dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); WebResponse response = request.GetResponse(); Console.WriteLine(((HttpWebResponse)response).StatusDescription); dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseFromServer = reader.ReadToEnd(); Console.WriteLine(responseFromServer); reader.Close(); dataStream.Close(); response.Close(); Console.ReadLine(); 

ASP.NET Web Api控制器:

 public class TestController : ApiController { [Authorize] public String Post(byte[] value) { return value.Length.ToString(); } } 

在这种情况下,我可以调用“Post”方法,但是“value”是NULL 。 如果我将方法签名更改为(string值)比它永远不会调用。

即使“没有”[Authorize]设置它也有相同的奇怪行为。 – >所以与用户authentication无关。

任何想法我做错了什么? 我很感激任何帮助。

您好像在您的Web API控制器操作中使用了一些[Authorize]属性,我不明白这与您的问题有什么关系。

所以,让我们开始练习。 下面是一个简单的Web API控制器的样子:

 public class TestController : ApiController { public string Post([FromBody] string value) { return value; } } 

和这个问题的消费者:

 class Program { static void Main() { using (var client = new WebClient()) { client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; var data = "=Short test..."; var result = client.UploadString("http://localhost:52996/api/test", "POST", data); Console.WriteLine(result); } } } 

您无疑会注意到Web API控制器属性的[FromBody]装饰以及客户端POST数据的=前缀。 我build议你阅读一下Web API如何通过参数绑定来更好地理解概念。

[Authorize]属性而言,这可以用来保护服务器上的一些操作,使其只能被authentication用户访问。 事实上,你在这里想要达到的目标还不是很清楚。顺便说一句,你应该在你的问题上说得更清楚。 您是否正在尝试了解参数绑定在ASP.NET Web API中的工作方式(请阅读我链接的文章,如果这是您的目标)还是尝试进行一些身份validation和/或授权? 如果第二个是你的情况,你可能会发现我写的关于这个主题的following post有趣,让你开始。

如果在阅读了我所链接的资料之后,你就像我一样对自己说,WTF的人,我所要做的就是向服务器端端点发送一个string,我需要做所有这些工作? 没门。 然后结帐ServiceStack 。 您将拥有与Web API进行比较的良好基础。 我不知道微软在deviseWeb API的时候想的是什么,但是认真的说,我们应该为我们的HTML(比如Razor)和REST的东西分开基本的控制器。 这不可能是严重的。

如果您接受使用HTTP的事实,Web API可以很好地工作。 当你开始试图假装你正在通过电线发送对象时,它开始变得混乱。

  public class TextController : ApiController { public HttpResponseMessage Post(HttpRequestMessage request) { var someText = request.Content.ReadAsStringAsync().Result; return new HttpResponseMessage() {Content = new StringContent(someText)}; } } 

该控制器将处理HTTP请求,从有效负载中读取一个string并将该string返回。

您可以使用HttpClient通过传递一个StringContent的实例来调用它。 StringContent将默认使用text / plain作为媒体types。 这正是你想要通过的。

  [Fact] public void PostAString() { var client = new HttpClient(); var content = new StringContent("Some text"); var response = client.PostAsync("http://oak:9999/api/text", content).Result; Assert.Equal("Some text",response.Content.ReadAsStringAsync().Result); } 

我使用此代码发布HttpRequests。

 /// <summary> /// Post this message. /// </summary> /// <param name="url">URL of the document.</param> /// <param name="bytes">The bytes.</param> public T Post<T>(string url, byte[] bytes) { T item; var request = WritePost(url, bytes); using (var response = request.GetResponse() as HttpWebResponse) { item = DeserializeResponse<T>(response); response.Close(); } return item; } /// <summary> /// Writes the post. /// </summary> /// <param name="url">The URL.</param> /// <param name="bytes">The bytes.</param> /// <returns></returns> private static HttpWebRequest WritePost(string url, byte[] bytes) { ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); Stream stream = null; try { request.Headers.Clear(); request.PreAuthenticate = true; request.Connection = null; request.Expect = null; request.KeepAlive = false; request.ContentLength = bytes.Length; request.Timeout = -1; request.Method = "POST"; stream = request.GetRequestStream(); stream.Write(bytes, 0, bytes.Length); } catch (Exception e) { GetErrorResponse(url, e); } finally { if (stream != null) { stream.Flush(); stream.Close(); } } return request; } 

关于你的代码,尝试没有content.Type( request.ContentType = "application/x-www-form-urlencoded";

更新

我相信问题在于你如何试图找回价值。 当您执行POST并通过Stream发送字节时,它们不会作为parameter passing给操作。 您需要通过服务器上的stream来检索字节。

在服务器上,尝试从stream中获取字节。 下面的代码是我使用的。

  /// <summary> Gets the body. </summary> /// <returns> The body. </returns> protected byte[] GetBytes() { byte[] bytes; using (var binaryReader = new BinaryReader(Request.InputStream)) { bytes = binaryReader.ReadBytes(Request.ContentLength); } return bytes; } 

达雷尔当然是对他的回应。 有一点要补充的是,试图绑定到包含单个标记(如“hello”)的主体的原因。

是不是URL格式的编码数据。 在前面加上“=”就可以了:

 =hello 

它将成为一个空的名称和值为“hello”的单个键值对的URL表单编码。

但是,更好的解决scheme是在上传string时使用application / json:

 POST /api/sample HTTP/1.1 Content-Type: application/json; charset=utf-8 Host: host:8080 Content-Length: 7 "Hello" 

使用HttpClient你可以这样做:

 HttpClient client = new HttpClient(); HttpResponseMessage response = await client.PostAsJsonAsync(_baseAddress + "api/json", "Hello"); string result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); 

亨里克

对于WebAPI,这里是没有通过他们特殊的[FromBody]绑定检索正文文本的代码。

 public class YourController : ApiController { [HttpPost] public HttpResponseMessage Post() { string bodyText = this.Request.Content.ReadAsStringAsync().Result; //more code here... } } 

我遇到了这个问题,并find这篇文章。 http://www.jasonwatmore.com/post/2014/04/18/Post-a-simple-string-value-from-AngularJS-to-NET-Web-API.aspx

我find的解决scheme是简单地将string值用双引号包装在你的js文章中

奇迹般有效! FYI

 ([FromBody] IDictionary<string,object> data)