जावास्क्रिप्ट के दौरान ASP.NET MVC में MaxJsonLength अपवाद


122

अपने नियंत्रक कार्यों में से एक में मैं एक बहुत बड़ी वापसी कर रहा हूं JsonResult एक ग्रिड को भरने के लिए ।

मुझे निम्नलिखित मिल रहा है InvalidOperationException अपवाद हैं:

JSON JavaScriptSerializer का उपयोग करके क्रमांकन या डीरिएलाइज़ेशन के दौरान त्रुटि। स्ट्रिंग की लंबाई maxJsonLength संपत्ति पर निर्धारित मूल्य से अधिक है।

maxJsonLengthसंपत्ति को web.configउच्च मूल्य में सेट करना दुर्भाग्य से कोई प्रभाव नहीं दिखाता है।

<system.web.extensions>
  <scripting>
    <webServices>
      <jsonSerialization maxJsonLength="2147483644"/>
    </webServices>
  </scripting>
</system.web.extensions>

मैं के रूप में में वर्णित एक स्ट्रिंग के रूप में इसे वापस पारित करने के लिए नहीं करना चाहते हैं यह तो जवाब।

अपने शोध में मैं इस ब्लॉग पोस्ट पर आया था जहाँ इस व्यवहार को दरकिनार करने के लिए स्वयं ActionResult(जैसे LargeJsonResult : JsonResult) लिखना अनुशंसित है।

क्या यह एकमात्र समाधान है?
यह ASP.NET MVC में एक बग है?
क्या मैं कुछ भूल रहा हूँ?

कोई भी सहायता सराहनीय होगी।


2
आपका समाधान MVC 3 पर काम करता है
MatteoSp

1
@Matteo क्या आपको यकीन है? यह एक पुराना सवाल है और मुझे याद नहीं आ रहा है लेकिन जाहिर तौर पर मैंने इसे MVC3 के रूप में टैग किया है। दुर्भाग्य से मैं संस्करण / तारीख नहीं देख सकता, जब यह तय / बंद हो गया: aspnet.codeplex.com/workitem/3436
मार्टिन बुबर्ल

1
ज़रूर, मैं एमवीसी 3 के साथ काम कर रहा हूं और यह काम करता है। और सौभाग्य से, क्योंकि एमवीसी 3 में आपके पास स्वीकार किए गए उत्तर में "मैक्सजोन लैंथ" गुण नहीं हैं।
मैट्टोस्प्स

जवाबों:


228

ऐसा प्रतीत होता है कि यह MVC4 में तय किया गया है।

आप ऐसा कर सकते हैं, जिसने मेरे लिए अच्छा काम किया:

public ActionResult SomeControllerAction()
{
  var jsonResult = Json(veryLargeCollection, JsonRequestBehavior.AllowGet);
  jsonResult.MaxJsonLength = int.MaxValue;
  return jsonResult;
}

मैं ViewBag.MyJsonString प्रॉपर्टी में एक json स्ट्रिंग सेट कर रहा हूं, लेकिन जावास्क्रिप्ट लाइन के बाद रनटाइम पर मेरे विचार में एक ही त्रुटि हो रही है: var myJsonObj = @ Html.Raw (Json.EEcode (ViewBag.MyJsonString));
फैसल मक

1
अरे @orionedvards, @ GG, @ MartinBuberl मैं एक ही maxJson समस्या का सामना कर रहा हूं, लेकिन जब नियंत्रक को डेटा पोस्ट कर रहा हूं, तो मैं इसे कैसे संभाल सकता हूं, मैंने इस बारे में खोज करने में इतना समय बिताया है। कोई भी मदद नहीं करेगा।
कटकमानो

मेरे मामले में काम नहीं किया क्योंकि मुझे कलेक्शन को क्रमबद्ध करने से पहले मैक्सजोन लैंथ सेट करना था।
सेसर लियोन

मेरे मामले में ठीक काम करता है, मुझे अंतिम उपयोगकर्ता के लिए प्रस्तुत करने के लिए डेटाटेबल में "IMAGES" के कारण इसे लागू करना पड़ा। इसके बिना, बस किसी भी समझदार संदेश के बिना दुर्घटना।
मौरो कैंडिडो

33

तुम भी इस्तेमाल कर सकते हैं ContentResultके रूप में यहाँ का सुझाव दिया उपवर्गीकरण के बजाय JsonResult

var serializer = new JavaScriptSerializer { MaxJsonLength = Int32.MaxValue, RecursionLimit = 100 };

return new ContentResult()
{
    Content = serializer.Serialize(data),
    ContentType = "application/json",
};

2
मेरे मामले में, एक थकाऊ ऐप पर काम करते हुए, इस समाधान ने मेरे लिए सबसे अच्छा काम किया। बचाया jsonresult लागू करने। धन्यवाद!
क्रिस्टो

25

दुर्भाग्य से web.config सेटिंग को डिफ़ॉल्ट JsonResult कार्यान्वयन द्वारा अनदेखा किया जाता है । इसलिए मुझे लगता है कि इस मुद्दे को दूर करने के लिए आपको एक कस्टम जोंस परिणाम लागू करने की आवश्यकता होगी।


22

कस्टम वर्ग की कोई आवश्यकता नहीं है। यह वह सब है जिसकी आवश्यकता है:

return new JsonResult { Data = Result, MaxJsonLength = Int32.MaxValue };

Resultवह डेटा कहां है जिसे आप क्रमबद्ध करना चाहते हैं।


त्रुटि 137 'System.Web.Mvc.JsonResult' में 'MaxJsonLength' की परिभाषा नहीं है
PUG

इसने मेरे लिए काम किया, हालाँकि अभी भी इसे जोड़ना जरूरी है: JsonRequestBehavior = JsonRequestBehavior.AllowGet
DubMan

5

यदि स्ट्रिंग उत्पन्न करने के लिए Json.NET का उपयोग करते हैं json, तो इसे MaxJsonLengthमूल्य निर्धारित करने की आवश्यकता नहीं है ।

return new ContentResult()
{
    Content = Newtonsoft.Json.JsonConvert.SerializeObject(data),
    ContentType = "application/json",
};

4

मैंने इस लिंक का अनुसरण करके समस्या को हल किया

namespace System.Web.Mvc
{
public sealed class JsonDotNetValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
            throw new ArgumentNullException("controllerContext");

        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return null;

        var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
        var bodyText = reader.ReadToEnd();

        return String.IsNullOrEmpty(bodyText) ? null : new DictionaryValueProvider<object>(JsonConvert.DeserializeObject<ExpandoObject>(bodyText, new ExpandoObjectConverter()), CultureInfo.CurrentCulture);
    }
}

}

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        //Remove and JsonValueProviderFactory and add JsonDotNetValueProviderFactory
        ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
        ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory());
    }

3

मुझे आश्चर्य है कि किसी ने भी परिणाम फ़िल्टर का उपयोग करने का सुझाव नहीं दिया है। यह कार्रवाई / परिणाम पाइपलाइन में वैश्विक रूप से हुक करने का सबसे साफ तरीका है:

public class JsonResultFilter : IResultFilter
{
    public int? MaxJsonLength { get; set; }

    public int? RecursionLimit { get; set; }

    public void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (filterContext.Result is JsonResult jsonResult)
        {
            // override properties only if they're not set
            jsonResult.MaxJsonLength = jsonResult.MaxJsonLength ?? MaxJsonLength;
            jsonResult.RecursionLimit = jsonResult.RecursionLimit ?? RecursionLimit;
        }
    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {
    }
}

फिर, उस वर्ग का उपयोग करके एक उदाहरण दर्ज करें GlobalFilters.Filters:

GlobalFilters.Filters.Add(new JsonResultFilter { MaxJsonLength = int.MaxValue });

2

आप अपने LINQ अभिव्यक्ति को केवल उस क्षेत्र में परिभाषित करने का प्रयास कर सकते हैं जिसकी आपको आवश्यकता होगी।

उदाहरण। कल्पना करें कि आपके पास एक मॉडल है जिसमें आईडी, नाम, फोन और चित्र (बाइट सरणी) है और एक चुनिंदा सूची में json से लोड करने की आवश्यकता है।

LINQ क्वेरी:

var listItems = (from u in Users where u.name.Contains(term) select u).ToList();

यहां समस्या " यू का चयन करें " है जो सभी क्षेत्रों को प्राप्त करती है। तो, अगर आपके पास बड़ी तस्वीरें हैं, तो बूओम।

कैसे हल करें? बहुत, बहुत सरल।

var listItems = (from u in Users where u.name.Contains(term) select new {u.Id, u.Name}).ToList();

सर्वोत्तम अभ्यास केवल उस फ़ील्ड का चयन करते हैं जिसका आप उपयोग करेंगे।

याद है। यह एक सरल टिप है, लेकिन कई ASP.NET MVC डेवेलपर्स की मदद कर सकता है।


1
मैं यह नहीं मानूंगा कि इस मामले में उपयोगकर्ता अपने डेटा को फ़िल्टर करना चाहता है। कुछ लोगों को डेटाबेस से बड़ी मात्रा में पंक्तियों को वापस लाने की आवश्यकता है ...
साइमन निकोल्स

2

वैकल्पिक ASP.NET MVC 5 फिक्स:

मेरे मामले में अनुरोध के दौरान त्रुटि हो रही थी। मेरे परिदृश्य में सर्वश्रेष्ठ दृष्टिकोण वास्तविक को संशोधित कर रहा है JsonValueProviderFactoryजो वैश्विक परियोजना के लिए लागू होता है और global.csइस तरह फ़ाइल को संपादित करके किया जा सकता है ।

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

web.config प्रविष्टि जोड़ें:

<add key="aspnet:MaxJsonLength" value="20971520" />

और फिर निम्नलिखित दो कक्षाएं बनाएं

public class JsonValueProviderConfig
{
    public static void Config(ValueProviderFactoryCollection factories)
    {
        var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single();
        factories.Remove(jsonProviderFactory);
        factories.Add(new CustomJsonValueProviderFactory());
    }
}

यह मूल रूप से डिफ़ॉल्ट कार्यान्वयन की एक सटीक प्रतिलिपि है, System.Web.Mvcलेकिन एक विन्यास योग्य web.config एपसेटिंग मान के अतिरिक्त के साथ aspnet:MaxJsonLength

public class CustomJsonValueProviderFactory : ValueProviderFactory
{

    /// <summary>Returns a JSON value-provider object for the specified controller context.</summary>
    /// <returns>A JSON value-provider object for the specified controller context.</returns>
    /// <param name="controllerContext">The controller context.</param>
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
            throw new ArgumentNullException("controllerContext");

        object deserializedObject = CustomJsonValueProviderFactory.GetDeserializedObject(controllerContext);
        if (deserializedObject == null)
            return null;

        Dictionary<string, object> strs = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        CustomJsonValueProviderFactory.AddToBackingStore(new CustomJsonValueProviderFactory.EntryLimitedDictionary(strs), string.Empty, deserializedObject);

        return new DictionaryValueProvider<object>(strs, CultureInfo.CurrentCulture);
    }

    private static object GetDeserializedObject(ControllerContext controllerContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return null;

        string fullStreamString = (new StreamReader(controllerContext.HttpContext.Request.InputStream)).ReadToEnd();
        if (string.IsNullOrEmpty(fullStreamString))
            return null;

        var serializer = new JavaScriptSerializer()
        {
            MaxJsonLength = CustomJsonValueProviderFactory.GetMaxJsonLength()
        };
        return serializer.DeserializeObject(fullStreamString);
    }

    private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
    {
        IDictionary<string, object> strs = value as IDictionary<string, object>;
        if (strs != null)
        {
            foreach (KeyValuePair<string, object> keyValuePair in strs)
                CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);

            return;
        }

        IList lists = value as IList;
        if (lists == null)
        {
            backingStore.Add(prefix, value);
            return;
        }

        for (int i = 0; i < lists.Count; i++)
        {
            CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakeArrayKey(prefix, i), lists[i]);
        }
    }

    private class EntryLimitedDictionary
    {
        private static int _maximumDepth;

        private readonly IDictionary<string, object> _innerDictionary;

        private int _itemCount;

        static EntryLimitedDictionary()
        {
            _maximumDepth = CustomJsonValueProviderFactory.GetMaximumDepth();
        }

        public EntryLimitedDictionary(IDictionary<string, object> innerDictionary)
        {
            this._innerDictionary = innerDictionary;
        }

        public void Add(string key, object value)
        {
            int num = this._itemCount + 1;
            this._itemCount = num;
            if (num > _maximumDepth)
            {
                throw new InvalidOperationException("The length of the string exceeds the value set on the maxJsonLength property.");
            }
            this._innerDictionary.Add(key, value);
        }
    }

    private static string MakeArrayKey(string prefix, int index)
    {
        return string.Concat(prefix, "[", index.ToString(CultureInfo.InvariantCulture), "]");
    }

    private static string MakePropertyKey(string prefix, string propertyName)
    {
        if (string.IsNullOrEmpty(prefix))
        {
            return propertyName;
        }
        return string.Concat(prefix, ".", propertyName);
    }

    private static int GetMaximumDepth()
    {
        int num;
        NameValueCollection appSettings = ConfigurationManager.AppSettings;
        if (appSettings != null)
        {
            string[] values = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers");
            if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
            {
                return num;
            }
        }
        return 1000;
    }

    private static int GetMaxJsonLength()
    {
        int num;
        NameValueCollection appSettings = ConfigurationManager.AppSettings;
        if (appSettings != null)
        {
            string[] values = appSettings.GetValues("aspnet:MaxJsonLength");
            if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
            {
                return num;
            }
        }
        return 1000;
    }
}

आपको बहुत - बहुत धन्यवाद !
लारिजगेट

1

उपरोक्त में से किसी ने भी मेरे लिए तब तक काम नहीं किया जब तक मैंने एक्शन नहीं बदल दिया [HttpPost]। और अजाक्स प्रकार बनाया POST

    [HttpPost]
    public JsonResult GetSelectedSignalData(string signal1,...)
    {
         JsonResult result = new JsonResult();
         var signalData = GetTheData();
         try
         {
              var serializer = new System.Web.Script.Serialization.JavaScriptSerializer { MaxJsonLength = Int32.MaxValue, RecursionLimit = 100 };

            result.Data = serializer.Serialize(signalData);
            return Json(result, JsonRequestBehavior.AllowGet);
            ..
            ..
            ...

    }

और अजाक्स कॉल के रूप में

$.ajax({
    type: "POST",
    url: some_url,
    data: JSON.stringify({  signal1: signal1,.. }),
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        if (data !== null) {
            setValue();
        }

    },
    failure: function (data) {
        $('#errMessage').text("Error...");
    },
    error: function (data) {
        $('#errMessage').text("Error...");
    }
});

1
    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonResult()
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior,
            MaxJsonLength = Int32.MaxValue
        };
    }

MVC 4 में मेरे लिए फिक्स था।


0

आपके कोड JsonResult ऑब्जेक्ट को वापस करने से पहले आपको मैन्युअल रूप से कॉन्फ़िगरेशन अनुभाग से पढ़ना होगा। बस एक लाइन में web.config से पढ़ें:

        var jsonResult = Json(resultsForAjaxUI);
        jsonResult.MaxJsonLength = (ConfigurationManager.GetSection("system.web.extensions/scripting/webServices/jsonSerialization") as System.Web.Configuration.ScriptingJsonSerializationSection).MaxJsonLength;
        return jsonResult;

सुनिश्चित करें कि आपने web.config में कॉन्फ़िगरेशन तत्व को परिभाषित किया है


0

यह मेरे लिए काम किया

        JsonSerializerSettings json = new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
        };
        var result = JsonConvert.SerializeObject(list, Formatting.Indented, json);
        return new JsonResult { Data = result, MaxJsonLength = int.MaxValue };

0

एक अन्य मामला है - डेटा क्लाइंट से सर्वर पर भेजा जाता है। जब आप नियंत्रक विधि का उपयोग कर रहे हैं और मॉडल बहुत बड़ा है:

    [HttpPost]
    public ActionResult AddOrUpdateConsumerFile(FileMetaDataModelView inputModel)
    {
        if (inputModel == null) return null;
     ....
    }

सिस्टम इस तरह के अपवाद को छोड़ देता है "JSON JavaScriptSerializer का उपयोग करके क्रमांकन या डीरिएलाइज़ेशन के दौरान त्रुटि। स्ट्रिंग की लंबाई अधिकतम मान पर अधिकतम मूल्य से अधिक हो जाती है। पैरामीटर नाम: पैरामीटर नाम: इनपुट"

केवल बदलते Web.config सेटिंग्स इस मामले में मदद करने के लिए पर्याप्त नहीं हैं। आप अतिरिक्त डेटा मॉडल आकार या अनुरोध से मैन्युअल रूप से डिस्अरीलाइज़ मॉडल का समर्थन करने के लिए mvc json क्रमांक को ओवरराइड कर सकते हैं। आपकी नियंत्रक विधि बन जाती है:

   [HttpPost]
    public ActionResult AddOrUpdateConsumerFile()
    {
        FileMetaDataModelView inputModel = RequestManager.GetModelFromJsonRequest<FileMetaDataModelView>(HttpContext.Request);
        if (inputModel == null) return null;
        ......
    }

   public static T GetModelFromJsonRequest<T>(HttpRequestBase request)
    {
        string result = "";
        using (Stream req = request.InputStream)
        {
            req.Seek(0, System.IO.SeekOrigin.Begin);
            result = new StreamReader(req).ReadToEnd();
        }
        return JsonConvert.DeserializeObject<T>(result);
    }

0

आप इस कोड को cshtml में रख सकते हैं यदि आप नियंत्रक से दृश्य वापस कर रहे हैं और आप cshtml में json में एन्कोडिंग करते समय व्यू बैग डेटा की लंबाई बढ़ाना चाहते हैं

@{
    var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
    jss.MaxJsonLength = Int32.MaxValue;
    var userInfoJson = jss.Serialize(ViewBag.ActionObj);
}

var dataJsonOnActionGrid1 = @Html.Raw(userInfoJson);

अभी, dataJsonOnActionGrid1 js पृष्ठ पर accesible होगा और आपको उचित परिणाम मिलेगा।

धन्यवाद

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.