यह एक पुराना धागा है, लेकिन जब से मैं यहां आया, मुझे लगा कि मैं अपने निष्कर्षों को पोस्ट करूंगा ताकि वे दूसरों की मदद कर सकें।
सबसे पहले, मेरे पास एक ही मुद्दा था, जहां मैं अनुरोध प्राप्त करना चाहता था। बॉडी और उस (लॉगिंग / ऑडिटिंग) के साथ कुछ करना चाहिए। लेकिन अन्यथा मैं चाहता था कि समापन बिंदु समान दिखे।
तो, यह लग रहा था कि EnableBuffering () कॉल चाल कर सकती है। फिर आप शरीर पर एक सीक (0, एक्सएक्सएक्स) कर सकते हैं और सामग्री को फिर से पढ़ सकते हैं, आदि।
हालाँकि, इससे मेरा अगला मुद्दा बन गया। जब समापन बिंदु तक पहुँच हो, तो मुझे "सिन्कोर्नस संचालन रोक दिया जाता है" अपवाद। इसलिए, विकल्प में संपत्ति AllowSynchronousIO = true को सेट करने के लिए वर्कअराउंड है। इसे पूरा करने के कई तरीके हैं (लेकिन यहां पर विस्तार से बताना महत्वपूर्ण नहीं है ..)
फिर, अगला मुद्दा यह है कि जब मैं अनुरोध पढ़ने के लिए जाता हूं। लेकिन यह पहले ही निपटा दिया गया है। ओह। तो, क्या देता है?
मैं एंडपियन कॉल में न्यूटनसॉफ्ट.जॉन को अपने [FromBody] पार्सर के रूप में उपयोग कर रहा हूं। यही वह है जो सिंक्रोनस रीड के लिए जिम्मेदार है और जब यह पूरा हो जाता है तो यह स्ट्रीम को भी बंद कर देता है। उपाय? JSON को पार्स करने से पहले स्ट्रीम पढ़ें यकीन है, कि काम करता है और मैं इस के साथ समाप्त हुआ:
/// <summary>
/// quick and dirty middleware that enables buffering the request body
/// </summary>
/// <remarks>
/// this allows us to re-read the request body's inputstream so that we can capture the original request as is
/// </remarks>
public class ReadRequestBodyIntoItemsAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context == null) return;
// NEW! enable sync IO beacuse the JSON reader apparently doesn't use async and it throws an exception otherwise
var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
var req = context.HttpContext.Request;
req.EnableBuffering();
// read the body here as a workarond for the JSON parser disposing the stream
if (req.Body.CanSeek)
{
req.Body.Seek(0, SeekOrigin.Begin);
// if body (stream) can seek, we can read the body to a string for logging purposes
using (var reader = new StreamReader(
req.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false,
bufferSize: 8192,
leaveOpen: true))
{
var jsonString = reader.ReadToEnd();
// store into the HTTP context Items["request_body"]
context.HttpContext.Items.Add("request_body", jsonString);
}
// go back to beginning so json reader get's the whole thing
req.Body.Seek(0, SeekOrigin.Begin);
}
}
}
}
इसलिए अब, मैं [ReadRequestBodyIntoItems] विशेषता वाले समापन बिंदुओं में HttpContext.Items ["request_body"] का उपयोग करके शरीर तक पहुंच सकता हूं।
लेकिन यार, ऐसा लगता है जैसे बहुत से हूपों के माध्यम से कूदना है। तो यहाँ मैं कहाँ समाप्त हो गया, और मैं वास्तव में इसके साथ खुश हूँ।
मेरा समापन बिंदु कुछ इस तरह शुरू हुआ:
[HttpPost("")]
[ReadRequestBodyIntoItems]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData([FromBody] MyJsonObjectType value)
{
val bodyString = HttpContext.Items["request_body"];
// use the body, process the stuff...
}
लेकिन यह सिर्फ हस्ताक्षर बदलने के लिए बहुत अधिक सीधा है, जैसे:
[HttpPost("")]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData()
{
using (var reader = new StreamReader(
Request.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false
))
{
var bodyString = await reader.ReadToEndAsync();
var value = JsonConvert.DeserializeObject<MyJsonObjectType>(bodyString);
// use the body, process the stuff...
}
}
मुझे यह वास्तव में पसंद आया क्योंकि यह केवल एक बार शरीर की धारा को पढ़ता है, और मेरे पास डीसेरलाइज़ेशन का नियंत्रण है। यकीन है, यह अच्छा है अगर ASP.NET कोर मेरे लिए यह जादू करता है, लेकिन यहां मैं दो बार स्ट्रीम पढ़ने में समय बर्बाद नहीं करता (शायद हर बार बफरिंग), और कोड काफी स्पष्ट और साफ है।
यदि आपको बहुत से समापन बिंदुओं पर इस कार्यक्षमता की आवश्यकता है, तो शायद मिडलवेयर दृष्टिकोण क्लीनर हो सकता है, या आप कोड को अधिक संक्षिप्त बनाने के लिए शरीर के निष्कर्षण को कम से कम विस्तार समारोह में संलग्न कर सकते हैं।
वैसे भी, मुझे इस मुद्दे के सभी 3 पहलुओं को छूने वाला कोई स्रोत नहीं मिला, इसलिए यह पोस्ट। उम्मीद है कि यह किसी की मदद करता है!
BTW: यह ASP .NET कोर 3.1 का उपयोग कर रहा था।