Ultimate ASP.NET CORE 6.0 Web API --- 读书笔记(9)
作者:互联网
Creating Resources
本文内容来自书籍: Marinko Spasojevic - Ultimate ASP.NET Core Web API - From Zero To Six-Figure Backend Developer (2nd edition)
9.1 Handling POST Requests
[HttpGet("{id:guid}", Name = "CompanyById")]
,将GET修改后,给这个action
起了个名字
我们之前有输出的DTO,现在需要一个输入的DTO
public record CompanyForCreationDto(string Name, string Address, string Country);
注意:在一些项目中,输入和输出的DTO是同一个,但是推荐将它们分开,这样更加灵活容易重构
在输出的时候,我们没有验证参数,但是现在有了输入,需要验证输入的每个参数
[HttpPost]
public IActionResult CreateCompany([FromBody] CompanyForCreationDto? company)
{
if (company is null)
return BadRequest("CompanyForCreationDto object is null");
var createdCompany = _service.CompanyService.CreateCompany(company);
return CreatedAtRoute("CompanyById", new { id = createdCompany.Id }, createdCompany);
}
因为输入是来自客户端,所以有可能是null,所以需要验证入参
然后就是在新增成功之后的返回CreatedAtRoute
,这个方法会给客户端返回201
,代表以创建
而且,会在响应头的Location
属性中,填充查找这个新增的company
的地址
所以,需要提供获得这个company
的action
,也就是前面GET方法起了个名字的原因
9.2.1 Validation from the ApiController Attribute
[ApiController]
属性背后做了几件事
- 属性路由的前提
- 自动响应HTTP 400
- 推测并绑定参数
- 推测文件上传请求
- 对错误码的细节描述
当POST请求没有请求体,就会自动返回400,这是一种很好的行为,不过它阻止了我们返回自定义的不同信息和错误码给客户端
如果需要开启自定义的响应,需要在主项目中配置,压制/禁止默认的模型状态验证,也就是[ApiController]
所使用的验证
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
这样,我们就可以不需要将[ApiController]
删除来实现返回自定义的响应,因为属性还提供了其他的我们想要的功能
9.6 Model Binding in API
在一些参数传进来的时候,可能由于参数是自定义类型的数据,所以需要我们自定义一些数据绑定器
public class ArrayModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (!bindingContext.ModelMetadata.IsEnumerableType)
{
bindingContext.Result = ModelBindingResult.Failed();
return Task.CompletedTask;
}
var providedValue = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName)
.ToString();
if (string.IsNullOrEmpty(providedValue))
{
bindingContext.Result = ModelBindingResult.Success(null);
return Task.CompletedTask;
}
var genericType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
var converter = TypeDescriptor.GetConverter(genericType);
var objectArray = providedValue
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => converter.ConvertFromString(x.Trim()))
.ToArray();
var guidArray = Array.CreateInstance(genericType, objectArray.Length);
objectArray.CopyTo(guidArray, 0);
bindingContext.Model = guidArray;
bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
return Task.CompletedTask;
}
}
- 首先,我们的绑定器是针对
IEnumerable
类型的,所以检查我们需要绑定的参数 - 然后,我们提取数据,也就是HTTP请求发送过来的数据,并检查是不是null或者空
- 接着,提取
IEnumerable
的元素类型,然后根据这个获取到类型转换器,这个转换器的终点也就是IEnumerable
的元素类型 - 最后,创建数组,赋值,完成数据绑定
然后将这个绑定器使用在控制器上
public IActionResult GetCompanyCollection([ModelBinder(BinderType = typeof(ArrayModelBinder))] IEnumerable<Guid> ids)
标签:CORE,ASP,bindingContext,自定义,读书笔记,company,绑定,var,public 来源: https://www.cnblogs.com/huangwenhao1024/p/16383179.html