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 的相关文章

  • SqlServer调用webapi和webService接口

    1 通过http协议post调用webapi接口 xff08 json数据格式 xff09 declare 64 ServiceUrl as varchar 1000 set 64 ServiceUrl 61 39 http 127 0 0
  • vs2010 webapi开发http请求以及website中如何实现http请求

    一 vs2010 webapi开发 第一步 xff1a 创建 第二步 xff1a 离线安装NuGet 1 复制链接到浏览器打开 xff1a http visualstudiogallery msdn microsoft com 27077b
  • 使用cefsharp在winform中嵌套浏览器,解决程序闪退问题,你也可以做一个红芯浏览器^v^

    使用cefsharp在winform中嵌套浏览器 简单使用cefsharp在winform中嵌套浏览器 在上一节 我们学习了如何简单地在winform中嵌入chromium浏览器 我在使用这个开发项目时 需要点击一个按钮 弹出嵌入浏览器的窗
  • Subquery and Wrapping query

    Subquery Progressive query Into Wrapping query 1 Using fluent syntax string names Tom Dick Harry Mary Jay IEnumerable
  • Blazor 模板化组件开发指南

    翻译自 Waqas Anwar 2021年4月15日的文章 A Developer s Guide To Blazor Templated Components 1 在我之前的一篇文章 Blazor 组件入门指南中 我介绍了组件参数 并向您
  • csharp: 用Enterprise Library对象实体绑定数据

    Enterprise Library https msdn microsoft com en us library ff648951 aspx
  • 在wpf中利用异步lambda编程,模拟数据库连接,防止界面假死

    参考 图解C 第20章异步编程第五节程序 解决在wpf中连接数据库 界面假死问题 public partial class MainWindow Window private bool isConnected false public Ma
  • C# winform 一次只能允许一个应用(使用mutex)

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

    转载请注明出处 http blog csdn net water 0815 article details 53326990 本文同步发表于我的微信公众号和简书社区 微信公众号 惜福 xifu forever 扫一扫文章底部的二维码即可关注
  • Ado.Net总结

    ADO NET总结 ADO NET 是在 NET 平台上访问数据库的组件 它是以 ODBC Open Database Connectivity 技术的方式来访问数据库的一种技术 ADO NET常用命名空间 命名空间 数据提供程序 Syst
  • 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
  • Autofac与WebApi集成

    目录 Autofac原理 如何将Autofac与Web API集成 Autofac功能详解 1 HttpConfiguration 2 控制器 3 解析器 4 过滤器 1 注册过滤器提供程序 2 实现过滤器接口 3 注册过滤器 4 过滤器覆
  • 在winform中屏蔽双击最大化或最小化窗体(C#实现),禁用任务管理器结束程序

    在需要屏蔽双击窗体最大化 最小化 关闭 拖拽窗体中写入以下代码 可以根据需要取舍代码 protected override void WndProc ref Message m if m Msg 0x112 switch int m WPa
  • Custom numeric format strings

    string Multiplier Multiplier 0 Console WriteLine string Format Multiplier 1000000 string LiteralChar LiteralChar 0 000 C
  • 30、 移动端常用开发框架

    30 移动端常用开发框架 1 框架概述 框架 顾名思义就是一套架构 它会基于自身的特点向用户提供一套较为完整的解决方案 框架的控制权在框架 本身 使用者要按照框架所规定的某种规范进行开发 前端常用的框架有 Bootstrap Vue Ang
  • Capturing iteration variables

    首先要理解Lambda表达式的延迟执行 Deferred execution An important feature of most query operators is that they execute not when constr
  • 学习C# 哈希表(HashTable)用法

    学习C 哈希表 HashTable 用法 1 哈希表 HashTable 简述 在 NET Framework中 Hashtable是System Collections命名空间提供的一个容器 用于处理和表现类似keyvalue的键值对 其
  • C# 学习笔记

    不再是学生了 成了社畜了 公司主要技术栈是C 大一时候学C 学的很迷糊 总要重新学一下 入职已经20天了 也开始上手简单增删改查了 记录了一些C 相关的东西 只是还没有系统整理 WinForm 控件命名规范 ADO NET 连接数据库 Co
  • 将微服务部署到 Azure Kubernetes 服务 (AKS) 实践

    本文是对 NET Tutorial Deploy a microservice to Azure 的翻译和实践 入门级踩坑实践 k8s 大佬请回避 以免浪费您宝贵的时间 介绍 本文的目的是 通过使用 DockerHub 和 Azure Ku
  • 使用 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