2012-08-17 7 views
14

से बॉडी डेटा नहीं पढ़ सकता है, मैं नए Asp.Net Web Api में किसी अनुरोध से कुछ डेटा निकालने का प्रयास कर रहा हूं। मैं इस तरह के हैंडलर सेटअप:वेब एपीआई पोस्ट

public class MyTestHandler : DelegatingHandler 
{ 
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     if (request.Content.IsFormData()) 
     { 
      request.Content.ReadAsStreamAsync().ContinueWith(x => { 
       var result = ""; 
       using (var sr = new StreamReader(x.Result)) 
       { 
        result = sr.ReadToEnd(); 
       } 
       Console.Write(result); 
      }); 
     } 

     return base.SendAsync(request, cancellationToken); 
    } 
} 

यह मेरा http अनुरोध है:

POST http://127.0.0.1/test HTTP/1.1 
Connection: Keep-Alive 
Content-Length: 29 
Content-Type: application/x-www-form-urlencoded 
Expect: 100-continue 
Host: 127.0.0.1 

my_property=my_value 

समस्या यह है कि कोई फर्क नहीं पड़ता कि कैसे मैं request.Content से जानकारी पढ़ने की कोशिश यह हमेशा खाली है। मैं

request.Content.ReadAsStreamAsync 
request.Content.ReadAsFormDataAsync 
request.Content.ReadAs<FormDataCollection> 

के साथ-साथ

[HttpGet,HttpPost] 
    public string Index([FromBody]string my_property) 
    { 
     //my_property == null 
     return "Test"; 
    } 

कोई भी कोशिश की है, तो यह काम करता है है। मैं शरीर से डेटा नहीं प्राप्त कर सकता। मैं विंडोज 7 पर आईआईएस के अंदर होस्टिंग कर रहा हूं और अनुरोध सबमिट करने के लिए फिडलर का उपयोग कर रहा हूं। मैं क्या गलत कर रहा हूं?

+0

यह जानना उपयोगी होगा कि एक स्वतंत्र ग्राहक wcftestclient.exe जैसा समान परिणाम उत्पन्न करता है या नहीं। –

+0

इसे चलाने की कोशिश की लेकिन यह नहीं है क्योंकि यह कहता है कि मेरे एंडपॉइंट में कोई मेटाडेटा नहीं है। – Micah

+0

वह अजीब अजीब लग रहा है। क्या कोई कारण है कि आप प्रदत्त [HttpGet] और [HttpPost] पद्धति पर डेटा हस्तांतरण की इस विधि को चुन रहे हैं? –

उत्तर

20

समस्या यह है कि वेब एपी के साथ शरीर को केवल एक बार पढ़ा जा सकता है। मेरे पास एक HTTP मॉड्यूल चल रहा था जो अनुरोध के सभी विवरण लॉगिंग कर रहा था और शरीर के माध्यम से पढ़ रहा था।

+0

हां, तो इस तरह कर रही है लॉग इन करने की संभावना नहीं है, है ना ?? – kooldave98

+1

यह संभव है, आपको पहले LoadIntoBufferAsync() विधि का उपयोग करके इसे पहले एक बफर में पढ़ने की आवश्यकता है। यह सामग्री को मूल विधि के लिए अभी भी उपलब्ध कराता है। यहां से https://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi – Tom

0

मेरे पास एक ही समस्या थी और आखिर में लॉग में सामग्री लिखना नहीं चुना। मैं सामग्री-प्रकार और सामग्री-लंबाई लॉगिंग के साथ रह रहा हूं।

लेकिन जहां तक ​​संभव हो सके लॉग में सभी सामग्री लिखना हमेशा अच्छा विचार है।

लेकिन ऐसा लगता है कि वेबएपी के साथ वर्तमान में हम इसे प्राप्त नहीं कर सकते हैं।

7

यह बदसूरत है, लेकिन आप यह प्रारंभिक फेरबदल है कि आप, वास्तव में, DelegatingHandler में सामग्री की जगह ले सकता से लगता है ...

protected override Task SendAsync(
      HttpRequestMessage request, 
      CancellationToken cancellationToken) 
     {      
      Stream stream = new MemoryStream(); 

      request.Content.ReadAsStreamAsync().Result.CopyTo(stream); 
      stream.Seek(0,SeekOrigin.Begin); 

      // copy off the content "for later" 
      string query = new StreamReader(stream).ReadToEnd(); 
      stream.Seek(0,SeekOrigin.Begin); 

      // if further processing depends on content type 
      // go ahead and grab current value 
      var contentType = request.Content.Headers.ContentType; 

      request.Content = new StreamContent(stream); 
      request.Content.Headers.ContentType = contentType; 

      return base.SendAsync(request, cancellationToken); 
    } 

मैं पता नहीं अगर यह अच्छा है या बुरा प्रपत्र (संदिग्ध बुरा है), लेकिन .... ऐसा लगता है कि मॉडल काम करता है और मॉडल का पालन करता है, मैंने उन लोगों के लिए अनुशंसा की है जिन्हें अनुरोध हेडर और सामग्री को "रास्ते में" डिलीगेटिंग हैंडलर के साथ संशोधित करने की आवश्यकता है।

आपका लाभ काफी भिन्न हो सकता है।

6

मैं ब्रॉम के कोड पर अपना उत्तर आधारित करता हूं;

इस समारोह सुरक्षित किसी भी हैंडलर

private string SafeReadContentFrom(HttpRequestMessage request) 
{ 
    var contentType = request.Content.Headers.ContentType; 
    var contentInString = request.Content.ReadAsStringAsync().Result; 
    request.Content = new StringContent(contentInString); 
    request.Content.Headers.ContentType = contentType; 
    return contentInString; 
} 
0

आप एक प्रदाता पहले बना सकते हैं में सामग्री पढ़ सकते हैं। MultipartMemoryStreamProvider() फिर Request.Content.ReadAsMultipartAsync(provider); फिर सामग्री

public async Task<IHttpActionResult> Post(int id, string type) 
{ 
    // Check if the request contains multipart/form-data. 
    if(!Request.Content.IsMimeMultipartContent("form-data")) 
     return BadRequest("Unsupported media type"); 

    try 
    { 
     var azureManager = new AzureManager(); 
     var imageManager = new ImageManager(); 
     var provider = new MultipartMemoryStreamProvider(); 

     await Request.Content.ReadAsMultipartAsync(provider); 

     var assets = new List<Asset>(); 
     foreach (var file in provider.Contents) 
     { 
      var stream = await file.ReadAsStreamAsync(); 
      var guid = Guid.NewGuid(); 
      string blobName = guid.ToString(); 

      await azureManager.UploadAsync(blobName, stream); 

      var asset = new Asset 
      { 
       PropertyId = id, 
       FileId = guid, 
       FileName = file.Headers.ContentDisposition.FileName.Trim('\"').ToLower(), 
       FileSize = file.Headers.ContentLength ?? 0, 
       MimeType = file.Headers.ContentType.MediaType.ToLower() 
      }; 

      if (type == "photos") 
      { 
       asset.Type = AssetType.Photo; 

       // Resize and crop copies to 16:9 
       using (MemoryStream thumb = imageManager.ResizeImage(stream, 320, 180)) 
       { 
        await azureManager.UploadAsync(blobName, thumb, BlobContainers.Thumbs); 
       } 
       using (MemoryStream photo = imageManager.ResizeImage(stream, 1024, 576)) 
       { 
        await azureManager.UploadAsync(blobName, photo, BlobContainers.Photos); 
       } 
      } 
      else 
       asset.AssumeType(); 

      assets.Add(asset); 
     } 

     db.Assets.AddRange(assets); 
     await db.SaveChangesAsync(); 

     return Ok(new { Message = "Assets uploaded ok", Assets = assets }); 
    } 
    catch (Exception ex) 
    { 
     return BadRequest(ex.GetBaseException().Message); 
    } 
} 
2

यह मेरे लिए काम करता है।

[HttpPost] 
public IHttpActionResult Index(HttpRequestMessage request) 
{ 
    var form = request.Content.ReadAsFormDataAsync().Result; 
    return Ok(); 
}