During the development of a REST API, we had a need to authenticate a request prior to allowing the response to be processed within the controller, and so this created a need to be able to read the header as well as the form (if any) to determine if the credentials were passed into the request within the body of the form rather than through the request header.
A few lines of code reset the stream pointer to the beginning of the stream so that MVC would be able to read the form and populate the view model in the controller
public class WebServiceAuthenticationAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
var authenticationHeaderValue = actionContext.Request.Headers.Authorization;
try
{
if (authenticationHeaderValue != null)
{
var webRequestInfo = new WebRequestInfo(actionContext.Request.Method, actionContext.Request.RequestUri);
this.AuthenticationHeaderService.LogOnUsingAuthenticationHeader(authenticationHeaderValue, webRequestInfo);
}
else if (actionContext.Request.Content.IsFormData())
{
Task<NameValueCollection> formVals = actionContext.Request.Content.ReadAsFormDataAsync();
this.AuthenticationFormService.LogOnUsingFormsAuthentication(formVals.Result);
// reset the underlying stream to the beginning so that others may use it in the future...
using (var s = new System.IO.MemoryStream())
{
var ctx = (HttpContextBase) actionContext.Request.Properties["MS_HttpContext"];
ctx.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
}
}
}
catch (Exception)
{
throw;
}
}
}
Initially the data model was not being created by MVC and a null was passed into the controller method. After resetting the stream, MVC was able to read the form, create and populate the data model, and pass it into the controller method.
[WebServiceAuthentication]
public HttpResponseMessage Get(DocumentRequestModel requestForm)
{
var response = CreateResponse(HttpStatusCode.OK);
response.Content = new ByteArrayContent(this.documentService.GetDocument(requestForm.DocumentId.ToString()));
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}