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