Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get hold of Content that is already read

Tags:

I have a class that inherits from ApiController. It has a Put-method like this:

[PUT("user/{UserId}")] public HttpResponseMessage Put(string userId, PaymentRequest paymentRequest) {     // Calling business logic and so forth here     // Return proper HttpResponseMessage here } 

The method works fine as it is above. Now I need to validate the signature of the method call, but here I run into a problem. The signature is essentially a combination of method + url + body. The method I can get by calling Request.Method and the url I can get by calling Request.RequestUri.ToString(), but I can't get hold of the body as it was before it was automatically deserialized into a PaymentRequest object by the asp.net MVC4 framework.

My first try: As I have now understood Request.Content.ReadAsStringAsync().Result returns nothing. This is because the content can only be read once.

My second try: I tried to serialize it back to a JSON string.

var serializer = new JavaScriptSerializer(); var paymentRequestAsJson = serializer.Serialize(paymentRequest); 

The problem with this is that the formatting turns out slightly different than the body part of the signature. It has the same data, but some more spaces.

I can't change what the caller of my Put-method does, as this is a third party component. What should I do?

like image 278
Halvard Avatar asked Aug 10 '12 12:08

Halvard


People also ask

Why can't I retain information when I read?

After reading, you may find it almost impossible to retain the information acquired. It may be due to lack of adequate sleep and rest, distractions while reading, poor nutrition, failure to choose the right book, or memory issues such as decay or shallow processing.


2 Answers

You could read from the underlying request:

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()); } 
like image 158
Darin Dimitrov Avatar answered Sep 20 '22 07:09

Darin Dimitrov


Don't include the body parameter in the signature and that will allow you to buffer the content and read the content as many times as you like.

[PUT("user/{UserId}")] public HttpResponseMessage Put(string userId) {     Request.Content.LoadIntoBufferAsync().Wait();     var paymentRequest = Request.Content.ReadAsAsync<PaymentRequest>().Result;     var requestBody = Request.Content.ReadAsStringAsync().Result;     // Calling business logic and so forth here     // Return proper HttpResponseMessage here } 
like image 34
Darrel Miller Avatar answered Sep 22 '22 07:09

Darrel Miller