MVC中ajax传递null或空数组参数的问题


先来看一个代码,后端参数是两个string类型的数组

public void ArrayTest(string[] array1, string[] array2)

前端Ajax调用,分别传递null和空数组

$.ajax("/Home/ArrayTest", {
    type: "post",
    data: JSON.stringify({array1:null, array2:[]}),
    contentType: "application/json; charset=utf-8"
});
contentType如果用默认的application/x-www-form-urlencoded; charset=UTF-8那么array2参数根本就不会被提交到后台,jQuery官方也不认为这是个bug,因为该类型以键值对形式提交数据,一个空数组似乎没法表示。
后端接收这2个参数竟然都是null,这不是我想要的。后端参数换成List<string>呢,情况更糟array1是一个初始化了的空集合,array2却是null。
原因就不分析了,反正我觉得这是微软的bug,坑还得自己填。

首先添加json的ValueProviderFactory替换原来的JsonValueProviderFactory
public sealed class JsonNetValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        // first make sure we have a valid context
        if (controllerContext == null)
            throw new ArgumentNullException("controllerContext");

        // now make sure we are dealing with a json request
        if (
            !controllerContext.HttpContext.Request.ContentType.StartsWith("application/json",
                                                                            StringComparison.OrdinalIgnoreCase))
            return null;

        // get a generic stream reader (get reader for the http stream)
        StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
        string bodyText = streamReader.ReadToEnd();
        if (String.IsNullOrEmpty(bodyText))
        {
            // no JSON data
            return null;
        }

        var JSONObject = JsonConvert.DeserializeObject(bodyText) as JObject;

        // create a backing store to hold all properties for this deserialization
        Dictionary<string, object> backingStore =
            new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        foreach (var item in JSONObject)
        {
            backingStore.Add(item.Key, item.Value);
        }
        // return the object in a dictionary value provider so the MVC understands it
        return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
    }
}

这里用Json.Net进行反序列化,比原来的JavaScriptSerializer效率高,而且妈妈再也不用担心Json请求太大的问题了。

然后添加json的ModelBinder

public class JsonModelBinder : IModelBinder
{
    private IModelBinder _defaultBinder = new DefaultModelBinder();
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json",
                                                                            StringComparison.OrdinalIgnoreCase))
            return _defaultBinder.BindModel(controllerContext, bindingContext);
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == null)
            return null;
        else
            return (((JToken)valueProviderResult.RawValue).ToObject(bindingContext.ModelType));
    }
}

最后修改Global.asax

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();

ok大功告成,null是null,空是空。

这不是个完美的解决方案,填坑嘛,先填上再说,最终还是希望微软能修复这些个问题。

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM