zoukankan      html  css  js  c++  java
  • ASP.NET Core WebAPI学习-6

    1. ASP.NET Core WebAPI学习-1
    2. ASP.NET Core WebAPI学习-2
    3. ASP.NET Core WebAPI学习-3
    4. ASP.NET Core WebAPI学习-4
    5. ASP.NET Core WebAPI学习-5
    6. ASP.NET Core WebAPI学习-6

    Web API 增删改方法

    在这里插入图片描述

    PUT vs PATCH

    PUT:整体更新/替换
    资源所有的字段都被重写了,或者是设置为该字段的默认值
    PATCH: 局部更新
    使用JsonPatchDocument发送变更的数据,对资源指定的字段进行更新

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

    Patch使用方法:

    /// <summary>
    /// 局部更新Employee
    /// </summary>
    /// <param name="companyId"></param>
    /// <param name="employeeId"></param>
    /// <param name="patchDocument"></param>
    /// <returns></returns>
    [HttpPatch("{employeeId}")]
    public async Task<IActionResult> PartiallyUpdateEmployeeForCompany(
        Guid companyId,
        Guid employeeId,
        JsonPatchDocument<EmployeeUpdateDto> patchDocument)
    {
        if (!await companyRepository.CompanyExistsAsync(companyId))
        {
            return NotFound();
        }
        var employeeEntity = await companyRepository.GetEmployeeAsync(companyId, employeeId);
    
        //如果不存在则创建
        if (employeeEntity == null)
        {
            var employeeDto = new EmployeeUpdateDto();
            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<EmployeeDto>(employeeToAdd);
            return CreatedAtRoute(nameof(GetEmployeeForCompany), new
                                  {
                                      companyId,
                                      employeeId = dtoToReturn.Id
                                  }, dtoToReturn);
        }
    
        var dtoToPatch = mapper.Map<EmployeeUpdateDto>(employeeEntity);
        //需要处理验证错误
        patchDocument.ApplyTo(dtoToPatch, ModelState);
        if (!TryValidateModel(dtoToPatch))
        {
            return ValidationProblem(ModelState);//400 BadRequest
        }
        mapper.Map(dtoToPatch, employeeEntity);
        companyRepository.UpdateEmployee(employeeEntity);
        await companyRepository.SaveAsync();
        return NoContent();
    }
    

    POST vs PUT

    POST:

    1. 用来创建资源
    2. 服务器端负责URI的生成
      PUT:
    3. 必须使用一个已知的URI
    4. 如果URI对应的资源不存在,那么应该返回404错误

    PUT用来新增或更新
    在这里插入图片描述

    PATCH

    1. 用来做局部更新的
    2. PATCH请求Body里面的数据格式为JSON PATCH (RFC 6902)
    3. PATCH请求的media type是application/json-patch+json
      在这里插入图片描述

    使用Newtonsoft.JSON替换3.1默认的json库

    1. 安装Microsoft.AspNetCore.Mvc.NewtonsoftJson包
    2. 在Startup.cs的ConfigureServices配置
     public void ConfigureServices(IServiceCollection services)
     {
         services.AddControllers(configure: setup =>
                                 {
                                     setup.ReturnHttpNotAcceptable = true;
                                 })
             .AddNewtonsoftJson(setup =>
                                {
                                    setup.SerializerSettings.ContractResolver =
                                        new CamelCasePropertyNamesContractResolver();
                                })
     }
    

    在Controller里面使用自定义的错误验证报告信息

    /// <summary>
    /// 使用自定义的错误验证报告信息
    /// </summary>
    /// <param name="modelStateDictionary"></param>
    /// <returns></returns>
    public override ActionResult ValidationProblem([ActionResultObjectValue] ModelStateDictionary modelStateDictionary)
    {
        var options = HttpContext.RequestServices
            .GetRequiredService<IOptions<ApiBehaviorOptions>>();
        return (ActionResult)options.Value.InvalidModelStateResponseFactory(ControllerContext);
    }
    

    HttpDelete删除

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

    针对集合资源的分页

    集合资源的数量通常比较大,需要对它们进行分页查询
    避免性能问题
    参数通过Query String进行传递
    api/companies?pageNumber=1&pageSize=5
    每页的笔数需要进行控制
    默认就应该分页
    应该对底层的数据存储进行分页

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    查询分页参数定义:

    namespace Routine.Api.ResourceParameters
    {
        public class CompanyDtoParameter
        {
            private const int MaxPageSize = 20;
            public string CompanyName { get; set; }
            public string SearchTerm { get; set; }
            public int PageNumber { get; set; } = 1;
            private int pageSize = 5;
    
            public int PageSize
            {
                get => pageSize;
                set => pageSize = (value > MaxPageSize) ? MaxPageSize : value;
            }
        }
    }
    

    PagedList类定义

    ResourceUriType:
    namespace Routine.Api.Helpers
    {
        public enum ResourceUriType
        {
            PreviousePage,
            NextPage
        }
    }
    
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Routine.Api.Helpers
    {
        public class PagedList<T> : List<T>
        {
            public int CurrentPage { get; set; }
            public int TotalPages { get; set; }
            public int PageSize { get; set; }
            public int TotalCount { get; set; }
            public bool HasPrevious => CurrentPage > 1;
            public bool HasNext => CurrentPage < TotalPages;
            public PagedList(List<T> items, int count, int pageNumber, int pageSize)
            {
                TotalCount = count;
                PageSize = pageSize;
                CurrentPage = pageNumber;
                TotalPages = (int)Math.Ceiling(count / (double)PageSize);
                AddRange(items);
            }
    
            public static async Task<PagedList<T>> CreateAsync(IQueryable<T> source, int pageNumber, int pageSize)
            {
                var count = await source.CountAsync();
                var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync();
                return new PagedList<T>(items, count, pageNumber, pageSize);
            }
    
        }
    }
    

    查询定义:

    public async Task<PagedList<Company>> GetCompaniesAsync(CompanyDtoParameter parameter)
    {
        if (parameter == null)
        {
            throw new ArgumentNullException(nameof(parameter));
        }
        var queryExpression = context.Companies as IQueryable<Company>;
        if (!string.IsNullOrWhiteSpace(parameter.CompanyName))
        {
            queryExpression = queryExpression.Where(x => x.Name == parameter.CompanyName.Trim());
        }
        if (!string.IsNullOrWhiteSpace(parameter.SearchTerm))
        {
            queryExpression = queryExpression.Where(x => x.Name == parameter.SearchTerm.Trim() ||
                                                    x.Introduction.Contains(parameter.SearchTerm.Trim()));
        }
        //分页
        //queryExpression = queryExpression
        //    .Skip(parameter.PageSize * (parameter.PageNumber - 1))
        //    .Take(parameter.PageSize);
        //return await queryExpression.ToListAsync();
        return await PagedList<Company>.CreateAsync(queryExpression, parameter.PageNumber, parameter.PageSize);
    }
    

    Controller中使用分页:

    [HttpGet(Name = nameof(GetCompanies))]
    [HttpHead]
    public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompanies([FromQuery]CompanyDtoParameter parameter = null)
    {
        //var companies = await companyRepository.GetCompaniesAsync();
        //return Ok(companies);
        //CompanyDtoParameter parameter = null;
        var companies = await companyRepository.GetCompaniesAsync(parameter);
        //var companyDtos = new List<CompanyDto>();
        //foreach (var item in companies)
        //{
        //    companyDtos.Add(new CompanyDto()
        //    {
        //        Id = item.Id,
        //        CompanyName = item.Name
        //    });
        //}
        var previousPageLink = companies.HasPrevious
            ? CreateCompaniesResourceUri(parameter, ResourceUriType.PreviousePage)
            : null;
        var nextPageLink = companies.HasNext
            ? CreateCompaniesResourceUri(parameter, ResourceUriType.NextPage)
            : null;
        var paginationMetadata = new
        {
            totalCount = companies.TotalCount,
            pageSize = companies.PageSize,
            currentPage = companies.CurrentPage,
            totalPages = companies.TotalPages,
            previousPageLink,
            nextPageLink
        };
        //在Response头部,添加分页信息
        Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(paginationMetadata, new JsonSerializerOptions()
                                                                      {
                                                                          Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                                                                      }));
    
        var companyDtos = mapper.Map<IEnumerable<CompanyDto>>(companies);
    
        return Ok(companyDtos);
    }
    
    /// <summary>
    /// 创建分页url
    /// </summary>
    /// <param name="parameter"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    private string CreateCompaniesResourceUri(CompanyDtoParameter parameter, ResourceUriType type)
    {
        switch (type)
        {
            case ResourceUriType.PreviousePage:
                return Url.Link(nameof(GetCompanies), new
                                {
                                    pageNumber = parameter.PageNumber - 1,
                                    pageSize = parameter.PageSize,
                                    companyName = parameter.CompanyName,
                                    searchTerm = parameter.SearchTerm
                                });
            case ResourceUriType.NextPage:
                return Url.Link(nameof(GetCompanies), new
                                {
                                    pageNumber = parameter.PageNumber + 1,
                                    pageSize = parameter.PageSize,
                                    companyName = parameter.CompanyName,
                                    searchTerm = parameter.SearchTerm
                                });
            default:
                return Url.Link(nameof(GetCompanies), new
                                {
                                    pageNumber = parameter.PageNumber,
                                    pageSize = parameter.PageSize,
                                    companyName = parameter.CompanyName,
                                    searchTerm = parameter.SearchTerm
                                });
        }
    }
    
  • 相关阅读:
    flex>导航
    flex>图表控件
    Struts2>Cannot find the tag library descriptor for /strutstags
    jsp>Smartupload例子代码
    flex>MXML语法
    解决JBoss只能通过localhost(127.0.0.1)而不能通过IP访问
    jsp>tomcat配置虚拟目录
    JSF>概述
    Struts2>中文乱码
    flex>HttpService
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878828.html
Copyright © 2011-2022 走看看