如何解决 .NET Post 请求参数json串太长,请求失败~

背景

最近遇到一个Json串反序列化失败,提示“使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength 属性设置的值”。

 配置文件中Web.Config设置“<jsonSerialization maxJsonLength=2147483647”很遗憾设置了依然无效。

提供的接口接收Json字符串直接序列化实体。但json字符串中会有图片base64(可能多张图片),Json字符串如下:

//参数picture是base64格式
{
    "PictureInfo": [
        {
            "creationDate": "2023-12-17 10:37:04",
            "extendName": "jpg",
            "id": "xxxxxxx",
            "picture": "/9j/4*****3Vb/apNy71XYi/w/N/D/wKiigo/9k=",
        },
        {
            "creationDate": "2023-12-17 10:37:04",
            "extendName": "jpg",
            "id": "xxx",
            "picture": "/9j/*****A01JGRQ+3apZsbn+bePWiiiJJ//9k=",
        }
    ],
    "orderNumber": "xxxxx"
}

实体类

 public class OrderInfo
 {
     public List<PictureInfo> PictureInfo { get; set; }
     public string  orderNumber  { get; set; }
 }
 public class PictureInfo { 
     public string id { get;  set; }
     public DateTime creationDate { get;  set; }
     public string extendName { get;  set; }
     /// <summary>
     /// base64格式
     /// </summary>
     public string picture { get;  set; }
 }

  public class ResultJson
  {
      public int code { get; set; }
      public string msg { get; set; }
  }

Post方法

       对于ClientPost一个Json回Server,网上说post请求没有限制参数大小,但在如下方法中就直接不进入该方法,给用户直接返回错误信息:“Internal Server Error”。

     .NET 会根据接收到的Json字符串自动序列化成实体OrderInfo,运用的是.Net自带的序列化方法,会有一些缺陷导致失败。

 [System.Web.Http.HttpPost]
 public JsonResult SavePicture(OrderInfo  orderInfo)
 { try
 {

     ResultJson result = new ResultJson();
     foreach (PictureInfo item in OrderInfo.PictureInfo)
     {

         //用运单号+时间流水为图片命名,存储图片到指定路径
         if (!string.IsNullOrWhiteSpace(item.picture))
         {
             string filePath = "/Picture/";
             string fileName = orderInfo.orderNumber + "-" + item.id + "-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpeg";

             byte[] imageByte = Convert.FromBase64String(item.picture);

             using (MemoryStream memoryStream = new MemoryStream(imageByte))
             {
                 Bitmap bmp = new Bitmap(memoryStream);
                 if (!Directory.Exists(Server.MapPath(filePath)))
                 {
                     Directory.CreateDirectory(Server.MapPath(filePath));
                 }
                 //新建第二个bitmap类型的bmp2变量。
                 Bitmap bmp2 = new Bitmap(bmp, bmp.Width, bmp.Height);
                 Graphics draw = Graphics.FromImage(bmp2);
                 draw.DrawImage(bmp, 0, 0);
                 draw.Dispose();
                 bmp2.Save(Server.MapPath(filePath + fileName), System.Drawing.Imaging.ImageFormat.Jpeg);

                 memoryStream.Close();
             }

             result.code = 1;
             result.msg = "图片处理ok";
         }
         else
         {
             result.code = -1;
             result.msg = "无图片内容!";
         }
     }

 }
 catch (Exception ex)
 {
     result.code = -1;
     result.msg = $"图片处理异常:{ex.Message}";
 }
 }

用户调用接口收到返回信息“Internal Server Error

org.apache.http.client.HttpResponseException: Internal Server Error
at org.apache.http.impl.client.AbstractResponseHandler.handleResponse(Abstr
at com.kyexpress.open.commons.feign.client.HttpClientService.execute(HttpCl
at com.kyexpress.open.commons.feign.client.HttpClientService.postJson(Httpc
at com.kyexpress.ka.waybill.router.provider.handler.receipt.StandardReceipt
at com.kyexpress.ka.waybill.router.provider.handler,receit.bstractReceipt
at com.kyexpress.ka.waybill.router.provider.handler.receipt.StandardReceipt
at sun.reflect.GeneratedlethodAccessor2153.invoke(Unknown Source)
at sun.reflect.DelegatingMlethodAccessorImpl.invoke (DelegatingllethodAccessor
at java.lang.reflect.Method.invoke(Method.java:498)

解决方案

  1.  建立Json.Net的ValueProviderFactory,这个类主要就是用于Json字符串的反序列化。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace FileProject.Common.Helper
{
    using System.Collections;
    using System.Dynamic;
    using System.Globalization;
    using System.IO;
    using System.Web.Mvc;
    using System.Web.Script.Serialization;

    public class JsonNetValueProviderFactory : ValueProviderFactory
    {
        private void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value)
        {
            IDictionary<string, object> d = value as IDictionary<string, object>;
            if (d != null)
            {
                foreach (KeyValuePair<string, object> entry in d)
                {
                    AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value);
                }
                return;
            }

            IList l = value as IList;
            if (l != null)
            {
                for (int i = 0; i < l.Count; i++)
                {
                    AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]);
                }
                return;
            }

            // primitive
            backingStore[prefix] = value;
        }

        private object GetDeserializedObject(ControllerContext controllerContext)
        {
            if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase))
            {
                // not JSON request
                return null;
            }

            StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            string bodyText = reader.ReadToEnd();
            if (String.IsNullOrEmpty(bodyText))
            {
                // no JSON data
                return null;
            }
            //接下来的代码是关键,判断content type,如果是json.net,那么就使用Json.Net的反序列化方法,如果不是,那么就使用系统默认的反序列化方法
            if (controllerContext.HttpContext.Request.ContentType.StartsWith("application/json.net", StringComparison.InvariantCultureIgnoreCase))
            {
                //var jsonData = JsonConvert.DeserializeObject<ExpandoObject>(bodyText);

                JavaScriptSerializer serializerReq = new JavaScriptSerializer();
                serializerReq.MaxJsonLength = int.MaxValue;
                var jsonData = serializerReq.Deserialize<ExpandoObject>(bodyText);
                return jsonData;
            }
            else
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                serializer.MaxJsonLength = int.MaxValue;
                object jsonData = serializer.DeserializeObject(bodyText);
                return jsonData;
            }
        }

        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            object jsonData = GetDeserializedObject(controllerContext);
            if (jsonData == null)
            {
                return null;
            }

            Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            AddToBackingStore(backingStore, String.Empty, jsonData);
            return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
        }

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

        private string MakePropertyKey(string prefix, string propertyName)
        {
            return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName;
        }
    }
}

2、在初始化MVC时替换掉默认的JsonValueProviderFactory。 
在Global.asax的Application_Start时,写入以下代码:

namespace FileProject
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
           
          // 添加如下代码  
 
 ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
            ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());
        }
    }
}

以上Post请求问题就完整解决了~~~~

补充:针对Get请求返回值处理

可以写如下辅助类,直接调用即可~


 public static class JsonHelper
 {
     public static JsonResult MaxJson(object data, JsonRequestBehavior behavior)
     {
         return MaxJson(data, null, null, behavior);
     }

     private static JsonResult MaxJson(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
     {
         JsonResult jsonResult = new JsonResult();
         jsonResult.Data = data;
         jsonResult.ContentType = contentType;
         jsonResult.ContentEncoding = contentEncoding;
         jsonResult.JsonRequestBehavior = behavior;
         jsonResult.MaxJsonLength = Int32.MaxValue; //设置为int的最大值
         return jsonResult;
     }
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Best_to_Own

你的鼓励,是我继续创作的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值