MVC中用JObject作为前端向后端传递的Model参数类型:

MVC中用JObject作为前端向后端传递的Model参数类型:

方案一:

1. 在Global.asax文件中:

using Test.Manage.Common;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Test.Manage
{
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
        }
    }
}

2. CustomModelBinder.cs文件:

using DevMate.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;

namespace Test.Manage.Common
{
    public class CustomModelBinder : DefaultModelBinder
    {
        private readonly object _locker = new object();
        private const string cachekey = "JsonModel";
        private Dictionary<string, int> _indexCache = new Dictionary<string, int>();
        private int _index = 0;
        private JObject _data
        {
            get
            {
                return HttpContext.Current.Items[cachekey] as JObject;
            }
            set
            {
                HttpContext.Current.Items[cachekey] = value;
            }
        }

        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;
            if (request.Files.Count > 0)
                return base.BindModel(controllerContext, bindingContext);

            if (_data == null)
            {
                using (var sr = new StreamReader(request.InputStream))
                {
                    sr.BaseStream.Position = 0;
                    var json = sr.ReadToEnd();
                    _data = JsonConvert.DeserializeObject<JObject>(json);
                }
            }

            if (_data == null)
                return base.BindModel(controllerContext, bindingContext);

            string id = _data["RequestId"] == null ? null : _data["RequestId"].ToString();
            if (string.IsNullOrEmpty(id))
                return base.BindModel(controllerContext, bindingContext);

            string key = "param";
            lock (_locker)
            {
                if (_indexCache.Count > 100)
                    _indexCache.Clear();

                if (!_indexCache.ContainsKey(id))
                {
                    _indexCache.Add(id, 0);
                }

                _index = _indexCache[id];
                key = "param" + _index;
                _index++;
                _indexCache[id] = _index;
            }

            object obj = null;
            string jsonField = DataConvert.ToString(_data[key]);
            if (bindingContext.ModelType == typeof(JArray))
            {
                obj = DataConvert.ToJArray(jsonField);
            }
            else if (bindingContext.ModelType.IsClass || bindingContext.ModelType.IsArray || bindingContext.ModelType.IsGenericType)
            {
                obj = JsonConvert.DeserializeObject(jsonField, bindingContext.ModelType);
            }
            else
            {
                obj = _data[key].ToObject(bindingContext.ModelType);
            }

            return obj;
        }
    }
}

3. 前端RPC调用方法求封装: 

(function (global, $) {
    var jp = {};
    global.jp = jp;

    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    function guid() {
        return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
    }

    jp.createRpc = function (rpcUrl, fail, loading) {
        return function () {
            var ParamentersData = {
                RequestId: 'JP' + guid()
            };

            for (var i = 0; i < arguments.length; i++) {
                var key = "param" + i;
                ParamentersData[key] = arguments[i];
            };

            var options = {
                type: 'post',
                url: rpcUrl,
                dataType:'json',
                contentType: 'application/json',
                data: JSON.stringify(ParamentersData),
                beforeSend: function () {
                    if (!loading)
                        $JVue.loading = true;
                },
                complete: function (event,xhr,options) {
                    $JVue.loading = false;
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    console.log(XMLHttpRequest);
                    $JVue.loading = false;
                    if (!fail) {
                        $JVue.$message({
                            message: $JVue.$t('wsm.errorCode.'+XMLHttpRequest.responseJSON.Code),
                            type: 'error',
                            onClose: function() {
                                //登录超时
                                if (XMLHttpRequest.responseJSON.Code == 30014 && top.$JVue.loginPage)
                                    top.location.href = top.$JVue.loginPage;
                            },
                        });
                    }
                }
            };

            var promise = $.ajax(options);

            return promise;
        };
    }    
})
(window, jQuery);

4. 示例:

 前端调用:

        var param = {
            ItemId: this.itemForm.ID,
            Fields: this.fields,
        };
    
        var action = jp.createRpc('TestAction');
        action(param) //注意:这里无需使用如“{API参数名obj:param}” 作参数,方案二则需要
            .done(function (data) {
                ......
            });

后端方法:

        [HttpPost]
        public JsonResult TestAction(JObject obj)
        {
            ......
        }

----------------------------------------------------------

方案二:

1. 在Global.asax文件中:

using test.Web.Common;
using System.Web.Mvc;
using System.Web.Routing;
using System.Linq;
using System.Web.Http;

namespace test.Web
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

           

            //ValueProviderFactories.Factories默认包括以下ValueProviderFactory:    

            //System.Web.Mvc.ChildActionValueProviderFactory
            //System.Web.Mvc.FormValueProviderFactory
            //System.Web.Mvc.JsonValueProviderFactory
            //System.Web.Mvc.RouteDataValueProviderFactory
            //System.Web.Mvc.QueryStringValueProviderFactory
            //System.Web.Mvc.HttpFileCollectionValueProviderFactory

            ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
            ValueProviderFactories.Factories.Add(new CustomValueProvider());
            ModelBinderProviders.BinderProviders.Add(new CustomModelBinderProvider());
        }
    }
}

2. CustomModelBinderProvider.cs文件:

using Newtonsoft.Json.Linq;
using System;
using System.Web;
using System.Web.Mvc;

namespace test.Web.Common
{
    public class CustomModelBinderProvider : IModelBinderProvider
    {
        //public IModelBinder GetBinder(Type modelType)        

        //{
        //    if (modelType == typeof(string) || modelType == typeof(HttpPostedFileBase))
        //    {
        //        return null;
        //    }
        //    else if (modelType == typeof(JArray))
        //    {
        //        return new CustomModelBinder(typeof(JArray));
        //    }
        //    else if (modelType == typeof(JObject))
        //    {
        //        return new CustomModelBinder(typeof(JObject));
        //    }
        //    else if (modelType.IsClass || modelType.IsArray || modelType.IsGenericType)
        //    {
        //        return new CustomModelBinder(modelType);
        //    }

        //    return null;
        //}

        

        //改为以下:解决了ModelBinder绑定JArray/JObject与过去传递实体对象参数不可兼容的问题

        public IModelBinder GetBinder(Type modelType)
        {            

            //if (modelType == typeof(string) || modelType == typeof(HttpPostedFileBase))
            //{
            //    return null;
            //}
            //else
            //if (modelType.IsClass || modelType.IsArray || modelType.IsGenericType)
            //{
            //    return new CustomModelBinder(modelType);
            //}
            //else 
            if (modelType == typeof(JArray))
            {
                return new CustomModelBinder(typeof(JArray));
            }
            else if (modelType == typeof(JObject))
            {
                return new CustomModelBinder(typeof(JObject));
            }           

            return new DefaultModelBinder();
        }

    }
}

3. CustomModelBinder

using System;
using System.Web.Mvc;
using Newtonsoft.Json;

namespace test.Web.Common
{
    public class CustomModelBinder : IModelBinder
    {
        public Type ModelType { get; set; }

        public CustomModelBinder(Type modelType)
        {
            ModelType = modelType;
        }

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (value != null)
            {
                return JsonConvert.DeserializeObject(value.AttemptedValue, ModelType);
            }
            return null;
        }        
    }

}

4. CustomValueProviderFactory

using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Text;
using System.Web.Mvc;

namespace test.Web.Common
{
    public class CustomValueProviderFactory : 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;
                

            controllerContext.HttpContext.Request.InputStream.Seek(0, SeekOrigin.Begin);
            string json = null;
            using (var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream, Encoding.UTF8))
            {
                json = reader.ReadToEnd();
                reader.Close();
                //controllerContext.HttpContext.Request.InputStream.Seek(0,SeekOrigin.Begin);
            }

            
            if (string.IsNullOrEmpty(json) || !(json.StartsWith("{") || json.StartsWith("[")))
                return new CommonValueProvider(json);

            //var jsonProvider = new JsonValueProviderFactory().GetValueProvider(controllerContext);
            //if (jsonProvider != null)
            //    return jsonProvider;

            return new JObjectValueProvider(json.StartsWith("[") ?
                JArray.Parse(json) as JContainer :
                JObject.Parse(json) as JContainer);
        }

    }

5. CommonValueProvider 

using System.Globalization;
using System.Web.Mvc;

namespace test.Web.Common
{   

    public class CommonValueProvider : IValueProvider
    {
        private string _param;

        public CommonValueProvider(string param)
        {
            _param = param;
        }

        public bool ContainsPrefix(string prefix)
        {
            return !string.IsNullOrEmpty(_param);
        }

        public ValueProviderResult GetValue(string key)
        {
            return new ValueProviderResult(_param, _param, CultureInfo.CurrentCulture);
        }
    }
}

6. JObjectValueProvider

using Newtonsoft.Json.Linq;
using System.Globalization;
using System.Web.Mvc;

namespace test.Web.Common
{
    public class JObjectValueProvider : IValueProvider
    {
        private JContainer _jcontainer;

        public JObjectValueProvider(JContainer jcontainer)
        {
            _jcontainer = jcontainer;
        }

        public bool ContainsPrefix(string prefix)
        {
            var token = _jcontainer.SelectToken(prefix);
            return token != null;
        }

        public ValueProviderResult GetValue(string key)
        {
            var token = _jcontainer.SelectToken(key);
            if (token == null) return null;
            return new ValueProviderResult(token.ToString(), token.ToString(), CultureInfo.CurrentCulture);
        }
    }    

7. 前端RPC调用方法封装:

(function (global, $) {
    var jp = {};
    global.jp = jp;

    jp.createRpc = function (rpcUrl, fail, loading) {
        return function (param) {
            var options = {
                type: 'post',
                url: rpcUrl,
                dataType:'json',
                contentType: 'application/json',
                data: JSON.stringify(param),
                beforeSend: function () {
                    if (!loading)
                        $JVue.loading = true;
                },
                complete: function (event,xhr,options) {
                    $JVue.loading = false;
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    console.log(XMLHttpRequest);
                    $JVue.loading = false;
                    if (!fail) {
                        $JVue.$message({
                            message: !!XMLHttpRequest.responseJSON.Cause ? XMLHttpRequest.responseJSON.Cause : $JVue.$t('sos.errorCode.' + XMLHttpRequest.responseJSON.Code),
                            type: 'error',
                            onClose: function() {
                                //登录超时
                                if (XMLHttpRequest.responseJSON.Code == 30014 && top.$JVue.loginPage)
                                    top.location.href = top.$JVue.loginPage;
                            },
                        });
                    }
                }
            };

            var promise = $.ajax(options);

            return promise;
        };
    }

    jp.getQueryString = function(name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
        var reg_rewrite = new RegExp("(^|/)" + name + "/([^/]*)(/|$)", "i");
        var r = window.location.search.substring(1).match(reg);
        var q = window.location.pathname.substring(1).match(reg_rewrite);
        if(r != null){
            return decodeURI(r[2]);
        }else if(q != null){
            return decodeURI(q[2]);
        }else{
            return null;
        }
    }
})
(window, jQuery); 

8. 示例: 

 前端调用:

        var param = {
            ItemId: this.itemForm.ID,
            Fields: this.fields,
        };
    
        var action = jp.createRpc('TestAction');
        action({obj:param}) //注意:这里需使用如“{API参数名obj:param}” 作参数,方案一则不需要
            .done(function (data) {
                ......
            });

后端方法:

        [HttpPost]
        public JsonResult TestAction(JObject obj)
        {
            ......
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值