热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ASP.NETCore3.x入门(七)WebAPI

此入门教程是记录下方参考资料视频的学习过程开发工具:VisualStudio2019参考资料:https:www.bilibili.comvideoBV1c441167KQAPI文

此入门教程是记录下方参考资料视频的学习过程
开发工具:Visual Studio 2019

参考资料:https://www.bilibili.com/video/BV1c441167KQ
API文档:https://docs.microsoft.com/zh-cn/dotnet/api/?view=aspnetcore-3.1

目录

ASP.NET Core 3.x 入门(一)创建项目 和 部署

ASP.NET Core 3.x 入门(二)建立 Controller ,使用 Tag Helper

ASP.NET Core 3.x 入门(三)View Component

ASP.NET Core 3.x 入门(四)Razor Page

ASP.NET Core 3.x 入门(五)SignalR

ASP.NET Core 3.x 入门(六)Blazor

ASP.NET Core 3.x 入门(七)Web API

ASP.NET Core 3.x 入门(八)gRPC - Protocol Buffer

ASP.NET Core 3.x 入门(九)gRPC in ASP.NET Core 3.x

架构

  • RESTful Web API:这次实现的
  • Repository:就是之前用的 Service
  • Controller:这里我们不返回完整的页面了,只返回数据,通常是 JSON

新建项目

还是 ASP.NET Core Web Application
我的命名是 My_ASP_NET_Core_Api
空模板,Https 和 Docker 都不勾选
将之前项目的 Models 和 Services 文件夹都复制到当前项目中,Services 目录下删除 Department 和 Employee 相关的接口和类

Repositories

项目下新建 Repositories 文件夹,新建六个类
IDepartmentRepository.cs

public interface IDepartmentRepository
{
    Task Add(Department department);
    Task> GetAll();
    Task GetById(int id);
}

DepartmentRepository.cs

public class DepartmentRepository : IDepartmentRepository
{
    private readonly List _departments = new List();

    public DepartmentRepository()
    {
        this._departments.Add(new Department
        {
            Id = 1,
            Name = "HR",
            EmployeeCount = 16,
            Location = "Beijing"
        });
        this._departments.Add(new Department
        {
            Id = 2,
            Name = "R&D",
            EmployeeCount = 52,
            Location = "Shanghai"
        });
        this._departments.Add(new Department
        {
            Id = 3,
            Name = "Sales",
            EmployeeCount = 200,
            Location = "China"
        });
    }

    public Task> GetAll()
    {
        return Task.Run(() => this._departments.AsEnumerable());
    }

    public Task GetById(int id)
    {
        return Task.Run(() => this._departments.FirstOrDefault(x => x.Id == id));
    }

    public Task Add(Department department)
    {
        department.Id = this._departments.Max(x => x.Id) + 1;
        this._departments.Add(department);
        return Task.Run(() => department);
    }
}

IEmployeeRepository.cs

public interface IEmployeeRepository
{
    Task Add(Employee employee);
    Task> GetByDepartmentId(int departmentId);
    Task Fire(int id);
}

EmployeeRepository.cs

public class EmployeeRepository : IEmployeeRepository
{
    private readonly List _employees = new List();

    public EmployeeRepository()
    {
        this._employees.Add(new Employee
        {
            Id = 1,
            DepartmentId = 1,
            FirstName = "Nick",
            LastName = "Carter",
            Gender = Gender.男
        });
        this._employees.Add(new Employee
        {
            Id = 2,
            DepartmentId = 1,
            FirstName = "Michael",
            LastName = "Jackson",
            Gender = Gender.男
        });
        this._employees.Add(new Employee
        {
            Id = 3,
            DepartmentId = 1,
            FirstName = "Mariah",
            LastName = "Carey",
            Gender = Gender.女
        });
        this._employees.Add(new Employee
        {
            Id = 4,
            DepartmentId = 2,
            FirstName = "Axl",
            LastName = "Rose",
            Gender = Gender.男
        });
        this._employees.Add(new Employee
        {
            Id = 5,
            DepartmentId = 2,
            FirstName = "Kate",
            LastName = "Winslet",
            Gender = Gender.女
        });
        this._employees.Add(new Employee
        {
            Id = 6,
            DepartmentId = 3,
            FirstName = "Rob",
            LastName = "Thomas",
            Gender = Gender.男
        });
        this._employees.Add(new Employee
        {
            Id = 7,
            DepartmentId = 3,
            FirstName = "Avril",
            LastName = "Lavigne",
            Gender = Gender.女
        });
        this._employees.Add(new Employee
        {
            Id = 8,
            DepartmentId = 3,
            FirstName = "Katy",
            LastName = "Perry",
            Gender = Gender.女
        });
        this._employees.Add(new Employee
        {
            Id = 9,
            DepartmentId = 3,
            FirstName = "Michelle",
            LastName = "Monaghan",
            Gender = Gender.女
        });
    }
    public Task Add(Employee employee)
    {
        employee.Id = this._employees.Max(x => x.Id) + 1;
        this._employees.Add(employee);
        return Task.Run(() => employee);
    }

    public Task> GetByDepartmentId(int departmentId)
    {
        return Task.Run(() => this._employees.Where(x => x.DepartmentId == departmentId));
    }

    public Task Fire(int id)
    {
        return Task.Run(() =>
        {
            var employee = this._employees.FirstOrDefault(e => e.Id == id);
            if (employee != null)
            {
                employee.Fired = true;
                return employee;
            }

            return null;
        });
    }
}

ISummaryRepository.cs

public interface ISummaryRepository
{
    public Task GetCompanySummary();
}

SummaryRepository.cs

public class SummaryRepository : ISummaryRepository
{
    private readonly IDepartmentRepository _departmentRepository;

    public SummaryRepository(IDepartmentRepository departmentRepository)
    {
        this._departmentRepository = departmentRepository;
    }

    public Task GetCompanySummary()
    {
        return Task.Run(() =>
        {
            var all = this._departmentRepository.GetAll().Result;
            return new CompanySummary
            {
                EmployeeCount = all.Sum(x => x.EmployeeCount),
                AverageDepartmentEmployeeCount = (int)all.Average(x => x.EmployeeCount)
            };
        });
    }
}

这六个文件和之前删除的 Service 差不多

写完别忘记注册,Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddSingleton();
        services.AddSingleton();
        services.AddSingleton();
        services.AddSingleton();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Controllers

新建 Controllers
ApiController 建议继承 ControllerBase ,Controller 就是继承自 ControllerBase
ControllerBase 没有对 View 的支持,因为是 Web Api ,所以不需要 View

DepartmentController.cs

[Route("v1/[controller]")]
[ApiController]
public class DepartmentController : ControllerBase
{
    private readonly IDepartmentRepository _departmentRepository;

    public DepartmentController(IDepartmentRepository departmentRepository)
    {
        this._departmentRepository = departmentRepository;
    }

    [HttpGet]// v1/Department verb:GET
    //public async Task GetAll() //也可以
    public async Task>> GetAll()
    {
        var departments = await this._departmentRepository.GetAll();

        if (!departments.Any())
        {
            return NoContent();
        }

        return Ok(departments);
        //return new ObjectResult(departments);
    }

    [HttpPost]// v1/Department verb:POST
    public async Task> Add([FromBody]Department department)
    {
        var added = await this._departmentRepository.Add(department);

        return Ok(added);
    }
}

EmployeeController.cs

[Route("v1/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
    private readonly IEmployeeRepository _employeeRepository;

    public EmployeeController(IEmployeeRepository employeeRepository)
    {
        this._employeeRepository = employeeRepository;
    }

    [HttpGet("{departmentId}")]
    public async Task GetByDepartmentId(int departmentId)
    {
        var employees = await this._employeeRepository.GetByDepartmentId(departmentId);

        if (!employees.Any())
        {
            return NoContent();
        }

        return Ok(employees);
    }

    [HttpGet("One/{id}", Name = "GetById")]
    public async Task GetById(int id)
    {
        var result = await this._employeeRepository.GetById(id);

        if (null == result)
        {
            return NotFound();
        }

        return Ok(result);
    }

    [HttpPost]
    public async Task Add([FromBody] Employee employee)
    {
        var added = await this._employeeRepository.Add(employee);
        return CreatedAtRoute("GetById", new { id = added.Id }, added);
        //这里的 GetById 就是上面写的那个 GetById 方法,[HttpGet("One/{id}", Name = "GetById")]
    }

    [HttpPut("{id}")]//其实这里应该用 [HttpPatch]
    public async Task Fire(int id)
    {
        var result = await this._employeeRepository.Fire(id);

        if (null != result)
        {
            return NoContent();
        }

        return NotFound();
    }
}

SummaryController.cs

[Route("v1/[controller]")]
[ApiController]
public class SummaryController : ControllerBase
{
    private readonly ISummaryRepository _summaryRepository;

    public SummaryController(ISummaryRepository summaryRepository)
    {
        this._summaryRepository = summaryRepository;
    }

    public async Task Get()
    {
        var result = await this._summaryRepository.GetCompanySummary();
        return Ok(result);
    }
}

ApiController Attribute

Controller 上标注的 [ApiController]

  • Attribute 路由
  • 对 Model 自动验证:比如 [FromBody]Department department ,会根据 Model 字段或属性的 Attribute 标注进行验证
  • 推断绑定源:比如 [FromBody]Department department 显示的写出 department 是从请求的 Body 里来的,因为 Controller 有 [ApiController] 标注,所以不加 [FromBody] 也行
    • [FromBody] :Body
    • [FromForm] :表单
    • [FromRoute] :类似 [HttpGet("{departmentId}")] ,但是使用 [HttpGet("")] 的方法的参数里就不需要再标注 [FromRoute]
    • [FromQuery]:QueryString:? 的参数
    • [FromHeader] :从 Http 请求的 Header 里取数据
    • [FromServices]
    • 具体内容去看文档

补充

[Route("v1/[controller]")]

路由,v1 版本控制,[controller] 是一个通配符,指的是控制器的名称,Department
RESTful Api 主要是通过 Http 动词来区分 Action ,所以默认不用加 Action ,就是说 url 访问 GET 的方法不需要管 Action 的名称

[ApiController]
[HttpGet]

HttpGet 默认可以不写,url 就是 版本/控制器名称 verb:GET

[HttpPost]
[FromBody]
CreatedAtRoute (string routeName, object routeValues, object content);

routeName
String
用于生成 URL 的路由的名称。

routeValues
Object
用于生成 URL 的路由数据。

content
Object
要在实体正文中设置格式的内容值。说白了就是返回给前端的数据

使用 Postman 查看结果

若使用 xml 去请求,还是会返回 json
因为默认情况下,ASP.NET Core Api 返回的是 json 格式的数据
若想支持 xml ,需要修改 Startup 类

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddXmlSerializerFormatters();
}

ASP.NET Core Api 也支持一些常用的格式,以及自定义格式

Department Get 测试

http://localhost:5000/v1/Department

效果图
ASP.NET Core 3.x  入门(七)Web API

Department Post 测试

选择 POST ,url 不变,在 Body 里添加数据
ASP.NET Core 3.x  入门(七)Web API

效果图
ASP.NET Core 3.x  入门(七)Web API

状态码截图
ASP.NET Core 3.x  入门(七)Web API

EmployeeController Get 测试

http://localhost:5000/v1/Emoloyee/1

效果图
ASP.NET Core 3.x  入门(七)Web API

http://localhost:5000/v1/Employee/One/1

效果图
ASP.NET Core 3.x  入门(七)Web API

EmployeeController Post 测试

http://localhost:5000/v1/Employee

效果图
ASP.NET Core 3.x  入门(七)Web API

EmployeeController Put 测试

http://localhost:5000/v1/Employee/9

效果图
ASP.NET Core 3.x  入门(七)Web API

状态码 204 ,对应 NoContent() ,说明成功

Get 去验证一下
效果图
ASP.NET Core 3.x  入门(七)Web API

SummaryController Get 测试

http://localhost:5000/v1/Summary

效果图
ASP.NET Core 3.x  入门(七)Web API

ASP.NET Core 3.x 入门(七)Web API 结束


推荐阅读
  • ABP框架是ASP.NET Boilerplate的简称,它不仅是一个开源且文档丰富的应用程序框架,还提供了一套基于领域驱动设计(DDD)的最佳实践架构模型。本文将详细介绍ABP框架的特点、项目结构及其在Web API优先架构中的应用。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • iOS 百度地图使用指南:基本定位与地理编码
    本文详细介绍如何在 iOS 应用中集成百度地图,实现基本的地图定位和地理编码功能。配置详情请参考官方文档:http://developer.baidu.com/map/index.php?title=iossdk ... [详细]
  • 申请地址:https://developer.apple.com/appstore/contact/?topic=expedite 常见申请理由:1. 我们即将发布新产品,这是一个媒体活动,我们无法承担任何风险,因此在多个方面努力提升应用质量。 ... [详细]
  • PostgreSQL 12 版本预览:分离 max_wal_senders 和 max_connections 的连接槽处理
    本文介绍了 PostgreSQL 12 中的一项重要改进,即 max_wal_senders 参数不再计入 max_connections,从而解决了流复制连接槽不足的问题。 ... [详细]
  • WPF项目学习.一
    WPF项目搭建版权声明:本文为博主初学经验,未经博主允许不得转载。一、前言记录在学习与制作WPF过程中遇到的解决方案。使用MVVM的优点是数据和视图分离,双向绑定,低耦合,可重用行 ... [详细]
  • 本文探讨了在 SQL Server 2012 的 Integration Services 项目中配置 ADO.NET 源时遇到的错误及其解决方案。 ... [详细]
  • 使用Tkinter构建51Ape无损音乐爬虫UI
    本文介绍了如何使用Python的内置模块Tkinter来构建一个简单的用户界面,用于爬取51Ape网站上的无损音乐百度云链接。虽然Tkinter入门相对简单,但在实际开发过程中由于文档不足可能会带来一些不便。 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • WCF类型共享的最佳实践
    在使用WCF服务时,经常会遇到同一个实体类型在不同服务中被生成为不同版本的问题。本文将介绍几种有效的类型共享方法,以解决这一常见问题。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
author-avatar
紫百合1990_950
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有