.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 = $(&#39;#tb_departments&#39;).bootstrapTable(&#39;getSelections&#39;);<br/>
    var post = &#34;{&#39;str1&#39;:&#39;foovalue&#39;, &#39;str2&#39;:&#39;barvalue&#39;}&#34;;// JSON.stringify(a);<br/>
    $.ajax({<br/>
        type: &#34;POST&#34;,<br/>
        url: &#34;/Home/bout&#34;,<br/>
        contentType: &#34;application/json&#34;,//必须有<br/>
        dataType: &#34;json&#34;, //表示返回值类型,不必须<br/>
        data: post,//相当于 //data: &#34;{&#39;str1&#39;:&#39;foovalue&#39;, &#39;str2&#39;:&#39;barvalue&#39;}&#34;,<br/>
        success: function (data) {<br/>
            //获取数据ok<br/>
       alert(JSON.toString(data));<br/>
        }<br/>
    });<br/>
});

JArray

 $(‘#btn_delete’).click(function (e) {

    var a = $(&#39;#tb_departments&#39;).bootstrapTable(&#39;getSelections&#39;);<br/>
    var post = JSON.stringify(a);<br/>
    $.ajax({<br/>
        type: &#34;POST&#34;,<br/>
        url: &#34;/Home/About&#34;,<br/>
      contentType: &#34;application/json&#34;,//必须有<br/>
        dataType: &#34;json&#34;, //表示返回值类型,不必须<br/>
        data: post,//相当于 //data: &#34;{[{&#39;str1&#39;:&#39;foovalue&#39;, &#39;str2&#39;:&#39;barvalue&#39;},{&#39;str1&#39;:&#39;foovalue&#39;, &#39;str2&#39;:&#39;barvalue&#39;}]}&#34;,<br/>
        success: function (data) {<br/>
            //获取数据ok<br/>
          alert(data.id + &#34;--&#34; +data.userName);<br/>
        }<br/>
    });<br/>
});

在.net core 中没有用于取Body值的ValueProvider,编一个,这是基于工厂模式的ValueProvider,先上代码 实现IValueProviderFactory接口:

 public class JObjectValueProviderFactory : IValueProviderFactory

{<br/>
    public Task CreateValueProviderAsync(ValueProviderFactoryContext controllerContext)<br/>
    {<br/>
        if (controllerContext == null) throw new ArgumentNullException(&#34;controllerContext&#34;);<br/>
        if (controllerContext.ActionContext.HttpContext.Request.ContentType == null) { return Task.CompletedTask; } ;

if (!controllerContext.ActionContext.HttpContext.Request.ContentType.

            StartsWith(&#34;application/json&#34;, StringComparison.OrdinalIgnoreCase))<br/>
        {<br/>
            return Task.CompletedTask;//不是&#34;application/json&#34;类型不处理交给原有的<br/>
        }<br/>
        var bodyText = string.Empty;<br/>
        using (var reader = new StreamReader(controllerContext.ActionContext.HttpContext.Request.Body))<br/>
        {<br/>
            bodyText = reader.ReadToEnd().Trim();//取得Body<br/>
        }<br/>
        if (string.IsNullOrEmpty(bodyText)) { return Task.CompletedTask; }//为空不处理<br/>
        else<br/>
        {//添加JObject一ValueProviders以便处理值<br/>
            controllerContext.ValueProviders.Add(<br/>
            new JObjectValueProvider(bodyText.EndsWith(&#34;]}&#34;) ?//是不是组<br/>
        JArray.Parse(bodyText) as JContainer ://是Jarray<br/>
        JObject.Parse(bodyText) as JContainer));// JObject<br/>
        }<br/>
        return Task.CompletedTask;<br/>
    }<br/>
}

对应的IValueProvider:

 internal class JObjectValueProvider : IValueProvider

{<br/>
    private JContainer _jcontainer;<br/>
    public JObjectValueProvider(JContainer jcontainer)<br/>
    {<br/>
        _jcontainer = jcontainer;<br/>
    }<br/>
    public bool ContainsPrefix(string prefix)<br/>
    {<br/>
        //  return _jcontainer.SelectToken(prefix) != null;<br/>
        return true;<br/>
    }<br/>
    public ValueProviderResult GetValue(string key)<br/>
    {<br/>
        var jtoken = _jcontainer.SelectToken(&#34;&#34;);<br/>
        if (jtoken == null) return ValueProviderResult.None;<br/>
        return new ValueProviderResult( jtoken.ToString(), CultureInfo.CurrentCulture);<br/>
    }<br/>
}

在Startup中注册:

 services.AddMvc(options =&gt;

           {<br/>
               options.ValueProviderFactories.Add(new JObjectValueProviderFactory());//取值<br/>
               options.ModelBinderProviders.Insert(0, new JObjectModelBinderProvider());//加入Jobject绑定<br/>
           });

 public class JObjectModelBinderProvider : IModelBinderProvider

{<br/>
    public IModelBinder GetBinder(ModelBinderProviderContext context)<br/>
    {<br/>
        if (context == null) throw new ArgumentNullException(nameof(context));<br/>
        if (context.Metadata.ModelType == (typeof(JObject)))//同时支Body持数据JObject,和Form键值对<br/>
        {<br/>
            return new JObjectModelBinder(context.Metadata.ModelType);<br/>
        }<br/>
        if (context.Metadata.ModelType == (typeof(JArray)))//Jarray支持<br/>
        {<br/>
            return new JObjectModelBinder(context.Metadata.ModelType);<br/>
        }<br/>
        return null;<br/>
    }<br/>
}

同样也必须对JObjectModelBinder相应修改以增加对JObject,JArray支持,当然也可以另外写

 public class JObjectModelBinder : IModelBinder

{<br/>
    public JObjectModelBinder(Type type)<br/>
    {<br/>
        if (type == null)<br/>
        {<br/>
            throw new ArgumentNullException(&#34;type&#34;);<br/>
        }<br/>
    }<br/>
    public Task BindModelAsync(ModelBindingContext bindingContext)<br/>
    {<br/>
        if (bindingContext == null) throw new ArgumentNullException(&#34;bindingContext&#34;);<br/>
        ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);//调用取值 ValueProvider<br/>
        try<br/>
        {<br/>
            if (bindingContext.ModelType == typeof(JObject))<br/>
            {<br/>
                JObject obj = new JObject();<br/>
                if (bindingContext.ActionContext.HttpContext.Request.ContentType == &#34;application/json&#34;)//json<br/>
                {<br/>
                    if (result.ToString().StartsWith(&#34;[&#34;))//是否是组?<br/>
                    {<br/>
                        obj =(JObject) JArray.Parse(result.ToString()).First;//取首值。<br/>
                        bindingContext.Result = (ModelBindingResult.Success(obj));<br/>
                        return Task.CompletedTask;<br/>
                    }<br/>
                    else<br/>
                    {<br/>
                        obj = JObject.Parse(result.ToString());//不是组直接取值<br/>
                    }<br/>
                }<br/>
                else  //form<br/>
                {<br/>
                    foreach (var item in bindingContext.ActionContext.HttpContext.Request.Form)<br/>
                    {<br/>
                        obj.Add(new JProperty(item.Key.ToString(), item.Value.ToString()));<br/>
                    }<br/>
                }<br/>
                if ((obj.Count == 0))<br/>
                {<br/>
                    bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(result.ToString()));<br/>
                    return Task.CompletedTask;<br/>
                }<br/>
                bindingContext.Result = (ModelBindingResult.Success(obj));<br/>
                return Task.CompletedTask;<br/>
            }<br/>
            if (bindingContext.ModelType == typeof(JArray ))<br/>
            {<br/>
                JArray obj = new JArray();<br/>
                if   (bindingContext.ActionContext.HttpContext.Request.ContentType.<br/>
            StartsWith(&#34;application/json&#34;, StringComparison.OrdinalIgnoreCase))//json<br/>
                    {<br/>
                    if (result.ToString().StartsWith(&#34;[&#34;))//是否是组?<br/>
                    {<br/>
                        JArray array = new JArray();<br/>
                        array = JArray.Parse(result.ToString());//取首值。<br/>
                        bindingContext.Result = (ModelBindingResult.Success(array));<br/>
                        return Task.CompletedTask;<br/>
                    }<br/>
                }<br/>
                if ((obj.Count == 0))<br/>
                {<br/>
                    bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(result.ToString()));<br/>
                    return Task.CompletedTask;<br/>
                }<br/>
                bindingContext.Result = (ModelBindingResult.Success(obj));<br/>
                return Task.CompletedTask;<br/>
            }<br/>
            return Task.CompletedTask;<br/>
        }<br/>
        catch (Exception exception)<br/>
        {<br/>
            if (!(exception is FormatException) &amp;&amp; (exception.InnerException != null))<br/>
            {<br/>
                exception = ExceptionDispatchInfo.Capture(exception.InnerException).SourceException;<br/>
            }<br/>
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, exception, bindingContext.ModelMetadata);<br/>
            return Task.CompletedTask;<br/>
        }<br/>
    }<br/>
}

控制器写法Form键值对、JObject、Jarry方式一样   public IActionResult bout(JArray data)

在客户客户端有区别,JObject、Jarry数据必须指定: contentType: “application/json”,//必须有

当以json内容为数组时提交,控制器接收类型为JObject,只取第一个JObject。