netcore webapi接口同时支持多种编码请求方式

功能:netcore webapi接口支持GET和POST请求,同时支持application/x-www-form-urlencoded和application/json两种请求方式。

背景:在以前.NET Framework写MVC5的时候,Action的参数前端传递的时候默认是可以自适应的,即:以queryString、表单或者json传递都能够被正确接收,而到了asp.net core中,action接收参数默认只有queryString,显式声明了FromForm或FromBody之后也只能被表单或json接受,即使是同时打上FromForm和FromBody,也只有FromForm生效,FromBody不会起作用。

一、基本介绍

 

简介:在http协议中规定了GET、HEAD、POST、PUT、DELETE、CONNECT 等请求方式,其中比较常用的就是POST和GET,其中POST用来向服务器提交数据,POST只规定了提交的数据必须放在请求的主体中,但是并没有规定传输数据的编码方式。简单介绍一下主流的两种编码方式,也是实际开发中使用最多的两种方式:

1.application/x-www-form-urlencoded

最常见的请求方式,特别是自己在测试后端接口时,经常在前端url中直接以键值对的形式写入参数的值。但是该方式默认采用URLENCODE编码会导致消息包大,form表单默认以该方式提交,请求一般是如下的方式:

Content-Type: application/x-www-form-urlencoded

title=test&text=test

2.application/json

application/json 这个 Content-Type 也是非常常见的,越来越多的人使用该方式传递,该方式传递的是序列化后的字符串,因为采用的是JSON格式的数据,因此支持更多复杂的类型。请求体一般如下:

{

    "id":123,

    "name":"admin",

}

二、服务端接口请求和接收方法分析

方式1:

请求地址:/?id=123&name=bob

服务端方法:void Action(int id, string name)   

这里的所有参数都是简单类型,都来自url

方式2:

 请求地址:/?id=123&name=bob

服务端方法:

(1)void Action([FromUri] int id, [FromUri] string name)

这个和方式1一样

(2) void Action([FromBody] string name);

这里[FormBody]特性显示标明读取整个body为一个字符串作为参数

方式3:

请求地址: /?id=123

类定义:

public class Customer {   // 定义的一个复杂对象类型

  public string Name { get; set; }

  public int Age { get; set; }

}

(1)服务端方法: void Action(int id, Customer c) 

参数id从query string中读取,参数c是一个复杂Customer对象类戏,通过formatter从body中读取

(2)服务端方法: void Action(Customer c1, Customer c2)

这里会出错!多个参数都是复杂类型,都试图从body中读取,而body只能被读取一次

(3)服务端方法: void Action([FromUri] Customer c1, Customer c2)

这种可以!不同于上面的action,复杂类型c1将从url中读取,c2将从body中读取

方式4:

ModelBinder方式:

void Action([ModelBinder(MyCustomBinder)] SomeType c)

//标示使用特定的model binder来解析参数

[ModelBinder(MyCustomBinder)]

public class

SomeType { } //

通过给特定类型SomeType声明标注[ModelBidner(MyCustomBinder)]特性使得所有SomeType类型参数应用此规则

void Action(SomeType c) // 由于c的类型为SomeType,因而应用SomeType上的特性决定其采用model binding

/*网上有篇文章:https://masuit.org/1889?t=v3oivzkjzjeo,里面介绍了为ASP.NET Core实现一个自适应ModelBinder,让Action自适应前端参数传递

大体介绍如下:文章的目的是替换掉FromBody的默认行为,写一个自定义的ModelBinder。

最终实现的方法:

Masuit.Tools.AspNetCore

安装这个nuget包,

并加入

builder.Services.AddControllers(options => options.ModelBinderProviders.InsertBodyOrDefaultBinding());

这行代码即可*/

通过这个方法解决了queryString、表单或者json传递都能够被正确接收,但是这里如果通过浏览器GET请求访问就会出错了,因此笔者找到了另外一种解决方式。

方式5:

直接上代码:

 定义接收参数实体:

 [ModelBinder(BinderType = typeof(SampleClassModelBinder))]

public class ParamEntity

{

        public string id { get; set; }

        public string name{ get; set; }

}

 

public class SampleClassModelBinder : IModelBinder

    {

        public async Task BindModelAsync(ModelBindingContext bindingContext)

        {

            try

            {

                var stream = bindingContext.HttpContext.Request.Body;

                string body;

                using (var reader = new StreamReader(stream))

                {

                    body = await reader.ReadToEndAsync();

                }

                var someClass = JsonConvert.DeserializeObject<TimeCountParamEntity>(body);

 

                bindingContext.Result = ModelBindingResult.Success(someClass);

            }

            catch (Exception ex)

            {             }

        }

    }

 方法:Action([FromBody] ParamEntity data)

 通过这个方法解决了queryString、表单或者json传递都能够被正确接收,并可以通过浏览器GET请求访问。

 

posted on 2022-09-23 14:09  FIGHTING360  阅读(1202)  评论(0编辑  收藏  举报