Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API action filter content can't be read

Related question: Web API action parameter is intermittently null and http://social.msdn.microsoft.com/Forums/vstudio/en-US/25753b53-95b3-4252-b034-7e086341ad20/web-api-action-parameter-is-intermittently-null

Hi!

I'm creating a ActionFilterAttribute in ASP.Net MVC WebAPI 4 so I can apply the attribute in action methods at the controller that we need validation of a token before execute it as the following code:

public class TokenValidationAttribute : ActionFilterAttribute
{
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
        //Tried this way
        var result = string.Empty;
        filterContext.Request.Content.ReadAsStringAsync().ContinueWith((r)=> content = r.Result);

        //And this
        var result = filterContext.Request.Content.ReadAsStringAsync().Result;

        //And this
        var bytes = await request.Content.ReadAsByteArrayAsync().Result;
        var str = System.Text.Encoding.UTF8.GetString(bytes);

        //omit the other code that use this string below here for simplicity
    }
}

I'm trying to read the content as string. Tried the 3 ways as stated in this code, and all of them return empty. I know that in WebApi I can read only once the body content of the request, so I'm commenting everything else in the code, and trying to get it run to see if I'm getting a result. The point is, the client and even the Fiddler, reports the 315 of the content length of the request. The same size is getting on the server content header as well but, when we try read the content, it is empty.

If I remove the attribute and make the same request, the controller is called well, and the deserialization of Json happens flawless. If I put the attribute, all I get is a empty string from the content. It happens ALWAYS. Not intermittent as the related questions state.

What am I doing wrong? Keep in mind that I'm using ActionFilter instead of DelegatingHandler because only selected actions requires the token validation prior to execution.

Thanks for help! I really appreciate it.

Regards...

Gutemberg

like image 469
Gutemberg Ribeiro Avatar asked Aug 20 '13 16:08

Gutemberg Ribeiro


1 Answers

By default the buffer policy for Web Host(IIS) scenarios is that the incoming request's stream is always buffered. You can take a look at System.Web.Http.WebHost.WebHostBufferPolicySelector. Now as you have figured, Web Api's formatters will consume the stream and will not try to rewind it back. This is on purpose because one could change the buffer policy to make the incoming request's stream to be non-buffered in which case the rewinding would fail.

So in your case, since you know that the request is going to be always buffered, you could get hold of the incoming stream like below and rewind it.

Stream reqStream = await request.Content.ReadAsStreamAsync();

if(reqStream.CanSeek)
{
     reqStream.Position = 0;
}

//now try to read the content as string
string data = await request.Content.ReadAsStringAsync();
like image 50
Kiran Avatar answered Oct 13 '22 17:10

Kiran