1

WebApi 中请求的 JSON 数据字段作为 POST 参数传入

 3个月前 阅读数 6
以下为 快照 页面,建议前往来源网站查看,会有更好的阅读体验。
原文链接: http://www.cnblogs.com/oangs/p/14273813.html

使用 POST 方式请求 JSON 数据到服务器 WebAPI 接口时需要将 JSON 格式封装成数据模型接收参数。即使参数较少,每个接口仍然需要单独创建模型接收。下面方法实现了将 JSON 参数中的字段作为接口参数接收。实现的并不完美,现在只支持 JSON 格式顶级结构字段作为参数使用,且未处理复杂格式参数。

每个接收参数都会进行 JSON 反序列化操作,故参数多的情况下创建模型接收显然更节省资源。

以下方法只进行过简单测试,如有问题,还请大佬们自行解决,解决后希望能在此留言与诸位网友分享。

POST 提交的 JSON 数据演示:

{'Code':10000,Msg:'中文测试'}

WebApi 中获取方式:

        [HttpPost]
        public string Post([FromJson]int Code,[FromJson]string Msg)
        {
            return "OK";
        }

YRbqayb.png!mobile

FromJson 类:

    public class FromJsonAttribute : Attribute, IBindingSourceMetadata
    {
        public BindingSource BindingSource
        {
            get
            {
                return BindingSource.Custom;
            }
        }
    }

ModelBuilder 类:

    public class JsonParameterModelBinder : IModelBinder
    {
        private readonly BodyModelBinder bodyModelBinder;

        public JsonParameterModelBinder(IList<IInputFormatter> formatters, IHttpRequestStreamReaderFactory readerFactory)
        {
            bodyModelBinder = new BodyModelBinder(formatters, readerFactory);
        }

        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));

            var postStr = string.Empty;
            using (StreamReader sr = new StreamReader(bindingContext.HttpContext.Request.Body))
                postStr = sr.ReadToEndAsync().Result;

            var jobj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(postStr);
            var val = jobj[bindingContext.FieldName]?.ToObject<object>();

            if (val != null)
                bindingContext.Result = ModelBindingResult.Success(Convert.ChangeType(val, bindingContext.ModelType, null));

            //将流重新写回 Request.Body 不然第二个参数再操作时会报错
            bindingContext.HttpContext.Request.Body = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(postStr));

            return Task.CompletedTask;
        }
    }

Provider 类:

    public class JsonParameterModelBinderProvider : IModelBinderProvider
    {
        private readonly IList<IInputFormatter> _formatters;

        public JsonParameterModelBinderProvider(IList<IInputFormatter> Formatters)
        {
            _formatters = Formatters;
        }

        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
                throw new ArgumentNullException(nameof(context));

            if (context.BindingInfo.BindingSource != null && context.BindingInfo.BindingSource.CanAcceptDataFrom(BindingSource.Custom))
                return new JsonParameterModelBinder(_formatters, context.Services.GetRequiredService<IHttpRequestStreamReaderFactory>());

            return null;
        }
    }

修改 Startup.cs 的 void ConfigureServices(IServiceCollection services) 方法,增加:

            services.AddMvc(options =>
            {
                options.ModelBinderProviders.Insert(0, new JsonParameterModelBinderProvider(options.InputFormatters));
            });

插入到 0 位置,优先处理,尽量不要使用 Add 方法插入到末位,否则可能不会被处理。

以上代码在 .Net 5 下测试通过。其他框架版本未测试。


猜你喜欢

  • 2

    linux C语言多线程编程,如何传入参数,如何获得返回值 发表于 2018-08-07 2...

  • 0
    • www.ascotbe.com 4天前
    • 快照

    c++传入参数的问题

    c++传入参数的问题 | ascotbeint tex (int a,int b)值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象或是大的结构体对象,将耗费一定的时间和空间。 int tex(int *a,int *b)指针传递:同样...

  • 84
    • 51CTO blog.51cto.com 3年前
    • 快照

    django的form常用字段和参数-Old-K

    http://www.cnblogs.com/wupeiqi/articles/6144178.htmlDjango的内置字段如下:Fieldrequired=True#请求不能为空widget=None#HTML插件label=None#用于生成lable标签或显示内容initial=None#初始值help_text=''#帮助信息(在标签旁边显示)error_messages=None#(错...

  • 32
    • solidot 奇客资讯 www.solidot.org 1年前
    • 快照

    非洲猪瘟传入香港

  • 2

    为何condition_variable不设计成传入BaseLockable? - 知乎登录一下,更多精彩内容等你发现贡献精彩回答,参与评论互动查看全部 3 个回答

  • 1

    现在有个需求就是 有张表,表的字段 有时候会增加 或者减少, 用大数据的话 采用什么方式合理。我想过用HBASE,但是考虑到后续需要对这些数据进行数据分析,HBASE在数据分析这块儿 又没有什么优势。所以有些顾虑,不知道朋友有什么好的方法没 。有知道的朋友还

  • 31
    • 博客园 www.cnblogs.com 2年前
    • 快照

    springmvc 请求参数解析细节

    springmvc 的请求流程,相信大家已经很熟悉了,不熟悉的同学可以参考下资料! 有了整体流程的概念,是否对其中的实现细节就很清楚呢?我觉得不一定,比如:单是参数解析这块,就是个大学问呢? 首先,我们从最靠近请求末...

  • 52

    通过Feign包装rpc的调用姿势,在使用的版本中发现一个奇怪的bug,大部分场景下请求正常,少数情况下请求返回400,记录下原因 场景复现 1. 环境相关版本 Spring版本如 <...

  • 34

    内网通过K8S搭建多个分支测试环境,可是如果外网需要访问而且域名都是一致的情况下,这个时候变得麻烦了。如何通过不同的请求参数访问不同的后端环境呢,答案是可以的,通过lua可以达到。入口:http://fengwan.blog.51cto.com/?envs=branches#branches环境http://fe...

  • 23
    • www.throwable.club 1年前
    • 快照

    SpringMVC请求参数接收总结(一)

    在日常使用 SpringMVC 进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结。 SpringMVC 中处理控制器参数的接口是 HandlerMethodArgumentResolver ,此接口有众多子类...

关于极客头条


聚合每日国内外有价值,有趣的链接。