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
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
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;
}
([FromBody] IDictionary<string,object> data)
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...
}
}
You seem to have used some [Authorize]
attribute on your Web API controller action and I don't see how this is relevant to your question.
So, let's get into practice. Here's a how a trivial Web API controller might look like:
public class TestController : ApiController
{
public string Post([FromBody] string value)
{
return value;
}
}
and a consumer for that matter:
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);
}
}
}
You will undoubtedly notice the [FromBody] decoration of the Web API controller attribute as well as the =
prefix of the POST data om the client side. I would recommend you reading about how does the Web API does parameter binding to better understand the concepts.
As far as the [Authorize]
attribute is concerned, this could be used to protect some actions on your server from being accessible only to authenticated users. Actually it is pretty unclear what you are trying to achieve here.You should have made this more clear in your question by the way. Are you are trying to understand how parameter bind works in ASP.NET Web API (please read the article I've linked to if this is your goal) or are attempting to do some authentication and/or authorization? If the second is your case you might find the following post that I wrote on this topic interesting to get you started.
And if after reading the materials I've linked to, you are like me and say to yourself, WTF man, all I need to do is POST a string to a server side endpoint and I need to do all of this? No way. Then checkout ServiceStack. You will have a good base for comparison with Web API. I don't know what the dudes at Microsoft were thinking about when designing the Web API, but come on, seriously, we should have separate base controllers for our HTML (think Razor) and REST stuff? This cannot be serious.