.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)
.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)
.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一)
上一篇主要是以Form键值对提交的数据,转为Json方式处理,有时我们直接以Body字串提交,我们要解决以下两种方式提交的取值问题:
JObject
$('#btn_add').click(function (e) { var a = $('#tb_departments').bootstrapTable('getSelections'); var post = "{'str1':'foovalue', 'str2':'barvalue'}";// JSON.stringify(a); $.ajax({ type: "POST", url: "/Home/bout", contentType: "application/json",//必须有 dataType: "json", //表示返回值类型,不必须 data: post,//相当于 //data: "{'str1':'foovalue', 'str2':'barvalue'}", success: function (data) { //获取数据ok alert(JSON.toString(data)); } }); });
JArray
$('#btn_delete').click(function (e) { var a = $('#tb_departments').bootstrapTable('getSelections'); var post = JSON.stringify(a); $.ajax({ type: "POST", url: "/Home/About", contentType: "application/json",//必须有 dataType: "json", //表示返回值类型,不必须 data: post,//相当于 //data: "{[{'str1':'foovalue', 'str2':'barvalue'},{'str1':'foovalue', 'str2':'barvalue'}]}", success: function (data) { //获取数据ok alert(data.id + "--" +data.userName); } }); });
在.net core 中没有用于取Body值的ValueProvider,编一个,这是基于工厂模式的ValueProvider,先上代码 实现IValueProviderFactory接口:
public class JObjectValueProviderFactory : IValueProviderFactory { public Task CreateValueProviderAsync(ValueProviderFactoryContext controllerContext) { if (controllerContext == null) throw new ArgumentNullException("controllerContext"); if (controllerContext.ActionContext.HttpContext.Request.ContentType == null) { return Task.CompletedTask; } ; if (!controllerContext.ActionContext.HttpContext.Request.ContentType. StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) { return Task.CompletedTask;//不是"application/json"类型不处理交给原有的 } var bodyText = string.Empty; using (var reader = new StreamReader(controllerContext.ActionContext.HttpContext.Request.Body)) { bodyText = reader.ReadToEnd().Trim();//取得Body } if (string.IsNullOrEmpty(bodyText)) { return Task.CompletedTask; }//为空不处理 else {//添加JObject一ValueProviders以便处理值 controllerContext.ValueProviders.Add( new JObjectValueProvider(bodyText.EndsWith("]}") ?//是不是组 JArray.Parse(bodyText) as JContainer ://是Jarray JObject.Parse(bodyText) as JContainer));// JObject } return Task.CompletedTask; } }
对应的IValueProvider:
internal class JObjectValueProvider : IValueProvider { private JContainer _jcontainer; public JObjectValueProvider(JContainer jcontainer) { _jcontainer = jcontainer; } public bool ContainsPrefix(string prefix) { // return _jcontainer.SelectToken(prefix) != null; return true; } public ValueProviderResult GetValue(string key) { var jtoken = _jcontainer.SelectToken(""); if (jtoken == null) return ValueProviderResult.None; return new ValueProviderResult( jtoken.ToString(), CultureInfo.CurrentCulture); } }
在Startup中注册:
services.AddMvc(options => { options.ValueProviderFactories.Add(new JObjectValueProviderFactory());//取值 options.ModelBinderProviders.Insert(0, new JObjectModelBinderProvider());//加入Jobject绑定 });
由于新增//Jarray类型对.net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) JObjectModelBinderProvider做了改动
public class JObjectModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); if (context.Metadata.ModelType == (typeof(JObject)))//同时支Body持数据JObject,和Form键值对 { return new JObjectModelBinder(context.Metadata.ModelType); } if (context.Metadata.ModelType == (typeof(JArray)))//Jarray支持 { return new JObjectModelBinder(context.Metadata.ModelType); } return null; } }
同样也必须对JObjectModelBinder相应修改以增加对JObject,JArray支持,当然也可以另外写
public class JObjectModelBinder : IModelBinder { public JObjectModelBinder(Type type) { if (type == null) { throw new ArgumentNullException("type"); } } public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) throw new ArgumentNullException("bindingContext"); ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);//调用取值 ValueProvider try { if (bindingContext.ModelType == typeof(JObject)) { JObject obj = new JObject(); if (bindingContext.ActionContext.HttpContext.Request.ContentType == "application/json")//json { if (result.ToString().StartsWith("["))//是否是组? { obj =(JObject) JArray.Parse(result.ToString()).First;//取首值。 bindingContext.Result = (ModelBindingResult.Success(obj)); return Task.CompletedTask; } else { obj = JObject.Parse(result.ToString());//不是组直接取值 } } else //form { foreach (var item in bindingContext.ActionContext.HttpContext.Request.Form) { obj.Add(new JProperty(item.Key.ToString(), item.Value.ToString())); } } if ((obj.Count == 0)) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(result.ToString())); return Task.CompletedTask; } bindingContext.Result = (ModelBindingResult.Success(obj)); return Task.CompletedTask; } if (bindingContext.ModelType == typeof(JArray )) { JArray obj = new JArray(); if (bindingContext.ActionContext.HttpContext.Request.ContentType. StartsWith("application/json", StringComparison.OrdinalIgnoreCase))//json { if (result.ToString().StartsWith("["))//是否是组? { JArray array = new JArray(); array = JArray.Parse(result.ToString());//取首值。 bindingContext.Result = (ModelBindingResult.Success(array)); return Task.CompletedTask; } } if ((obj.Count == 0)) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(result.ToString())); return Task.CompletedTask; } bindingContext.Result = (ModelBindingResult.Success(obj)); return Task.CompletedTask; } return Task.CompletedTask; } catch (Exception exception) { if (!(exception is FormatException) && (exception.InnerException != null)) { exception = ExceptionDispatchInfo.Capture(exception.InnerException).SourceException; } bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, exception, bindingContext.ModelMetadata); return Task.CompletedTask; } } }
控制器写法Form键值对、JObject、Jarry方式一样 public IActionResult bout(JArray data)
在客户客户端有区别,JObject、Jarry数据必须指定: contentType: "application/json",//必须有
当以json内容为数组时提交,控制器接收类型为JObject,只取第一个JObject。
转载请务必注明出处
作者QQ153476025