编程语言
首页 > 编程语言> > Ultimate ASP.NET CORE 6.0 Web API --- 读书笔记(9)

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的地址

所以,需要提供获得这个companyaction,也就是前面GET方法起了个名字的原因

9.2.1 Validation from the ApiController Attribute

[ApiController]属性背后做了几件事

当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;
    }
}
  1. 首先,我们的绑定器是针对IEnumerable类型的,所以检查我们需要绑定的参数
  2. 然后,我们提取数据,也就是HTTP请求发送过来的数据,并检查是不是null或者空
  3. 接着,提取IEnumerable的元素类型,然后根据这个获取到类型转换器,这个转换器的终点也就是IEnumerable的元素类型
  4. 最后,创建数组,赋值,完成数据绑定

然后将这个绑定器使用在控制器上

public IActionResult GetCompanyCollection([ModelBinder(BinderType = typeof(ArrayModelBinder))] IEnumerable<Guid> ids)

标签:CORE,ASP,bindingContext,自定义,读书笔记,company,绑定,var,public
来源: https://www.cnblogs.com/huangwenhao1024/p/16383179.html