2013-08-27 67 views
3

我面臨的情況是,我必須從ASP.NET Web API的傳入請求中讀取表單數據兩次(從模型聯編程序和篩​​選器)。我試過使用LoadIntoBufferAsync,但沒有運氣。調用ReadAsFormDataAsync兩次

// from model binder 
Request.Content.LoadIntoBufferAsync().Wait(); 
var formData = Request.Content.ReadAsFormDataAsync().Result; 

// from filter 
var formData = Request.Content.ReadAsFormDataAsync().Result; 
+0

將有助於創建一個repro。 – Aliostad

回答

1

問題是內容的底層緩衝區是隻能讀取一次的只向前流。

爲什麼你需要讀兩遍?多一點背景會有所幫助。是從兩個單獨的過濾器中讀取嗎​​?

編輯:可能會嘗試直接從MS_HttpContext讀取並使用它作爲您的內容流(不要認爲這在自己託管的環境中工作)。

using (var s = new System.IO.MemoryStream()) { 
    var ctx = (HttpContextBase)actionContext.Request.Properties["MS_HttpContext"]; 
    ctx.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
    ctx.Request.InputStream.CopyTo(s); var body = 
    System.Text.Encoding.UTF8.GetString(s.ToArray()); 
} 
+0

感謝您回答Alex。我正在閱讀模型粘合劑和過濾器。 – VJAI

+0

也許你可以直接從HttpContext中讀取 - 我不認爲它可以在自己託管的場景中工作。我會在我的答案中添加一些代碼。 – AlexGad

+0

我在上面添加了一些代碼,也許你在你的過濾器中使用它,然後閱讀模型聯編程序中的內容?如果上述不起作用,我認爲你也可以直接尋找底層緩衝區。 – AlexGad

0

你真的不應該這樣做。在一天結束時,HttpContext流指向Web API讀取的同一個流。

你可以嘗試把LoadIntoBufferAsync放在兩個地方,因爲一個人可以在另一個地方觸發,它已經在緩衝區中,呼叫LoadIntoBufferAsync沒有副作用。

// from model binder 
Request.Content.LoadIntoBufferAsync().Wait(); 
var formData = Request.Content.ReadAsFormDataAsync().Result; 

// from filter 
Request.Content.LoadIntoBufferAsync().Wait(); 
var formData = Request.Content.ReadAsFormDataAsync().Result; 
+0

你可以發佈代碼嗎? – VJAI

+0

@Mark我剛剛做到了。 – Aliostad

+0

今天到辦公室時我會試試這個。 – VJAI

0

在一個REST API的發展,我們有必要在允許要在控制器內處理的響應進行認證的請求,並且因此這創造了一個需要能夠讀取頭,以及作爲表單(如果有的話)來確定憑證是否通過表單主體而不是通過請求頭傳遞到請求中。

的幾行代碼流指針復位到流的開始,使MVC將能夠讀取的形式並填充視圖模型在控制器

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; 
      } 
     } 
    } 

最初數據模型不是由MVC創建,並將null傳遞給控制器​​方法。重置流之後,MVC能夠讀取表單,創建並填充數據模型,並將其傳遞到控制器方法中。

[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; 
}