ASP.NET Core WebAPI学习-6

2023-11-11

  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
                            });
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.NET Core WebAPI学习-6 的相关文章

  • [简约webAPI]php连接MSsql server的五种方法总结

    参考了下php官方手册总结了五种PHP连接MSsql server的方法 mssql 系列函数 sqlsrv 系列函数 odbc方式连接sqlserver PDO方式连接sqlserver COM方式连接 参考php手册 xff0c 对ph
  • Java调用webApi接口,接口需要令牌验证Authorization

    Java调用webApi接口 xff0c 接口需要令牌验证Authorization 需要的包post方式 没了 需要的包 1 commons httpclient 3 1 jar 2 dom4j 1 6 1 jar post方式 span
  • 如何在 Ubuntu 20.04 上安装 Dotnet Core

    NET Core 是一个免费的开源软件框架 其设计时考虑了 Linux 和 macOS 它是 NET Framework 的跨平台继承者 适用于 Linux macOS 和 Windows 系统 NET Core 框架已经提供了用于引导项目
  • 如何在 Ubuntu 22.04 上安装 .NET Core (dotnet)

    微软 NET核心是一个免费的开源软件框架 设计时考虑了 Linux 和 macOS 它是 NET Framework 的跨平台继承者 可用于 Linux macOS 和 Windows 系统 NET Core 6 是一个 LTR 版本 将在
  • 微信小程序uploader上传文件并提交表单数据完整案例(接口框架WebAPI)

    文章目录 写在前面的话 uploader介绍 用法与代码 小程序前端 后台接口 WebAPI 采坑记录 写在前面的话 最近又自己在折腾微信小程序了 最新的一个功能中需要实现图片上传 幸运的是 微信小程序扩展能力中有现成的文件上传组件uplo
  • Blazor 模板化组件开发指南

    翻译自 Waqas Anwar 2021年4月15日的文章 A Developer s Guide To Blazor Templated Components 1 在我之前的一篇文章 Blazor 组件入门指南中 我介绍了组件参数 并向您
  • 学习abp-1-ContosoUniversity Abp版

    1 去abp官网下载模板工程 https aspnetboilerplate com 项目名称为ContosoAbp 这里使用的是net core 3 x 2 x版本在编辑用户时 会报错 打开下载的解决方案 等待nuget还原包 2 数据库
  • visual studio 2019 sql server localdb 数据库中文乱码解决方法

    今天使用localdb学习asp net core时 发现写入localdb数据库的中文为乱码 按照网上的方法解决 却无法显示 这里只有用sql语句更改了 参考这个 但我试了不成功 用sql语句更改可以 https www cnblogs
  • csharp: 用Enterprise Library对象实体绑定数据

    Enterprise Library https msdn microsoft com en us library ff648951 aspx
  • C# winform 一次只能允许一个应用(使用mutex)

    在很多应用程序开发过程中 需要只允许一个程序实例 即使是通过虚拟桌面方式连接过来的 也是只允许一个人运行 下面是实现该功能的代码 注意mutexName 为系统名称 Global为全局 表示即使通过通过虚拟桌面连接过来 也只是允许运行一次
  • Postman工具——环境变量与全局变量

    转载请注明出处 http blog csdn net water 0815 article details 53326990 本文同步发表于我的微信公众号和简书社区 微信公众号 惜福 xifu forever 扫一扫文章底部的二维码即可关注
  • 关于vs引用nuget包出错的解决办法(自己摸索)

    关于vs引用nuget包出错的解决办法 问题来源 解决办法 问题来源 vs2015在引用不同的版本的nuget安装包时会出现如下提示 An error occurred while retrieving package metadata f
  • Convert vs Cast

    Convert采用的是银行的舍入原则 而不是Cast的截取原则 Convert的四舍六入五留双规则 为了避免四舍五入规则造成的结果偏高 误差偏大的现象出现 一般采用四舍六入五留双规则 Banker s Rounding 四舍六入五留双应该改
  • Autofac与WebApi集成

    目录 Autofac原理 如何将Autofac与Web API集成 Autofac功能详解 1 HttpConfiguration 2 控制器 3 解析器 4 过滤器 1 注册过滤器提供程序 2 实现过滤器接口 3 注册过滤器 4 过滤器覆
  • C# 代码规范和质量检查工具 StyleCop.Analyzers

    简介 原来一直用 ReSharper 来进行代码质量检查 不过毕竟是收费的 所以想找个免费的可以推广给公司的同事也一起用 搜索了一下 找到了StyleCop 但是我在 VS 2015里安装 StyleCop 或者通过 Nuget 包安装 S
  • 学习C# 哈希表(HashTable)用法

    学习C 哈希表 HashTable 用法 1 哈希表 HashTable 简述 在 NET Framework中 Hashtable是System Collections命名空间提供的一个容器 用于处理和表现类似keyvalue的键值对 其
  • 将微服务部署到 Azure Kubernetes 服务 (AKS) 实践

    本文是对 NET Tutorial Deploy a microservice to Azure 的翻译和实践 入门级踩坑实践 k8s 大佬请回避 以免浪费您宝贵的时间 介绍 本文的目的是 通过使用 DockerHub 和 Azure Ku
  • .Net WebAPI 高速下载文件接口实现

    接触WebAPI一年多了 感觉是个承上启下 开创未来的技术 老一辈程序员写接口就像写方法一样 不需要了解太多网页的知识 却可以在浏览器中访问这些接口 由于是基于HTTP协议 因此不管是PC 手机还是嵌入式均可顺利访问 对于当下软件多终端的设
  • 如何禁用某些应用程序服务的动态 WebAPI

    我想关闭我的ABP项目中特定应用程序服务的自动WebAPI生成服务 RemoteService 属性可用于将类标记为远程服务或禁用本质上实现 IRemoteService 接口的特定类 RemoteService false public
  • 使用 Odata 查询基于 EF 的 DTO

    我有一个 ASP NET Core Web API 设置 其中包含 SQL Server 数据库和 EF 数据模型 版本 EF Microsoft EntityFrameworkCore 5 0 0 预览版 7 20365 15 OData

随机推荐

  • 小样本中的自监督

    自监督脉络 SimCLR SimCLRV2 BYOL Moco SimSiam 一些典型操作 原图地址 When Does Self supervision Improve Few shot Learning 2019 ECCV 关键点 通
  • 计算机视觉(四):使用K-NN分类器对CIFAR-10进行分类

    1 引言 之前我们学习了KNN分类器的原理 现在让我们将KNN分类器应用在计算机视觉中 学习如何使用这个算法来进行图片分类 2 准备工作 创建项目结构如图所示 在datasets文件中下载数据集Cifar 10 k nearest neig
  • 基于Tensorflow搭建卷积神经网络CNN(花卉识别)保姆及级教程

    项目介绍 TensorFlow2 X 搭建卷积神经网络 CNN 实现人脸识别 可以识别自己的人脸哦 搭建的卷积神经网络是类似VGG的结构 卷积层与池化层反复堆叠 然后经过全连接层 最后用softmax映射为每个类别的概率 概率最大的即为识别
  • C#使用checked检查溢出

    在进行数值类型之间的强制转换时 可能会丢失信息 比如将 int 类型转换为 short 类型时 如果 int 类型会的值大于 short 类型所能存储的最大值 那么就会发生溢出 1 使用checked检查溢出 通常情况下 发生溢出时并不会自
  • this指向

    1 在全局环境中的this window 无论是否在严格模式下 在全局执行环境中 在任何函数体外部 this 都指向全局对象 use strict console log this window console log this windo
  • 联邦学习 深度学习对抗攻击

    联邦学习本身 联邦学习 实际上是一种加密的分布式机器学习技术 参与各方可以在不披露底层数据和底层数据的加密 混淆 形态的前提下共建模型 如果机构之间的数据无法互通 一家企业一家机构数据量有限 或者是少数巨头公司垄断大量数据 而小公司很难获得
  • 移动端Touch (触摸)事件

    一 常见的触摸事件 touchstart touchmove和touchend touchstart事件 当手指触摸屏幕时候触发 即使已经有一个手指放在屏幕上也会触发 touchmove事件 当手指在屏幕上滑动的时候连续地触发 在这个事件发
  • 怎么选择boost升压电路的电感?只要三个公式

    原文来自公众号 工程师看海 添加微信 chunhou0820 获取仿真文件 BOOST电源架构是一种非常经典的升压电源方案 它是利用开关管开通和关断的时间比率 维持稳定输出的一种开关电源 它以小型 轻量和高效率的特点被广泛应用在各行业电子设
  • 1-1、Qt基本概念以及界面绑定信号与槽的实例

    1 各种程序格式的选择方式 2 例子 新建mainwindow的项目 在ui拖动一个pushbuttton 点击界面下的信号与槽的部分 点击 然后选择发送者 信号 接收者 槽 一下为源码 sampl 1 pro Project create
  • yum提示 “Cannot retrieve metalink for repository: epel/x86_64” 的解决方法

    今天在centos7服务器上用yum的时候发现 yum命令不能用了 不管用yum什么命令都会出现如下提示 完整的错误提示如下 One of the configured repositories failed Unknown and yum
  • 深入理解[观察者模式]原理与技术

    观察者模式 Observer Pattern 也叫做发布 订阅 Publish Subscribe 模式 模型 视图 Model View 模式 这个模式的一个最重要的作用就是解耦 也就是将被观察者和观察者进行解耦 使得他们之间的依赖性更小
  • 【华为OD机试真题 C++】计算最大乘积 【2022 Q4

    前言 华为OD机试真题 C 本专栏包含华为OD机试真题C 解答 会实时更新收纳网友反馈 为大家更新最新的华为德科OD机试试题 为大家提供学习和练手的题库 订阅本专栏后可私信进交流群哦 答案仅供参考 不可照抄哦 题目描述 计算最大乘积 给定一
  • 【Unity3D】粒子光环

    作业要求 参考http i remember fr en 这类网站 使用粒子流编程控制制作一些效果 如 粒子光环 这个网站打不开 参考了一下师兄们的博客的图片 我看了一下 我感觉和上课做的粒子海洋有一些相似 就是需要变成一个环形 制作流程
  • JavaScript 数字去掉小数点后的0

    JavaScript 数字去掉小数点后的0 方法很简单 JavaScript提供了现成的方法 parseFloat function parseNum value value parseFloat value
  • 从头再来系列-Markdown基本语法

    以下内容摘抄于网络 Markdown 简介 Markdown 是一种轻量级标记语言 它允许人们使用易读易写的纯文本格式编写文档 Markdown 语言在 2004 由约翰 格鲁伯 英语 John Gruber 创建 Markdown 编写的
  • oracle基础知识

    1 oracle特点 2 oracle体系 实例 一组oracle后台进程以及在服务器中分配的共享内存区域 数据库 基于磁盘的数据文件 控制文件 日志文件 参数文件和归档文件等组成的物理文件集合 数据库服务器 三者之间的关系 实例用于控制和
  • 【DBeaver日常】查询出结果后,无法回到SQL编辑页面

    正常的查询页面 正常页面可以通过以下图示中的符号进行上下调整 上三角点击完以后的展示页面 如下图 下三角点击完以后的展示页面 如下图 误触以后的页面 误触以后可以通过下图中标示的部分进行恢复 结果面板恢复 最大化区域图示 选择上图中红色框线
  • QT学习之个人编程规范

    每个人对语言的编程习惯都不一样 这里简单介绍一下自己在学习使用Qt时养成的编程习惯 仅供参考 1 命名规则 1 1 常规命名规则 1 1 1 类命名规则 适用对象 1 窗口控件实现类 所有之间或间接继承于QWidget类的实现类 规则 命名
  • OpenMP设置线程数及开启方法

    1 OpenMP线程数设置 通常我们希望并行线程数可以随着机器改变自适应的调整 网上介绍OpenMP的文章很多 但是很少提到该怎么分配线程数 一般来说线程数最大可以开到2 核心数 但是这样电脑计算资源就会被占用的过多 其他程序基本上会卡的不
  • ASP.NET Core WebAPI学习-6

    ASP NET Core WebAPI学习 1 ASP NET Core WebAPI学习 2 ASP NET Core WebAPI学习 3 ASP NET Core WebAPI学习 4 ASP NET Core WebAPI学习 5