Reading HttpContent in a WebApi Controller

How can I read the contents of a PUT request in an MVC webApi controller action.

[HttpPut] public HttpResponseMessage Put(int accountId, Contact contact) { var httpContent = Request.Content; var asyncContent = httpContent.ReadAsStringAsync().Result; ... 

I get an empty string here :(

What I need to do: find out what properties were changed / sent in the initial request (this means that if the Contact object has 10 properties, and I want to update only 2 of them, I also send an object with two properties, something like this :

 { "FirstName": null, "LastName": null, "id": 21 } 

Expected Outcome

 List<string> modified_properties = {"FirstName", "LastName"} 
+45
c # asp.net-mvc asp.net-web-api
Sep 19
source share
4 answers

By design, the body content in the ASP.NET Web API is considered a direct stream that can be read only once.

The first read in your case is done when the web API binds your model, after which Request.Content will return nothing.

You can remove contact from your action parameters, get the content and deserialize it manually into an object (for example, using Json.NET):

 [HttpPut] public HttpResponseMessage Put(int accountId) { HttpContent requestContent = Request.Content; string jsonContent = requestContent.ReadAsStringAsync().Result; CONTACT contact = JsonConvert.DeserializeObject<CONTACT>(jsonContent); ... } 

This should do the trick (assuming accountId is a URL parameter, so it won’t be considered reading content).

+87
Sep 19 '12 at 12:32
source

You can save your CONTACT parameter as follows:

 using (var stream = new MemoryStream()) { var context = (HttpContextBase)Request.Properties["MS_HttpContext"]; context.Request.InputStream.Seek(0, SeekOrigin.Begin); context.Request.InputStream.CopyTo(stream); string requestBody = Encoding.UTF8.GetString(stream.ToArray()); } 

Returned for me a json representation of the object of my parameter, so I could use it to handle exceptions and register.

Found as accepted answer here

+11
Mar 02 '16 at 17:00
source

Despite the fact that this solution may seem obvious, I just wanted to publish it here so that the next guy would execute it faster.

If you still want to have the model as a parameter in the method, you can create a DelegatingHandler to buffer the contents.

 internal sealed class BufferizingHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { await request.Content.LoadIntoBufferAsync(); var result = await base.SendAsync(request, cancellationToken); return result; } } 

And add it to the global message handlers:

 configuration.MessageHandlers.Add(new BufferizingHandler()); 

This decision is based on Darrell Miller's answer.

Thus, all requests will be buffered.

+3
Sep 28 '16 at 12:56 on
source

The easiest way to read the contents of any request is to use an http proxy, such as fiddler

This has a huge advantage in that you show local traffic all (plus full requests - headers, etc.) and many other requests that read the contents of the request inside a specific action in a specific controller. show you - for example 401/404, etc.

You can also use the violinist composer to create test queries from scratch or by modifying previous queries.

If for some reason you cannot use a proxy or need to view a request from a web application, then this answer looks reasonable

-5
Feb 14 '15 at 6:18
source



All Articles