2010-12-21 17 views
11

एएसपी.नेट एमवीसी 3 आरसी 2 में, डिफ़ॉल्ट मॉडलबिंडर स्वचालित रूप से अनुरोध निकाय को पार्स करेगा यदि Content-Typeapplication/json पर सेट है। समस्या यह है कि, स्ट्रीम के अंत में Request.InputStream छोड़ देता है। इसका मतलब यह है कि अगर आप अपने खुद के कोड का उपयोग कर इनपुट धारा पढ़ने की कोशिश, तो आपको पहले शुरुआत करने के लिए इसे वापस रीसेट:क्या एएसपी.नेट एमवीसी 3 आरसी 2 में जेएसओएन मॉडलबिंडर को अक्षम करने का कोई तरीका है?

// client sends HTTP request with Content-Type: application/json and a JSON 
// string in the body 

// requestBody is null because the stream is already at the end 
var requestBody = new StreamReader(Request.InputStream).ReadToEnd(); 

// resets the position back to the beginning of the input stream 
var reader = new StreamReader(Request.InputStream); 
reader.BaseStream.Position = 0; 
var requestBody = reader.ReadToEnd(); 

जब से मैं Json.NET उपयोग कर रहा हूँ मेरी क्रमबद्धता/अक्रमांकन ऐसा करने के लिए, मैं करना चाहते हैं इस अतिरिक्त पार्सिंग करने से डिफ़ॉल्ट मॉडलबिंडर को अक्षम करने के लिए। क्या उसे करने का कोई तरीका है?

उत्तर

15

आप अपने Global.asax में Application_Start में निम्नलिखित रख सकते हैं:

ValueProviderFactories.Factories.Remove(
      ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().First()); 

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

+0

धन्यवाद, यह चाल है! क्या यह एक अनियंत्रित सुविधा है, या क्या मुझे कुछ याद आया? –

+0

एमवीसी में डिफ़ॉल्ट रूप से मूल्य प्रदाता कारखानों का एक सेट शामिल है। एमवीसी 3 के साथ, उन्होंने जेसनवेलुप्रोवाइडर फैक्ट्री को डिफ़ॉल्ट में से एक के रूप में शामिल किया। उपरोक्त सभी कोड इसे ढूंढते हैं और एप्लिकेशन शुरू होने पर इसे हटा देते हैं। इसके आस-पास एक और तरीका आपके AJAX अनुरोधों को सामग्री प्रकार एप्लिकेशन/जेसन का उपयोग नहीं करना पड़ सकता था, लेकिन मुझे लगता है कि मूल्य प्रदाता कारखाने को हटाने शायद अधिक सही है। स्पष्टीकरण के लिए –

+0

धन्यवाद। मुझे यह भी पता नहीं था कि क्वेरीस्ट्रिंग और मार्ग जैसी चीजों के लिए प्रदाता कारखानों थे। मुझे लगता है कि मॉडलबिंडर ने उन सभी को संभाला था। –

0

मुझे इसका उत्तर देने में काफी देर हो चुकी है, लेकिन मैंने एमवीसी 5 में एक विशिष्ट कार्रवाई के लिए IValueProvider को बदलने का एक तरीका विकसित किया है। मैं यह देखने के प्रयास से गुजर चुका हूं कि यह एमवीसी 3 में संभव है क्योंकि यह सवाल पुराना है, लेकिन मुझे लगता है कि यह कुछ हद तक समान है।

अस्वीकरण: यह सुंदर नहीं है।

सबसे पहले, हम एक नए इंटरफ़ेस हम एक विशेषता में लागू कर सकते हैं कार्रवाई विशिष्ट विन्यास बनाने के लिए बनाने के लिए:

internal interface IActionConfigurator 
{ 
    void Configure(ControllerContext controllerContext, ActionDescriptor actionDescriptor); 
} 

फिर, हम एक कस्टम ControllerActionInvoker बनाने (या AsyncControllerActionInvoker अगर आप async का उपयोग करें) ऊपर हुक करने के लिए हमारे नए इंटरफ़ेस:

internal sealed class CustomControllerActionInvoker : AsyncControllerActionInvoker 
{ 
    protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) 
    { 
     var actionDescriptor = base.FindAction(controllerContext, controllerDescriptor, actionName); 
     var configurators = actionDescriptor.GetCustomAttributes(typeof(IActionConfigurator), true).Cast<IActionConfigurator>(); 
     foreach (var configurator in configurators) 
      configurator.Configure(controllerContext, actionDescriptor); 
     return actionDescriptor; 
    } 
} 

अब, हम स्थापित करने के लिए एक कस्टम DefaultControllerFactory लागू करना Controller.ActionInvoker:

+०१२३५१६४१०

ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory)); 

और कस्टम विशेषता में हमारे IActionConfigurator इंटरफ़ेस को लागू:

internal sealed class IgnoreJsonActionConfiguratorAttribute : Attribute, IActionConfigurator 
{ 
    public void Configure(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     // Here we can configure action-specific stuff on the controller 
     var factories = ValueProviderFactories.Factories.Where(f => !(f is JsonValueProviderFactory)).ToList(); 
     controllerContext.Controller.ValueProvider = new ValueProviderFactoryCollection(factories).GetValueProvider(controllerContext); 
    } 
} 

एक नया नियंत्रक उदाहरण के बाद से

internal sealed class CustomControllerFactory : DefaultControllerFactory 
{ 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     var instance = base.GetControllerInstance(requestContext, controllerType); 
     var controller = instance as Controller; 
     if (controller != null) 
      controller.ActionInvoker = new CustomControllerActionInvoker(); 
     return instance; 
    } 
} 

अंत में, हम स्टार्टअप कोड में डिफ़ॉल्ट के रूप में हमारे कस्टम नियंत्रक कारखाने सेट प्रत्येक अनुरोध पर बनाया गया है, हम संशोधित करने के लिए नियंत्रक पर क्रिया-विशिष्ट मान सेट करने में सक्षम हैं कि एमवीसी कार्रवाई को कैसे संसाधित करता है।

[AcceptVerbs(HttpVerbs.Post)] 
[IgnoreJsonActionConfigurator] 
public async Task<ActionResult> Foo() { ... } 
संबंधित मुद्दे