zoukankan      html  css  js  c++  java
  • net core RESTful Api笔记⑤

    PUT VS PATCH

    put整体更新:资源所有字段都被重写或者设置成默认值。

    patch局部更新:使用JsonPatchDocument发送变更的数据,对指定字段进行更新。

    修改EmployessController

     [HttpPut("{employeeId}")]
            public async Task<IActionResult> UpdateEmployeeForCompany(Guid companyId, Guid employeeId, EmployUpdateDto employ) 
            {
                if (!await companyRepository.CompanyExistsAsync(companyId)) 
                {
                    return NotFound();
                }
                var employeeEntity = await companyRepository.GetEmployeeAsync(companyId,employeeId);
                if (employeeEntity == null) 
                {
                    return NotFound();
                }
    
                //entity转化成updatedto
                //把转化进来的employ的值更新到updateDto
                //把updatedto映射回entity
                mapper.Map(employ, employeeEntity);
    
                companyRepository.UpdateEmployee(employeeEntity);
                await companyRepository.SaveAsync();
    
                return NoContent();
            }

    添加EmployUpdateDto

    using Rountion.API.Eneities;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Models
    {
        public class EmployUpdateDto
        {
            public string EmployeeNo { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public Gender Gender { get; set; }
            public DateTime DateOfBirth { get; set; }
        }
    }

    结果:

     PUT的更新和新增

    正常的put如果传递uri没有找到,返回404,如果客户端允许生成uri,传递到服务器可以创建资源

    修改EmployessController

    [HttpPut("{employeeId}")]
            public async Task<IActionResult> UpdateEmployeeForCompany(Guid companyId, Guid employeeId, EmployUpdateDto employ) 
            {
                if (!await companyRepository.CompanyExistsAsync(companyId)) 
                {
                    return NotFound();
                }
                var employeeEntity = await companyRepository.GetEmployeeAsync(companyId,employeeId);
                if (employeeEntity == null) 
                {
                    var employeeToAddEntity = mapper.Map<Employee>(employ);
                    employeeToAddEntity.Id = employeeId;
    
                    companyRepository.AddEmployee(companyId,employeeToAddEntity);
    
                    await companyRepository.SaveAsync();
    
                    var dtoToReturn = mapper.Map<EmployeeDto>(employeeToAddEntity);
                    return CreatedAtRoute(nameof(GetemployesFromCompany), new { CompanyId = companyId, employeeId = dtoToReturn.Id }, dtoToReturn);
                }
    
                //entity转化成updatedto
                //把转化进来的employ的值更新到updateDto
                //把updatedto映射回entity
                mapper.Map(employ, employeeEntity);
    
                companyRepository.UpdateEmployee(employeeEntity);
                await companyRepository.SaveAsync();
    
                return NoContent();
            }

     Patch用来局部更新,patch请求的body里面的数据格式是json patch:

    Patch请求的media type是application/json-patch+json

    json patch options:

    add:{"op":"add","path":"/biscuit/1","value":{"name":"Ginger Nut"}}

    Remove:{"op":"remove","path":"/biscuits"}

    Move:{"op":"move","from":"/biscuits","path":"/cookies"}

    Replice:{"op":"replice","path":"/biscuits/0/name","value":"Chocolate Digestive"}

    Copy:{"op":"copy","from":"/biscuits/0","path":"/best_biscuit"}

    Test:{"op":"test","path":"/best_biscuit/name","value":"Chocolate Digestive"}

    修改EmployessController

     [HttpPatch("{employeeId}")]
            public async Task<IActionResult> PartiallyUpdateEmployeeForCompany(Guid companyId,Guid employeeId,JsonPatchDocument<EmployUpdateDto> patchDocument) 
            {
                if (!await companyRepository.CompanyExistsAsync(companyId))
                {
                    return NotFound();
                }
                var employeeEntity = await companyRepository.GetEmployeeAsync(companyId, employeeId);
                if (employeeEntity == null)
                {
                    return NotFound();
                }
                var dotToPatch = mapper.Map<EmployUpdateDto>(employeeEntity);
    
                //需要处理验证错误
    
                patchDocument.ApplyTo(dotToPatch);
    
                mapper.Map(dotToPatch,employeeEntity);
    
                companyRepository.UpdateEmployee(employeeEntity);
    
                await companyRepository.SaveAsync();
                return NoContent();
            }
    JsonPatchDocument需要在startup里注册
     services.AddControllers(setup =>
                {
                    //返回的不是请求类型,报错
                    setup.ReturnHttpNotAcceptable = true;
                }).AddNewtonsoftJson(setup=> 
                {
                    setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                }).AddXmlDataContractSerializerFormatters();

     最后的结果:

     这里其实对返回值和在没有查到情况下没有处理,处理方式:

            [HttpPatch("{employeeId}")]
            public async Task<IActionResult> PartiallyUpdateEmployeeForCompany(Guid companyId,Guid employeeId,JsonPatchDocument<EmployUpdateDto> patchDocument) 
            {
                if (!await companyRepository.CompanyExistsAsync(companyId))
                {
                    return NotFound();
                }
                var employeeEntity = await companyRepository.GetEmployeeAsync(companyId, employeeId);
                if (employeeEntity == null)
                {
                    var employeeDto = new EmployUpdateDto();
                    patchDocument.ApplyTo(employeeDto, ModelState);
                    if (TryValidateModel(employeeDto))
                    {
                        return ValidationProblem(ModelState);
                    }
                    var employeeToAdd = mapper.Map<Employee>(employeeDto);
                    employeeToAdd.Id = employeeId;
    
                    companyRepository.AddEmployee(companyId, employeeToAdd);
                    await companyRepository.SaveAsync();
    
                    var dtoToReturn = mapper.Map<Employee>(employeeToAdd);
    
                    return CreatedAtRoute(nameof(GetemployesFromCompany), new { CompanyId = companyId, employeeId = dtoToReturn.Id }, dtoToReturn);
                }
                var dotToPatch = mapper.Map<EmployUpdateDto>(employeeEntity);
    
                //需要处理验证错误
                //这个是检测JsonPatchDocument
                //不到对应映射的属性会ModelState出错
                patchDocument.ApplyTo(dotToPatch,ModelState);
                //假如为不空的字段更新""就不行
                if (TryValidateModel(dotToPatch)) 
                {
                    return ValidationProblem(ModelState);
                }
    
                mapper.Map(dotToPatch,employeeEntity);
    
                companyRepository.UpdateEmployee(employeeEntity);
    
                await companyRepository.SaveAsync();
                return NoContent();
            }
            /// <summary>
            /// 自定义422
            /// </summary>
            /// <returns></returns>
            public override ActionResult ValidationProblem()
            {
                var options = HttpContext.RequestServices.GetRequiredService<IOptions<ApiBehaviorOptions>>();
                return (ActionResult)options.Value.InvalidModelStateResponseFactory(ControllerContext);
            }

     上面的自定义错误是需要在startup里配置的:AddControllers里

    .ConfigureApiBehaviorOptions(
                    setup=> {
                        setup.InvalidModelStateResponseFactory = context =>
                        {
                            var problemDetiles = new ValidationProblemDetails(context.ModelState)
                            {
                                Type = "http://ww.baidu.com",
                                Title = "chucuo",
                                Status = StatusCodes.Status422UnprocessableEntity,
                                Detail = "看信息",
                                Instance = context.HttpContext.Request.Path
                            };
                            problemDetiles.Extensions.Add("traceId",context.HttpContext.TraceIdentifier);
    
                            return new UnprocessableEntityObjectResult(problemDetiles) 
                            {
                                ContentTypes = { "application/problem+json"}   
                            };
                        };
                    });

    httpDelete:

            [HttpDelete("{employeeId}")]
            public async Task<IActionResult> DeleteEmployeeFromCompany(Guid companyId, Guid employeeId) 
            {
                if (!await companyRepository.CompanyExistsAsync(companyId)) 
                {
                    return NotFound();
                }
                var employeeEntity = await companyRepository.GetEmployeeAsync(companyId, employeeId);
                if (employeeEntity == null) 
                {
                    return NotFound();
                }
                companyRepository.DeleteEmployee(employeeEntity);
                await companyRepository.SaveAsync();
    
                return NoContent();
            }

    对于删除公司和员工做法一样,不过需要在OnModelCreating的对应关系里标明级联删除DeleteBehavior.Cascade,如果不行就在controller的delete里加上employee加载到内存执行delete。

  • 相关阅读:
    007 Java引用数据类型
    005 Java数组
    002 Java 引用数据类型示例
    001 Java入门和简介
    2.接口测试工具-Postman
    1、接口测试-前言
    测试工程师的进阶之路
    接口测试概述
    期末作品检查
    完成个人中心—导航标签
  • 原文地址:https://www.cnblogs.com/liuyang95/p/13234648.html
Copyright © 2011-2022 走看看