Im trying to transmit a string from client to ASP.NET MVC4 application.
But I can not receive the string, either it is null or the post method can not be found (404 error)
Client Code to transmit the string (Console Application):
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 Controller:
public class TestController : ApiController
{
[Authorize]
public String Post(byte[] value)
{
return value.Length.ToString();
}
}
In that case I'm able to call the "Post" method, but "value" is NULL
.
If I change the method signature to (string value) than it will never called.
Even "without" the [Authorize] setting it has the same strange behavior. -> So it has nothing to do with the user authentication.
Any ideas what I'm doing wrong? I'm grateful for any help.
This question is related to
c#
asp.net
asp.net-mvc
post
asp.net-web-api
i meet this problem, and find this article. http://www.jasonwatmore.com/post/2014/04/18/Post-a-simple-string-value-from-AngularJS-to-NET-Web-API.aspx
The solution I found was to simply wrap the string value in double quotes in your js post
works like a charm! FYI
([FromBody] IDictionary<string,object> data)
Web API works very nicely if you accept the fact that you are using HTTP. It's when you start trying to pretend that you are sending objects over the wire that it starts to get messy.
public class TextController : ApiController
{
public HttpResponseMessage Post(HttpRequestMessage request) {
var someText = request.Content.ReadAsStringAsync().Result;
return new HttpResponseMessage() {Content = new StringContent(someText)};
}
}
This controller will handle a HTTP request, read a string out of the payload and return that string back.
You can use HttpClient to call it by passing an instance of StringContent. StringContent will be default use text/plain as the media type. Which is exactly what you are trying to pass.
[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);
}
Darrel is of course right on with his response. One thing to add is that the reason why attempting to bind to a body containing a single token like "hello".
is that it isn’t quite URL form encoded data. By adding “=” in front like this:
=hello
it becomes a URL form encoding of a single key value pair with an empty name and value of “hello”.
However, a better solution is to use application/json when uploading a string:
POST /api/sample HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: host:8080
Content-Length: 7
"Hello"
Using HttpClient you can do it as follows:
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsJsonAsync(_baseAddress + "api/json", "Hello");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
Henrik
For WebAPI, here is the code to retrieve body text without going through their special [FromBody] binding.
public class YourController : ApiController
{
[HttpPost]
public HttpResponseMessage Post()
{
string bodyText = this.Request.Content.ReadAsStringAsync().Result;
//more code here...
}
}
I use this code to post 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;
}
In regards to your code, try it without the content.Type (request.ContentType = "application/x-www-form-urlencoded";
)
update
I believe the problem lies with how you are trying to retrieve the value. When you do a POST and send bytes via the Stream, they will not be passed into the action as a parameter. You'll need to retrieve the bytes via the stream on the server.
On the server, try getting the bytes from stream. The following code is what I use.
/// <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;
}
Source: Stackoverflow.com