从壹开始先后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之二 || 后端项目搭建

本文3.0版本文章

https://mp.weixin.qq.com/s/U2-zxmYyRNTt97Dk5bA-2Anode

 

前言

至于为何要搭建.Net Core 平台,这个网上的解释以及铺天盖地,想了想,仍是感受重要的一点,跨平台,嗯!没错,并且比.Net 更容易搭建,速度也更快,全部的包均有Nuget提供,再也不像之前的单纯引入组件,linux


已经没有了以前的Assemblies和COM的引入,初次使用感受会很别扭,不过使用多了,发现仍是很方便的,因此你必定要会使用Nuget,真的很强大,这点儿设计思路感受更像Linux了。nginx

下边这三点,是先对 .net core  有一个初步的认识,看得懂或者看不懂都没有关系,之后你们确定都会明白的:git

 

一、.net core 框架性能测试

http://www.techempower.com/benchmarks/ 咱们能够经过这个web框架性能测试来看看 aspcore 的性能github

 

二、.net core 执行过程

三、中间件执行过程

启动的时候先执行该中间件类的构造函数,而后一路 Next() ;下去,返回的时候,正好是反向的,执行的是该类的逻辑部分:web

 

四、AOP切面

 

 

 

五、总体框架结构与数据库表UML

 

 

 

 

 

1、建立第一个Core

    说了从零开始,就得从零开始,老生常谈,开始。数据库

一、SDK 安装

固然,前提是你得安装.Net Core,VS 2015也是能够,只不过须要单独安装.Net Core,首先你得装个vs2015 而且保证已经升级至 update3及以上。apache

个人 VS 是 2017,我这里只说2017,有不会的网友能够留言,只要在Visual Studio Installer 中安装下图中的Core 平台便可。编程

下载 SDK 地址 :https://dotnet.microsoft.com/downloadjson

选择指定的平台便可安装:

 

这里说下,SDK 和 RunTime 的区别:
1、SDK 是用来开发 NetCore 的,内部捆绑了 Runtime 运行时;
二、可是如何只想运行 NetCore 项目的话,只须要在服务器中安装 Runtime 运行时便可;

 

怎么判断安装成功了呢?直接运行命令,若是有结果证实成功了:

 

 

 

二、新建项目


一、File --> Project (记得文件名不要是中文,否则,你懂的)

二、而后选择.Net Core 版本和项目类型,我选择相对稳定的ASP.NET Core 2.2,而后选择API的项目类型

至于其余的,你们能够本身玩一玩,还有就是是否Docker支持,这两年Docker着实很火,我也会在之后的时间里,补上这块儿的使用。。。

 

 

Duang ,而后就出现了,特别简单的一个.Net Core API就这么诞生了,嗯不错,基本的分红这几个部分,是否是特别像一个控制台程序?并且真是简洁了很多。

 

这里要注意下,关于Https选项问题,有不少小伙伴在之后的接口调用中,勾选了这个,可是仍是一直使用 http 协议去访问,致使找不到响应的接口地址。

 

一、是你的项目建立的时候,勾选了 Https 选项,若是你尚未建立,那就能够不要勾选那个 HTTPS选项。

二、若是你的项目已经建立好了,每次访问都是HTTPS的,可是你不想这么作,能够在 launthSettings.json 文件中,把sslPort 端口号改为0便可

 

 

二、新建项目(3.0SDK)

 

 

点击下一步。

而后建立模板:

 

 

 

 

三、项目总体结构分析

接下来我们看看这个项目都包含了哪些东西: 

 

点开Controllers --> ValuesController 文件,你会发现四个方法,而且每一个方法也有各自的特性,分别是HttpGet,HttpPost,HttpPut,HttpDelete,这四个就是传说中的RESTful风格的编程。

为何会有这种风格呢:

RESTful 风格接口实际状况是,咱们在先后端在约定接口的时候,能够约定各类风格的接口,可是,RESTful 接口是目前来讲比较流行的,而且在运用中比较方便和常见的接口。

虽然它有一些缺陷,目前 github 也在主推 GraphQL 这种新的接口风格,但目前国内来讲仍是 RESTful 接口风格比较广泛。而且,在掌握了 RESTful 接口风格以后,会深刻的理解这种接口的优缺点,到时候,你天然会去想解决方案,而且在项目中实行新的更好的理念,因此,我这系列的博文,依然采用 http://cnodejs.org/ 网站提供的 RESTful 接口来实战。

了解程序开发的都应该知道,咱们所作的大多数操做都是对数据库的四格操做 “增删改查” 对应到咱们的接口操做分别是:post 插入新数据delete 删除数据put 修改数据get 查询数据

注意,这里是咱们约定,并不是这些动做只能干这件事情。从表层来讲,除get外的其余方法,没有什么区别,都是同样的。从深层来讲包括 get在内的全部方法都是如出一辙的,没有任何区别。可是,咱们约定,每种动做对应不一样的操做,这样方便咱们统一规范咱们的全部操做。

假设,咱们的接口是 /api/v1/love 这样的接口,采用 RESTful 接口风格对应操做是以下的:get 操做 /api/v1/love获取 /api/v1/love 的分页列表数据,获得的主体,将是一个数组,咱们能够用数据来遍历循环列表post 操做 /api/v1/love咱们会往 /api/v1/love 插入一条新的数据,咱们插入的数据,将是JOSN利用对象传输的。get 操做 /api/v1/love/1咱们获取到一个 ID 为 1 的数据,数据通常为一个对象,里面包含了 1 的各项字段信息。put 操做 /api/v1/love/1咱们向接口提交了一个新的信息,来修改 ID 为 1 的这条信息delete 操做 /api/v1/love/1咱们向接口请求,删除 ID 为 1 的这一条数据

由上述例子可知,咱们实现了5种操做,但只用了两个接口地址, /api/v1/love 和 /api/v1/love/1 。因此,采用这种接口风格,能够大幅的简化咱们的接口设计。

 

 
提醒:2.1之后,新建的controller 所继承的基类的 ControllerBase,致使在接口的返回值中,不能使用 return Json();方法,你可使用 return Ok(xxx),效果是同样的,
若是你必定要使用 Json,那就修改基类,继承 Controller 吧。

 

而后 F5 运行,就会看到接口地址,以及对应的内容,你能够根据本身的须要进行各类配置合适的路由,

这里要注意下,若是出现特性相同,方法同名,参数同样的,编译会报错,起名字很重要。

还有,这里会自动跳转到默认地址 api/values,固然是能够配置的,就在 Properties --> launchSettings.json 中

 


 

接下来点开 appsettings.json 文件,这里就是整个系统app的配置地址,更相似之前的web.config,之后你们会用到。

 这里还要说一下[HttpGet("{id}"),Name="Get"] ,这个有时候会带 Name,不少小伙伴不知道这是干啥的,我就简单说一下:

[HttpGet("{id}", Name = "GetTodo")] public IActionResult GetById(long id) 

"{id}" 是 todo 项 的 ID 的占位符变量。 调用 GetById 时,它会将 URL 中“{id}”的值分配给方法的 id 参数。Name = "GetTodo" 建立一个命名的路由,使你可以 HTTP 响应中连接到此路由。 稍后将使用示例进行解释。 有关详细信息,请参阅路由到控制器操做,还有这个Attribute Routing in Web API 2

 

通常来讲,路由名称都是和路由url一一对应的,尽可能不要重复,不过也不多有人写这个,没啥用,因此通常不要写。

 

 

继续往下,打开Startup.cs 文件这里是整个项目的启动文件,全部的启动相关的都会在这里配置,好比 依赖注入,跨域请求,Redis缓存等,更多详情在之后的文章中都会有所提起

 


 

2018-09-23 更新

2、重要文件说明

一、Program.cs

namespace CoreBackend.Api
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

这个Program是程序的入口, 看起来很眼熟, 是由于asp.net core application实际就是控制台程序(console application).

它是一个调用asp.net core 相关库的console application. 

Main方法里面的内容主要是用来配置和运行程序的.

由于咱们的web程序须要一个宿主, 因此 BuildWebHost这个方法就建立了一个WebHostBuilder. 并且咱们还须要Web Server.

asp.net core 自带了两种http servers, 一个是WebListener, 它只能用于windows系统, 另外一个是kestrel, 它是跨平台的.

kestrel是默认的web server, 就是经过UseKestrel()这个方法来启用的.

可是咱们开发的时候使用的是IIS Express, 调用UseIISIntegration()这个方法是启用IIS Express, 它做为Kestrel的Reverse Proxy server来用.

 

 

若是在windows服务器上部署的话, 就应该使用IIS做为Kestrel的反向代理服务器来管理和代理请求.

若是在linux上的话, 可使用apache, nginx等等的做为kestrel的proxy server.

固然也能够单独使用kestrel做为web 服务器, 可是使用iis做为reverse proxy仍是有不少有优势的: 例如,IIS能够过滤请求, 管理证书, 程序崩溃时自动重启等.

UseStartup<Startup>(), 这句话表示在程序启动的时候, 咱们会调用Startup这个类.

Build()完以后返回一个实现了IWebHost接口的实例(WebHostBuilder), 而后调用Run()就会运行Web程序, 而且阻止这个调用的线程, 直到程序关闭.

 

若是想要对AspNetCore源码进行研究,能够查看源码,这里提供两个方法:

一、F12,固然这个不能看到详细的,你须要安装一个组件,VS2017 Resharper

二、查看Github 开源源码 https://github.com/aspnet/MetaPackages/tree/master/src/Microsoft.AspNetCore 

 

二、Startup.cs

namespace CoreBackend.Api
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
//判断是不是环境变量
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //这个就是一个简单的中间件写法 app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }

其实Startup算是程序真正的切入点.

ConfigureServices方法是用来把services(各类服务, 例如identity, ef, mvc等等包括第三方的, 或者本身写的)加入(register)到container(asp.net core的容器)中去, 并配置这些services. 这个container是用来进行dependency injection的(依赖注入). 全部注入的services(此外还包括一些框架已经注册好的services) 在之后写代码的时候, 均可以将它们注入(inject)进去. 例如上面的Configure方法的参数, app, env, loggerFactory都是注入进去的services.

 

Configure方法是asp.net core程序用来具体指定如何处理每一个http请求的, 例如咱们可让这个程序知道我使用mvc来处理http请求, 那就调用app.UseMvc()这个方法就行. 可是目前, 全部的http请求都会致使返回"Hello World!".

 

 

看一看咱们项目的最后,Configure方法是如何配置的:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                // 在开发环境中,使用异常页面,这样能够暴露错误堆栈信息,因此不要放在生产环境。
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // 在非开发环境中,使用HTTP严格安全传输(or HSTS) 对于保护web安全是很是重要的。
                // 强制实施 HTTPS 在 ASP.NET Core,配合 app.UseHttpsRedirection
                //app.UseHsts();

            }

            #region Swagger
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                //以前是写死的
                //c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
                //c.RoutePrefix = "";//路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉

                //根据版本名称倒序 遍历展现
                typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
                {
                    c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
                });
            });
            #endregion

            #region Authen
            //app.UseMiddleware<JwtTokenAuth>();//注意此受权方法已经放弃,请使用下边的官方验证方法。可是若是你还想传User的全局变量,仍是能够继续使用中间件
            app.UseAuthentication();
            #endregion

            #region CORS
            //跨域第二种方法,使用策略,详细策略信息在ConfigureService中
            app.UseCors("LimitRequests");//将 CORS 中间件添加到 web 应用程序管线中, 以容许跨域请求。


            //跨域第一种版本,请要ConfigureService中配置服务 services.AddCors();
            //    app.UseCors(options => options.WithOrigins("http://localhost:8021").AllowAnyHeader()
            //.AllowAnyMethod()); 
            #endregion

            // 跳转https
            app.UseHttpsRedirection();
            // 使用静态文件
            app.UseStaticFiles();
            // 使用cookie
            app.UseCookiePolicy();
            // 返回错误码
            app.UseStatusCodePages();//把错误码返回前台,好比是404

            app.UseMvc();
        }

 

 

三、调试方法

.net core 调试的两种方法

一、经过IIS调试

 

二、项目自带的Kestrel web应用调式

 

 

 

3、注册并使用MVC

由于asp.net core 2.0使用了一个大而全的metapackage, 因此这些基本的services和middleware是不须要另外安装的.

首先, 在ConfigureServices里面向Container注册MVC: services.AddMvc();

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(); // 注册MVC到Container
        }

而后再Configure里面告诉程序使用mvc中间件:

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

            app.UseMvc();
 

注意顺序, 应该在处理异常的middleware后边调用app.UseMvc(), 因此处理异常的middleware能够在把request交给mvc之间就处理异常, 更重要的是它还能够捕获并处理返回MVC相关代码执行中的异常.

而后别忘了把app.Run那部分代码去掉. 而后改回到Develpment环境, 跑一下, 试试效果:

Chrome显示了一个空白页, 按F12, 显示了404 Not Found错误.

这是由于我只添加了MVC middleware, 可是它啥也没作, 也没有找到任何可用于处理请求的代码, 因此咱们要添加Controller来返回数据/资源等等

4、核心知识点

一、Routing 路由

路由有两种方式: Convention-based (按约定), attribute-based(基于路由属性配置的). 

其中convention-based (基于约定的) 主要用于MVC (返回View或者Razor Page那种的).

Web api 推荐使用attribute-based.

这种基于属性配置的路由能够配置Controller或者Action级别, uri会根据Http method而后被匹配到一个controller里具体的action上.

经常使用的Http Method有:

  • Get, 查询, Attribute: HttpGet, 例如: '/api/product', '/api/product/1'
  • POST, 建立, HttpPost, '/api/product'
  • PUT 总体修改更新 HttpPut, '/api/product/1'
  • PATCH 部分更新, HttpPatch, '/api/product/1'
  • DELETE 删除, HttpDelete, '/api/product/1

还有一个Route属性(attribute)也能够用于Controller层, 它能够控制action级的URI前缀.

如下不是本系列,就看思路便可,不用敲代码

 
//如下不是本系列教程,就看思路便可,不用敲代码
namespace CoreBackend.Api.Controllers { //[Route("api/product")] [Route("api/[controller]")] public class ProductController: Controller { [HttpGet] public JsonResult GetProducts() { return new JsonResult(new List<Product> { new Product { Id = 1, Name = "牛奶", Price = 2.5f }, new Product { Id = 2, Name = "面包", Price = 4.5f } }); } } }
 

使用[Route("api/[controller]")], 它使得整个Controller下面全部action的uri前缀变成了"/api/product", 其中[controller]表示XxxController.cs中的Xxx(实际上是小写).

也能够具体指定, [Route("api/product")], 这样作的好处是, 若是ProductController重构之后更名了, 只要不改Route里面的内容, 那么请求的地址不会发生变化.

而后在GetProducts方法上面, 写上HttpGet, 也能够写HttpGet(). 它里面还能够加参数,例如: HttpGet("all"), 那么这个Action的请求的地址就变成了 "/api/product/All".

 

二、内容协商 Content Negotiation

若是 web api提供了多种内容格式, 那么能够经过Accept Header来选择最好的内容返回格式: 例如:

application/json, application/xml等等

若是设定的格式在web api里面没有, 那么web api就会使用默认的格式.

asp.net core 默认提供的是json格式, 也能够配置xml等格式.

目前只考虑 Output formatter, 就是返回的内容格式.

 

若是想输出xml格式,就配置这里:

 

 

三、建立Post Action

如下不是本系列,就看思路便可,不用敲代码

 
 
//如下不是本系列教程,就看思路便可,不用敲代码     
[Route("{id}", Name = "GetProduct")] public IActionResult GetProduct(int id) { var product = ProductService...(x => x.Id == id); if (product == null) { return NotFound(); } return Ok(product); } [HttpPost] public IActionResult Post([FromBody] ProductCreation product) { if (product == null) { return BadRequest(); } var maxId = ProductService.Max(x => x.Id); var newProduct = new Product { Id = ++maxId, Name = product.Name, Price = product.Price }; ProductService.Add(newProduct); return CreatedAtRoute("GetProduct", new { id = newProduct.Id }, newProduct); }
 

 

[HttpPost] 表示请求的谓词是Post. 加上Controller的Route前缀, 那么访问这个Action的地址就应该是: 'api/product'

后边也能够跟着自定义的路由地址, 例如 [HttpPost("create")], 那么这个Action的路由地址就应该是: 'api/product/create'.

[FromBody] , 请求的body里面包含着方法须要的实体数据, 方法须要把这个数据Deserialize成ProductCreation, [FromBody]就是干这些活的.

客户端程序可能会发起一个Bad的Request, 致使数据不能被Deserialize, 这时候参数product就会变成null. 因此这是一个客户端发生的错误, 程序为让客户端知道是它引发了错误, 就应该返回一个Bad Request 400 (Bad Request表示客户端引发的错误)的 Status Code.

传递进来的model类型是 ProductCreation, 而咱们最终操做的类型是Product, 因此须要进行一个Map操做, 目前仍是挨个属性写代码进行Map吧, 之后会改为Automapper.

返回 CreatedAtRoute: 对于POST, 建议的返回Status Code 是 201 (Created), 可使用CreatedAtRoute这个内置的Helper Method. 它能够返回一个带有地址Header的Response, 这个Location Header将会包含一个URI, 经过这个URI能够找到咱们新建立的实体数据. 这里就是指以前写的GetProduct(int id)这个方法. 可是这个Action必须有一个路由的名字才能够引用它, 因此在GetProduct方法上的Route这个attribute里面加上Name="GetProduct", 而后在CreatedAtRoute方法第一个参数写上这个名字就能够了, 尽管进行了引用, 可是Post方法走完的时候并不会调用GetProduct方法. CreatedAtRoute第二个参数就是对应着GetProduct的参数列表, 使用匿名类便可, 最后一个参数是咱们刚刚建立的数据实体

运行程序试验一下, 注意须要在Headers里面设置Content-Type: application/json.

四、Validation 验证

针对上面的Post方法,  若是请求没有Body, 参数product就会是null, 这个咱们已经判断了; 若是body里面的数据所包含的属性在product中不存在, 那么这个属性就会被忽略.

可是若是body数据的属性有问题, 好比说name没有填写, 或者name太长, 那么在执行action方法的时候就会报错, 这时候框架会自动抛出500异常, 表示是服务器的错误, 这是不对的. 这种错误是由客户端引发的, 因此须要返回400 Bad Request错误.

验证Model/实体, asp.net core 内置可使用 Data Annotations进行: 

 
//如下不是本系列教程,就看思路便可,不用敲代码
using System; using System.ComponentModel.DataAnnotations; namespace CoreBackend.Api.Dtos { public class ProductCreation { [Display(Name = "产品名称")] [Required(ErrorMessage = "{0}是必填项")] // [MinLength(2, ErrorMessage = "{0}的最小长度是{1}")] // [MaxLength(10, ErrorMessage = "{0}的长度不能够超过{1}")]
     [StringLength(10, MinimumLength = 2, ErrorMessage = "{0}的长度应该不小于{2}, 不大于{1}")] public string Name { get; set; } [Display(Name = "价格")] [Range(0, Double.MaxValue, ErrorMessage = "{0}的值必须大于{1}")] public float Price { get; set; } } }
 

这些Data Annotation (理解为用于验证的注解), 能够在System.ComponentModel.DataAnnotation找到, 例如[Required]表示必填, [MinLength]表示最小长度, [StringLength]能够同时验证最小和最大长度, [Range]表示数值的范围等等不少.

[Display(Name="xxx")]的用处是, 给属性起一个比较友好的名字.

其余的验证注解都有一个属性叫作 ErrorMessage (string), 表示若是验证失败, 就会把ErrorMessage的内容添加到错误结果里面去. 这个ErrorMessage可使用参数, {0}表示Display的Name属性, {1}表示当前注解的第一个变量, {2}表示当前注解的第二个变量.

在Controller里面添加验证逻辑:

 
//如下不是本系列教程,就看思路便可,不用敲代码     
[HttpPost] public IActionResult Post([FromBody] ProductCreation product) { if (product == null) { return BadRequest(); } if (!ModelState.IsValid) { return BadRequest(ModelState); } var maxId = ProductService.Max(x => x.Id); var newProduct = new Product { Id = ++maxId, Name = product.Name, Price = product.Price }; ProductService.Add(newProduct); return CreatedAtRoute("GetProduct", new { id = newProduct.Id }, newProduct); }
 

ModelState: 是一个Dictionary, 它里面是请求提交到Action的Name和Value的对们, 一个name对应着model的一个属性, 它也包含了一个针对每一个提交的属性的错误信息的集合.

每次请求进到Action的时候, 咱们在ProductCreationModel添加的那些注解的验证, 就会被检查. 只要其中有一个验证没经过, 那么ModelState.IsValid属性就是False. 能够设置断点查看ModelState里面都有哪些东西.

若是有错误的话, 咱们能够把ModelState看成 Bad Request的参数一块儿返回到前台.

五、PUT请求

put应该用于对model进行完整的更新. 

首先最好仍是单独为Put写一个Dto Model, 尽管属性可能都是同样的, 可是也建议这样写, 实在不想写也能够.

ProducModification.cs

 
    public class ProductModification
    {
        [Display(Name = "产品名称")]
        [Required(ErrorMessage = "{0}是必填项")]
        [StringLength(10, MinimumLength = 2, ErrorMessage = "{0}的长度应该不小于{2}, 不大于{1}")]
        public string Name { get; set; }

        [Display(Name = "价格")]
        [Range(0, Double.MaxValue, ErrorMessage = "{0}的值必须大于{1}")]
        public float Price { get; set; }
    }
 

而后编写Controller的方法:

 
//如下不是本系列教程,就看思路便可,不用敲代码     
[HttpPut("{id}")]
        public IActionResult Put(int id, [FromBody] ProductModification product)
        {
            if (product == null)
            {
                return BadRequest();
            }

            if (product.Name == "产品")
            {
                ModelState.AddModelError("Name", "产品的名称不能够是'产品'二字");
            }

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var model = ProductService.SingleOrDefault(x => x.Id == id);
            if (model == null)
            {
                return NotFound();
            }
            model.Name = product.Name;
            model.Price = product.Price;

            // return Ok(model);
            return NoContent();
        }
 

按照Http Put的约定, 须要一个id这样的参数, 用于查找现有的model.

因为Put作的是完整的更新, 因此把ProducModification整个Model做为参数.

进来以后, 进行了一套和POST如出一辙的验证, 这地方确定能够改进, 若是验证逻辑比较复杂的话, 处处写一样验证逻辑确定是很差的, 因此建议使用FluentValidation.

而后, 把ProductModification的属性都映射查询找到给Product, 这个之后用AutoMapper来映射.

返回: PUT建议返回NoContent(), 由于更新是客户端发起的, 客户端已经有了最新的值, 无须服务器再给它传递一次, 固然了, 若是有些值是在后台更新的, 那么也可使用Ok(xxx)而后把更新后的model做为参数一块儿传到前台.

 

 
 

5、结语

    好啦,项目搭建就这么愉快的解决了,并且你也应该简单了解了.Net Core API是如何安装,建立,各个文件的意义以及如何运做,如何配置等,可是既然是接口,那必定是要先后端一块儿进行配置,使用,交流的平台,从上文看出,每次都特别麻烦,并且不直观,UI 不友好,怎么办呢?

    下一节咱们就使用一个神器 Swagger,一个快速,轻量级的项目RESTFUL接口的文档在线自动生成+功能测试功能软件。

 

Github && Gitee

https://github.com/anjoy8/Blog.Core.git

 

NOTE

如何不会使用Git,能够参考

https://www.jianshu.com/p/2b666a08a3b5