在Mac下创建ASP.NET Core Web API
在Mac下创建ASP.NET Core Web API
这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢?
原因如下:
- 官方文档涉及的内容相当全面,属于那种大而全的知识仓库,不太适合初学者,很容易让人失去重要,让人掉入到具体的细节之中。
- 对于大多数人来讲开发语言只是工具,程序员都有一个通病,就是死磕工具,把工具学深。我认为在工具上没有必要投入太多时间,以能高效地完成日常的工作项目为准即可。要需求驱动学习,你需要什么学什么。如果你学的新技术新特性只是屠龙之技或者只需要用到的时候去查一下即可的话,这种死磕这又有什么用。没有必要花120%的时间去学100%的知识,你只需要花20%的时间去学习80%的知识就可以了,剩下的等实际的项目中用到的时候去查就可以了,工具只是工具,不是工作本身。
- 目前基本所有的文章都是基于Windows平台的Visual Studio IDE来介绍的。而我用的是一台Mac,所以我将基于Mac平台的Visual Studio Code讲解适合我们实际项目中遇到的知识。
- 还有一点,就是这是我个人的学习总结。
这系列文章就是让你去花20%的时间去学80%的东西,剩下的20%再去看官方文档。
在.NET Core里面MVC和WebAPI两者被整合成一个框架,分享同一套代码和管线。这样我们就可以更方便地开发MVC应用程序和Web API接口。
创建项目
在这篇文章中我们将要创建的API如下:
| API | 描述 |
|---|---|
| GET /api/user | 获取所有的用户信息 |
| GET /api/user/{id} | 根据ID获取指定的用户 |
| POST /api/user | 添加新的用户 |
| PUT /api/user/{id} | 更新用户信息 |
| PATCH /api/user/{id} | 更新用户信息 |
| DELETE /api/user/{id} | 删除用户信息 |
根据上一篇文章,我们通过Yeoman创建一个WebAPI项目,命名为UserWebAPI:

添加模型类
然后在项目根目录下面新建一个Models文件夹,在该文件夹下面利用yo aspnet:class UserItem新建一个UserItem类。

namespace UserWebAPI.Models
{
public class UserItem
{
public string Key { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
添加仓储类
Repository类是封装了数据层的对象,包含了获取数据、并映射到实体模型类的业务逻辑。
首先我们在Models文件夹下面定义一个IUserRepositoryrepository接口。
通过运行yo aspnet:interface IUserRepository命令来创建该接口。
namespace UserWebAPI.Models
{
public interface IUserRepository
{
void Add(UserItem item);
IEnumerable<UserItem> GetAll();
UserItem Find(string key);
UserItem Remove(string key);
void Update(UserItem item);
}
}
接着再添加一个UserRepository类来实现IUserRepository接口。
namespace UserWebAPI.Models
{
public class UserRepository : IUserRepository
{
private static ConcurrentDictionary<string, UserItem> _users
= new ConcurrentDictionary<string, UserItem>();
public UserRepository()
{
Add(new UserItem { Name = "Charlie", Age = 18 });
}
public void Add(UserItem item)
{
item.Key = Guid.NewGuid().ToString();
_users[item.Key] = item;
}
public UserItem Find(string key)
{
UserItem user;
_users.TryGetValue(key, out user);
return user;
}
public IEnumerable<UserItem> GetAll()
{
return _users.Values;
}
public UserItem Remove(string key)
{
UserItem user;
_users.TryRemove(key, out user);
return user;
}
public void Update(UserItem item)
{
_users[item.Key] = item;
}
}
}
注册仓储
通过定义一个repository接口,我们从使用它的MVC Controller来解耦该repository类。我们在此将通过注入一个UserRepository来代替直接在Controller里面实例化一个UserRepository类。
为了注入一个repository到controller,我们必须通过DI容器来注册它,打开Startup.cs文件,在ConfigureServices方法添加如下代码:

添加控制器
控制器是用于处理HTTP请求并创建HTTP响应的对象,这里通过运行yo aspnet:webapicontroller UserController命令生成UserController控制器。
namespace UserWebAPI.Controllers
{
[Route("api/[controller]")]
public class UserController : Controller
{
public IUserRepository UserItems { get; set; }
public UserController(IUserRepository userItems)
{
UserItems = userItems;
}
}
}
获取用户信息
[HttpGet]
public IEnumerable<UserItem> GetAll()
{
return UserItems.GetAll();
}
[HttpGet("{id}", Name = "GetUser")]
public IActionResult GetById(string id)
{
var item = UserItems.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
上述两个方法实现了两个GET方法:
GET /api/userGET /api/user/{id}
运行dotnet restore、dotnet run之后,应用程序将会在本机启动,并在http://localhost:5000上开启监听服务。
然后在Postman上测试你的API接口是否能正确运行。

在GetById方法中:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
其中"{id}"是UserItem的ID占位符,当GetById被调用时,URL中的“{id}”值会被分配给该方法的id参数。
Name = "GetTodo"创建了一个命名的路由,并允许你在HTTP响应中链接到该路由。
GetAll方法返回了一个IEnumerable,MVC会自动将对象序列化成JSON并将JSON写入到响应消息的正文中。该方法的响应状态码为200,假设没有发生任何未处理异常。
而GetById方法返回的是一个更为通用的IActionResult类型。该方法有两种不同的返回类型:
- 如果没有项匹配指定的请求ID,该方法通过返回
NotFound表示一个404错误。 - 否则,该方法返回一个JSON响应正文和200响应码,通过返回
ObjectResult来表示。
添加新用户
[HttpPost]
public IActionResult Create([FromBody]UserItem item)
{
if (item == null)
{
return BadRequest();
}
UserItems.Add(item);
return CreatedAtRoute("GetUser", new { id = item.Key }, item);
}
通过[HttpPost] attribute 标明这个一个HTTP POST方法,[FromBody] attribute 告诉MVC从HTTP 请求的正文中获取用户UserItem值。
CreatedAtRoute方法返回一个201响应状态码(实际上是CreatedAtRouteResult对象),201状态码是通过POST方法在服务器上成功创建了一个新的资源时的标准响应码。CreateAtRoute也在响应里面添加了一个Location头信息,这个头信息指定了最新创建的User URI。
/// <summary>
/// Creates a <see cref="CreatedAtRouteResult"/> object that produces a Created (201) response.
/// </summary>
/// <param name="routeName">The name of the route to use for generating the URL.</param>
/// <param name="routeValues">The route data to use for generating the URL.</param>
/// <param name="value">The content value to format in the entity body.</param>
/// <returns>The created <see cref="CreatedAtRouteResult"/> for the response.</returns>
[NonAction]
public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object routeValues,
object value)
{
return new CreatedAtRouteResult(routeName, routeValues, value);
}
/// <summary>
/// Initializes a new instance of the <see cref="CreatedAtRouteResult"/> class with the values
/// provided.
/// </summary>
/// <param name="routeName">The name of the route to use for generating the URL.</param>
/// <param name="routeValues">The route data to use for generating the URL.</param>
/// <param name="value">The value to format in the entity body.</param>
public CreatedAtRouteResult(string routeName, object routeValues, object value)
: base(value)
{
RouteName = routeName;
RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
StatusCode = StatusCodes.Status201Created;
}
通过查看CreatedAtRouteResult的构造函数可以看到StatusCode(从ObjectResult对象继承而来)被直接设置成了Status201Created枚举值。
201状态码是当你在用POST/PUT在服务器端成功创建了一个新的资源时,服务器就应当返回201 Created同时在响应头添加一个Location来指定刚刚创建好的资源的URI。
通过Postman来发送Create请求

刚服务器接收到请求,会在VS Code的控制台显示出相应的信息:

点击Headers tab可以看到Location的值显示刚刚创建好的资源的URI。

更新用户信息(HTTP PUT)
[HttpPut("{id}")]
public IActionResult Update(string id, [FromBody] UserItem item)
{
if (item == null || item.Key != id)
{
return BadRequest();
}
var user=UserItems.Find(id);
if(user==null)
{
return NotFound();
}
UserItems.Update(item);
return new NoContentResult();
}
采用了HTTP PUT标记Update方法,并且响应状态码设置为204(No Content)。根据HTTP规范,PUT请求要求客户端发送整个被更新实体,而不是增量更新部分。如果要支持局部更新,则需要使用HTTP PATCH。
204(No Content)状态码表示服务器已经成功处理了你的请求,但不需要返回具体的数据。浏览器不用刷新页面,也不用重定向到新的页面,会保留发送了该请求的页面,不产生任何文档视图上的变化,只停留在当前页面。由于204响应被禁止包含任何消息体,因此它始终以消息头后的第一个空行结尾。对提交到服务器进行处理的数据,如果只需要返回是否成功的话,可考虑使用状态码204来作为返回信息,从而减少多余的数据传输。

NoContentResult类在构造函数中调用了父类的构造函数并把Status204NoContent传给了该类。
namespace Microsoft.AspNetCore.Mvc
{
public class NoContentResult : StatusCodeResult
{
public NoContentResult()
: base(StatusCodes.Status204NoContent)
{
}
}
}
更新用户信息(HTTP PATCH)
[HttpPatch("{id}")]
public IActionResult Update([FromBody] UserItem item, string id)
{
if (item == null)
{
return BadRequest();
}
var user = UserItems.Find(id);
if (user == null)
{
return NotFound();
}
item.Key = user.Key;
UserItems.Update(item);
return new NoContentResult();
}

删除用户
[HttpDelete("{id}")]
public IActionResult Delete(string id)
{
var user = UserItems.Find(id);
if (user == null)
{
return NotFound();
}
UserItems.Remove(id);
return new NoContentResult();
}
这个响应状态码同样是204(No Content)。

个人博客
在Mac下创建ASP.NET Core Web API的更多相关文章
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目
一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自 ...
- [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了
[译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 本文首发自:博客园 文章地址: https://www.cnblogs.com/yilezhu/p/ ...
- List多个字段标识过滤 IIS发布.net core mvc web站点 ASP.NET Core 实战:构建带有版本控制的 API 接口 ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目 Using AutoFac
List多个字段标识过滤 class Program{ public static void Main(string[] args) { List<T> list = new List& ...
- 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务
在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...
- ASP.NET Core Web API 跨域(CORS) Cookie问题
身为一个Web API,处理来自跨域不同源的请求,是一件十分合理的事情. 先上已有的文章,快速复制粘贴,启用CORS: Microsoft:启用 ASP.NET Core 中的跨域请求 (CORS) ...
- 在Mac下运行ASP.NET Core应用程序
在Mac下运行ASP.NET Core应用程序 通过参照.NET Core相关官方文档,在我的Mac电脑上用Visual Studio Code创建了我的第一个ASP.NET应用. 开发环境搭建 首先 ...
- Mac下运行ASP.NET Core应用程序
Mac下运行ASP.NET Core应用程序 在Mac下运行ASP.NET Core应用程序 通过参照.NET Core相关官方文档,在我的Mac电脑上用Visual Studio Code创建了我的 ...
- ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构.这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地 ...
随机推荐
- 一步步学习javascript基础篇(1):基本概念
一.数据类型 数据类型 基本数据类型(五种) Undefined Null Boolean Number String 复杂数据类型(一种) Object Undefined:只有一个值undefin ...
- ABP理论学习之工作单元(Unit of Work)
返回总目录 本篇目录 公共连接和事务管理方法 ABP中的连接和事务管理 仓储类 应用服务 工作单元 工作单元详解 关闭工作单元 非事务的工作单元 工作单元方法调用其它 工作单元作用域 自动保存 IRe ...
- 【腾讯Bugly干货分享】美团大众点评 Hybrid 化建设
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/rNGD6SotKoO8frmxIU8-xw 本期 T ...
- UWP图片编辑器(涂鸦、裁剪、合成)
一.编辑器简介 写这个控件之前总想找一找开源的,可以偷下懒省点事.可是各种地方都搜遍了也没有找到. 于是,那就做第一个吃螃蟹的人吧! 控件主要有三个功能:涂鸦.裁剪.合成. 涂鸦:主要是用到了InkT ...
- Linux环境下部署完JDK后运行一个简单的Java程序
前言 前一篇文章详细讲解了如何在Windows环境下安装虚拟机+Linux系统,并且成功部署了JDK. 不过部署完JDK之后,我们判断部署是否成功的依据是看"java -version&qu ...
- Orchard 微软CMS项目介绍
我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...
- 使用ViewPager+Fragment实现选项卡切换效果
实现效果 本实例主要实现用ViewPage和Fragment实现选项卡切换效果,选项卡个数为3个,点击选项卡或滑动屏幕会切换Fragment并实现选项卡下方下边框条跟随移动效果. 本程序用androi ...
- ASP.NET MVC 从零开始 - 请求处理
这篇文章是从我的 github 博客 lxconan.github.io 导入的. 这是这个系列的第三篇了.前两篇文章请参见: ASP.NET MVC 从零开始 - Create and Run AS ...
- CoreProfiler/NanoProfiler性能调试监控系列总目录
NanoProfiler - 适合生产环境的性能监控类库 之 基本功能篇 NanoProfiler - 适合生产环境的性能监控类库 之 大数据篇 NanoProfiler - 适合生产环境的性能监控类 ...
- SVN+码云 简单使用流程
1.登录码云网站...