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
起了个名字
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]
属性背后做了几件事
当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)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。