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)
- Application_End global.asax
- 如何在Visual Studio 2015中保存.sass文件
- 在ASP.NET MVC中,我如何使用C#代码中的Razor @ Url.Content()助手?
- 事务pipe理器已经禁用了对远程/networking事务的支持
- 未find方法:'!! 0 System.Array.Empty()'。 ASApp.BundleConfig.RegisterBundles(BundleCollection包)inBundleConfig.cs
- 什么是.axd文件?
- MS Visual Studio:如何从发布中排除某些项目文件夹?
- 如何使用ASP.NET和jQuery返回JSON
- logging最佳实践