2015-07-13 14 views
6

मैं प्रमाणीकरण उद्देश्यों के लिए शरीर को मिडलवेयर में पढ़ने की कोशिश कर रहा हूं, लेकिन जब अनुरोध एपीआई नियंत्रक को मिलता है तो वस्तु खाली होती है क्योंकि शरीर पहले से ही पढ़ा जा चुका है। वैसे भी इसके आसपास है। मैं इस तरह के शरीर को अपने मिडलवेयर में पढ़ रहा हूं।अनुरोध निकाय दो बार

var buffer = new byte[ Convert.ToInt32(context.Request.ContentLength) ]; 
await context.Request.Body.ReadAsync(buffer, 0, buffer.Length); 
var body = Encoding.UTF8.GetString(buffer); 
+1

बस उत्सुक पुन: पढ़ने: तुम क्यों जब प्रमाणीकरण प्रदर्शन अनुरोध के शरीर पढ़ रहे हैं? –

+0

यह एक एपीआई है जहां उदाहरण के लिए अनुरोध अनुरोध को सुरक्षित करने के लिए एपीकी की भी आवश्यकता है और अनुरोध को सुरक्षित करने के लिए हैश भी है। जो शीर्षकों में होने का अर्थ नहीं है। –

+0

एक [उदाहरण] (http://stackoverflow.com/questions/42561350/read-json-post-data-in-asp-net-core-mvc/42922579#42922579) पिनपॉइंट के सक्षम रिवाइंड का उपयोग करने से शरीर से जेसन पढ़ने के लिए। –

उत्तर

14

आप application/x-www-form-urlencoded या multipart/form-data का उपयोग कर रहे हैं, तो आप सुरक्षित रूप से के रूप में यह आगामी कॉल पर एक कैश्ड उदाहरण देता context.Request.ReadFormAsync() कई बार फोन कर सकते हैं।

यदि आप एक अलग सामग्री प्रकार का उपयोग कर रहे हैं, तो आपको अनुरोध को मैन्युअल रूप से बफर करना होगा और अनुरोध निकाय को MemoryStream जैसे रिवाइंडेबल स्ट्रीम द्वारा प्रतिस्थापित करना होगा। यहां आपके द्वारा किसी इनलाइन मिडलवेयर का उपयोग कर सकता है (यदि आप अपने पाइप लाइन में जल्द ही यह रजिस्टर करने की आवश्यकता):

app.Use(next => async context => { 
    // Keep the original stream in a separate 
    // variable to restore it later if necessary. 
    var stream = context.Request.Body; 

    // Optimization: don't buffer the request if 
    // there was no stream or if it is rewindable. 
    if (stream == Stream.Null || stream.CanSeek) { 
     await next(context); 

     return; 
    } 

    try { 
     using (var buffer = new MemoryStream()) { 
      // Copy the request stream to the memory stream. 
      await stream.CopyToAsync(buffer); 

      // Rewind the memory stream. 
      buffer.Position = 0L; 

      // Replace the request stream by the memory stream. 
      context.Request.Body = buffer; 

      // Invoke the rest of the pipeline. 
      await next(context); 
     } 
    } 

    finally { 
     // Restore the original stream. 
     context.Request.Body = stream; 
    } 
}); 

तुम भी BufferingHelper.EnableRewind() विस्तार है, जो Microsoft.AspNet.Http पैकेज का हिस्सा है का उपयोग कर सकते हैं: यह एक समान दृष्टिकोण पर आधारित है FYI करें

app.Use(next => context => { 
    context.Request.EnableRewind(); 

    return next(context); 
}); 

: लेकिन एक विशेष धारा है कि स्मृति में बफरिंग डेटा शुरू होता है और डिस्क पर एक अस्थायी फ़ाइल के लिए सब कुछ spools पर निर्भर करता है जब सीमा तक पहुंचने पर एक बफरिंग मिडलवेयर शायद भविष्य में vNext में जोड़ दिया जाएगा।

+2

मैं कैशिंग के बारे में उत्सुक हूँ। क्या वह अनुबंध या कार्यान्वयन विस्तार का वह हिस्सा है जो भविष्य में बदल सकता है? –

+1

@Pinpoint धन्यवाद इस बारे में नहीं सोचा था कि यह एक अच्छा विचार है। –

+0

@ निकट भविष्य में सिमोनबेलगर, मेजबान और मिडलवेयर शायद यह इंगित करने के लिए एक आम अनुबंध साझा करेंगे कि वे बफरिंग का समर्थन करते हैं या नहीं। अधिक जानकारी के लिए आप इस विकी पेज पर अधिक जानकारी प्राप्त कर सकते हैं: https://github.com/aspnet/HttpAbstractions/wiki/Rolling- नोट्स – Pinpoint

3

EnableRewind

Startup.cs 
using Microsoft.AspNetCore.Http.Internal; 

Startup.Configure(...){ 
... 
//Its important the rewind us added before UseMvc 
app.Use(next => context => { context.Request.EnableRewind(); return next(context); }); 
app.UseMvc() 
... 
} 

फिर से ठीक से निर्धारित की उल्लेख के लिए प्रयोग अपने मिडलवेयर में आप सिर्फ रिवाइंड करने और

private async Task GenerateToken(HttpContext context) 
    { 
    context.Request.EnableRewind(); 
    string jsonData = new StreamReader(context.Request.Body).ReadToEnd(); 
    ... 
    } 
संबंधित मुद्दे