在本章节,我们将着重介绍,如果搭建一个基于“.Net Core 3.1 WebAPI+EntityFrameWork+数据库”的应用程序
首先,我们需要.Net Core 3.1 WebAPI的应用程序
所需要的工具:
.Net Core 3.1运行开发环境
Visual Studio 2019
MySql 数据库或SqlServe数据库
创建空白解决方案
打开Visual Studio 2019 ->创建新项目,搜索“空白解决方案”,输入要搭建的服务名称,一般为“MYun.BPC.WebAPI.XXX”,如:
MYun.BPC.WebAPI.Basic
创建完成后,打开解决方案,选中,右键->添加->新建解决方案文件架。现阶段我们需要新增2个文件夹
01_Host 用于存放站点
02_Server 业务逻辑类库
完成后,我们就可以添加站点了
创建Action和Query站点
选中01_Host文件架,右键->添加->新建项目,搜索“ASP.NET Core Web”,选中,点击“下一步”,输入项目名称,名称一般为“MYun.BPC.WebAPI.XXX.Action”和“MYun.BPC.WebAPI.XXX.Query”如:
MYun.BPC.WebAPI.Basic.Action 用于处理端提交的操作请求
MYun.BPC.WebAPI. Basic .Query 用于处理端提交的查询请求
点击创建。这时,我们选中框架为“ASP.Net Core 3.1”,应用程序为“API”,Https配置关闭
创建完成后,效果如下:
到此,WabAPI站点创建完成,接下来,我们需要添加下面几个引用库,用来支持我们的站点
MYun.MY.Contract.Data.dll 契约类库,由类库Contract项目编译生成,用于承载返回的对象
Service.dll 框架类库, 由类库 Contract 项目编译生成,用于承载返回对象的基类
此外,我们还需要在NuGet添加
Newtonsoft.Json
的包。用来支持Json对象的序列化
右键单击“解决方案资源管理器” -> “管理 NuGet 包”中的项目
将“包源”设置为“nuget.org”
在搜索框中输入“Newtonsoft.Json”
从“浏览”选项卡中选择“Newtonsoft.Json”包,然后单击“安装”
当前版本为“12.0.3”
为站点生成说明文档
在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者的心情。或者详细点,或者简单点。那么有没有一种快速有效的方法来构建api说明文档呢?答案是肯定的, Swagger 就是最受欢迎的REST APIs文档生成工具之一!
为什么使用Swagger作为REST APIs文档生成工具
Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API。
Swagger 可以生成客户端SDK代码用于各种不同的平台上的实现。
Swagger 文件可以在许多不同的平台上从代码注释中自动生成。
Swagger 有一个强大的社区,里面有许多强悍的贡献者。
asp.net core中如何使用Swagger生成api说明文档呢
Swashbuckle.AspNetCore 是一个开源项目,用于生成 ASP.NET Core Web API 的 Swagger 文档。
NSwag 是另一个用于将 Swagger UI 或 ReDoc 集成到 ASP.NET Core Web API 中的开源项目。 它提供了为 API 生成 C# 和 TypeScript 客户端代码的方法。
下面以Swashbuckle.AspNetCore为例为大家进行展示
右键单击选中站点 -> “管理 NuGet 包”中的项目
将“包源”设置为“nuget.org”
在搜索框中输入“Swashbuckle.AspNetCore”
从“浏览”选项卡中选择“Swashbuckle.AspNetCore”包,然后单击“安装”
当前版本为“5.6.1”
Action和Query两个站点都安装完毕后,我们再右键选中这些站点->属性->生成
XML文档文件,勾选,指定路径bin\Debug\netcoreapp3.1\MYun.BPC.WebAPI.Basic.XXX.xml
如:
bin\Debug\netcoreapp3.1\MYun.BPC.WebAPI.Basic.Query.xml
bin\Debug\netcoreapp3.1\MYun.BPC.WebAPI.Basic.Action.xml
最后,我们打开项目里的Startup.cs 文件,新增引用命名空间
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Swagger;
using System.IO;
找到ConfigureServices方法。里面添加如下代码
services . AddSwaggerGen ( c =>
{
c . SwaggerDoc ( " v1 " , new OpenApiInfo
{
Version = " v1 " , //接口文档版本
Title = " Myun .NetCore BascQuery API " , //接口文档标题
Description = " 基础模块BaseQuery " , //描述,不同模块自己设计
}) ;
// 为 Swagger JSON and UI设置xml文档注释路径
var basePath = Path . GetDirectoryName ( typeof ( Program ). Assembly . Location ) ; //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
var ServicexmlPath = Path . Combine ( basePath , " Service.xml " ) ; //此为框架契约说明文档
c . IncludeXmlComments ( ServicexmlPath ) ;
var DataxmlPath = Path . Combine ( basePath , " MYun.MY.Contract.Data.xml " ) ; //此为返回对象说明文档
c . IncludeXmlComments ( DataxmlPath ) ;
var xmlPath = Path . Combine ( basePath , " MYun.BPC.WebAPI.Basic.Query.xml " ) ; //此为当前站点说明文档,Query或Action按不同站点具体配置
c . IncludeXmlComments ( xmlPath ) ;
}) ;
找到Configure方法。里面添加如下代码
//启用中间件服务生成Swagger作为JSON终结点
app . UseSwagger () ;
//启用中间件服务对swagger-ui,指定Swagger JSON终结点
app . UseSwaggerUI ( c =>
{
c . SwaggerEndpoint ( " /swagger/v1/swagger.json " , " Myun .NetCore BascQuery API " ) ;
}) ;
最终效果如下
using System ;
using System . Collections . Generic ;
using System . Linq ;
using System . Threading . Tasks ;
using Microsoft . AspNetCore . Builder ;
using Microsoft . AspNetCore . Hosting ;
using Microsoft . AspNetCore . Mvc ;
using Microsoft . Extensions . Configuration ;
using Microsoft . Extensions . DependencyInjection ;
using Microsoft . Extensions . Hosting ;
using Microsoft . Extensions . Logging ;
using Microsoft . OpenApi . Models ;
using Swashbuckle . AspNetCore . Swagger ;
using System . IO ;
namespace MYun . BPC . WebAPI . Basic . Action
{
public class Startup
{
public Startup ( IConfiguration configuration )
{
Configuration = configuration ;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices ( IServiceCollection services )
{
services . AddControllers () ;
services . AddSwaggerGen ( c =>
{
c . SwaggerDoc ( " v1 " , new OpenApiInfo
{
Version = " v1 " , //接口文档版本
Title = " Myun .NetCore BascQuery API " , //接口文档标题
Description = " 基础模块BaseQuery " , //描述,不同模块自己设计
}) ;
// 为 Swagger JSON and UI设置xml文档注释路径
var basePath = Path . GetDirectoryName ( typeof ( Program ). Assembly . Location ) ; //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
var ServicexmlPath = Path . Combine ( basePath , " Service.xml " ) ; //此为框架契约说明文档
c . IncludeXmlComments ( ServicexmlPath ) ;
var DataxmlPath = Path . Combine ( basePath , " MYun.MY.Contract.Data.xml " ) ; //此为返回对象说明文档
c . IncludeXmlComments ( DataxmlPath ) ;
var xmlPath = Path . Combine ( basePath , " MYun.BPC.WebAPI.Basic.Query.xml " ) ; //此为当前站点说明文档,Query或Action按不同站点具体配置
c . IncludeXmlComments ( xmlPath ) ;
}) ;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure ( IApplicationBuilder app , IWebHostEnvironment env )
{
if ( env . IsDevelopment ())
{
app . UseDeveloperExceptionPage () ;
}
app . UseRouting () ;
app . UseAuthorization () ;
app . UseEndpoints ( endpoints =>
{
endpoints . MapControllers () ;
}) ;
//启用中间件服务生成Swagger作为JSON终结点
app . UseSwagger () ;
//启用中间件服务对swagger-ui,指定Swagger JSON终结点
app . UseSwaggerUI ( c =>
{
c . SwaggerEndpoint ( " /swagger/v1/swagger.json " , " Myun .NetCore BascQuery API " ) ;
}) ;
}
}
}
到此,文档自动生成工具配置完成,我们现在试试效果。
我们打开项目自动生成的控制器WeatherForecastController文件和WeatherForecast文件,将各个方放加上备注说明,如下
接下来,我们右键站点->属性->调试,将“启动浏览器”修改为“swagger/index.html ”
保存后,点击调试“运行”。然后打开站点 http://localhost:port/swagger/index.html 看下效果。发现描述字段都已经出来了
注:为了方便后期维护和节约文档撰写时间,所有.NET Core项目的公共可见类和成员,必须要有描述,如果不描述,则编译的时候会产生警告。
统一时间格式
指定当前项目时间格式统一为文本。24小时制“yyyy-MM-dd HH:mm:ss”,选中站点->添加->新增项->类,添加一个DatetimeJsonConverter 类
using System ;
using System . Collections . Generic ;
using System . Linq ;
using System . Text . Json ;
using System . Text . Json . Serialization ;
using System . Threading . Tasks ;
namespace MYun . BPC . WebAPI . Basic . Action
{
public class DatetimeJsonConverter : JsonConverter < DateTime >
{
/// <summary>
/// 读
/// </summary>
/// <param name = " reader " ></param>
/// <param name = " typeToConvert " ></param>
/// <param name = " options " ></param>
/// <returns></returns>
public override DateTime Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
{
if ( reader . TokenType == JsonTokenType . String )
{
if ( DateTime . TryParse ( reader . GetString (), out DateTime date ))
return date ;
}
return reader . GetDateTime () ;
}
/// <summary>
/// 写
/// </summary>
/// <param name = " writer " ></param>
/// <param name = " value " ></param>
/// <param name = " options " ></param>
public override void Write ( Utf8JsonWriter writer , DateTime value , JsonSerializerOptions options )
{
writer . WriteStringValue ( value . ToString ( " yyyy-MM-dd HH:mm:ss " )) ;
}
}
}
打开Startup.cs 找到ConfigureServices方法,添加一条记录
services . AddMvc (). AddJsonOptions (( options ) =>
{
options . JsonSerializerOptions . Converters . Add ( new DatetimeJsonConverter ()) ;
options . JsonSerializerOptions . Encoder = JavaScriptEncoder . Create ( UnicodeRanges . All ) ;
options . JsonSerializerOptions . PropertyNamingPolicy = null;
}) ;
最终效果如下
public void ConfigureServices ( IServiceCollection services )
{
services . AddControllers () ;
services . AddMvc (). AddJsonOptions (( options ) =>
{
options . JsonSerializerOptions . Converters . Add ( new DatetimeJsonConverter ()) ;
options . JsonSerializerOptions . Encoder = JavaScriptEncoder . Create ( UnicodeRanges . All ) ;
options . JsonSerializerOptions . PropertyNamingPolicy = null;
}) ;
services . AddSwaggerGen ( c =>
{
c . SwaggerDoc ( " v1 " , new OpenApiInfo
{
Version = " v1 " , //接口文档版本
Title = " Myun .NetCore BascQuery API " , //接口文档标题
Description = " 基础模块BaseQuery " , //描述,不同模块自己设计
}) ;
// 为 Swagger JSON and UI设置xml文档注释路径
var basePath = Path . GetDirectoryName ( typeof ( Program ). Assembly . Location ) ; //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
var ServicexmlPath = Path . Combine ( basePath , " Service.xml " ) ; //此为框架契约说明文档
c . IncludeXmlComments ( ServicexmlPath ) ;
var DataxmlPath = Path . Combine ( basePath , " MYun.MY.Contract.Data.xml " ) ; //此为返回对象说明文档
c . IncludeXmlComments ( DataxmlPath ) ;
var xmlPath = Path . Combine ( basePath , " MYun.BPC.WebAPI.Basic.Action.xml " ) ; //此为当前站点说明文档,Query或Action按不同站点具体配置
c . IncludeXmlComments ( xmlPath ) ;
}) ;
}
这样,我们所有时间格式的输入输出,都统一为“yyyy-MM-dd HH:mm:ss”,我们用已有的WeatherForecastController控制器试试,发现时间结果都变了
指定标准接口和路由
查询请求
查询通用类库说明
QueryResponse 用来存放查询返回结果 基类
QueryRequest 用来存放查询请求 基类
查询路由指定”XXXQuery/[controller]/[action]”,如下:
[Route(“BasicQuery/[controller]/[action]”)]
创建一个新的查询控制器,举个例子
using System ;
using System . Collections . Generic ;
using System . Linq ;
using System . Threading . Tasks ;
using Microsoft . AspNetCore . Mvc ;
using Microsoft . Extensions . Logging ;
using Service ;
using MYun . MY . Contract . Data . Order ;
namespace MYun . BPC . WebAPI . Basic . Query . Controllers
{
[ ApiController ]
[ Route ( " BasicQuery/[controller]/[action] " )]
public class BasicController : ControllerBase
{
/// <summary>
/// 获取订单详情
/// </summary>
/// <param name = " param " ></param>
/// <returns></returns>
[ HttpPost ]
public QueryResponse < CPSOrder > GetOrderBySysNo ( QueryRequest < CPSOrderQuerySysNo > param )
{
QueryResponse < CPSOrder > result = new QueryResponse < CPSOrder >() ;
# region 检测param
if ( param == null )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = " GetLJChangeOrderBySysNo接口参数JSON对象不能为空 " } ;
return result ;
}
# endregion
try
{
# region 路由到Service
QueryResponse < CPSOrder > temp = new QueryResponse < CPSOrder >() { Body =new CPSOrder () { OrderSysNo = 111 , CreateTime = DateTime . Now } } ;
if ( temp . HasError )
{
result . HasError = true;
result . Fault = temp . Fault ;
}
else
{
result . Paging = temp . Paging ;
result . Body = temp . Body ;
}
return result ;
# endregion
}
catch ( Exception ex )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = ex . Message } ;
return result ;
}
}
/// <summary>
/// 获取订单列表
/// </summary>
/// <param name = " param " ></param>
/// <returns></returns>
[ HttpPost ]
public QueryResponse < List < CPSOrder >> GetOrderList ( QueryRequest < CPSOrderQuery > param )
{
QueryResponse < List < CPSOrder >> result = new QueryResponse < List < CPSOrder >>() ;
# region 检测param
if ( param == null )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = " GetLJOrderList接口参数JSON对象不能为空 " } ;
return result ;
}
# endregion
try
{
# region 路由到Service
QueryResponse < List < CPSOrder >> temp = new QueryResponse < List < CPSOrder >>() { Body =new List < CPSOrder > { new CPSOrder () { OrderSysNo = 222 , CreateTime = DateTime . Now } } } ;
if ( temp . HasError )
{
result . HasError = true;
result . Fault = temp . Fault ;
}
else
{
result . Paging = temp . Paging ;
result . Body = temp . Body ;
}
return result ;
# endregion
}
catch ( Exception ex )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = ex . Message } ;
return result ;
}
}
}
}
操作请求
操作 通用类库说明
ActionResponse 用来存放操作返回结果基类
ActionRequest 用来存放操作请求 基类
操作路由指定”XXXAction/[controller]/[action]”,如下:
[Route(“BasicAction/[controller]/[action]”)]
创建一个新的操作控制器,举个例子
using System ;
using System . Collections . Generic ;
using System . Linq ;
using System . Threading . Tasks ;
using Microsoft . AspNetCore . Mvc ;
using Microsoft . Extensions . Logging ;
using Service ;
using MYun . MY . Contract . Data . Order ;
namespace MYun . BPC . WebAPI . Basic . Action . Controllers
{
[ ApiController ]
[ Route ( " BasicAction/[controller]/[action] " )]
public class BasicController : ControllerBase
{
/// <summary>
/// 新增订单
/// </summary>
/// <param name = " param " ></param>
/// <returns></returns>
[ HttpPost ]
public ActionResponse < int > AddOrderCPS ( ActionRequest < OrderCPSAdd > param )
{
ActionResponse < int > result = new ActionResponse < int >() ;
# region 检测param
if ( param == null )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = " AddOrderRMA接口参数JSON对象不能为空 " } ;
return result ;
}
# endregion
try
{
# region 路由到Service
return new ActionResponse < int > { Body = 1 } ;
# endregion
}
catch ( Exception ex )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = ex . Message } ;
return result ;
}
}
/// <summary>
/// 编辑订单
/// </summary>
/// <param name = " param " ></param>
/// <returns></returns>
[ HttpPost ]
public ActionResponse EditOrderCPS ( ActionRequest < OrderCPSEdit > param )
{
ActionResponse result = new ActionResponse () ;
# region 检测param
if ( param == null )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = " EditOrderRMA接口参数JSON对象不能为空 " } ;
return result ;
}
# endregion
try
{
# region 路由到Service
return new ActionResponse () ;
# endregion
}
catch ( Exception ex )
{
result . HasError = true;
result . Fault = new MessageFault () { ErrorCode = 0 , ErrorDescription = ex . Message } ;
return result ;
}
}
}
}
创建业务处理层
新增一个02_Server文件夹用来处理业务逻辑。然后在文件夹下,右键->新建项目
MYun.BPC.WebAPI.XXX.Server文件结构如下
Service 用于承接接口请求
ActionBP用于处理操作逻辑
QueryBP用于处理查询逻辑
Help用于存放帮助类
Transform用于存放翻译类
添加NuGet包,包内有EntityFrameworkCore 等相关的引用,以及Newtonsoft.Json, EntityFrameworkCore等知识点,参考《.Net Core + EntityFramework连接数据库》
最后一步,添加相关项目程序集
然后将MYun.BPC.WebAPI.XXX.Query ,MYun.BPC.WebAPI.XXX.Action 这2个站点,引用MYun.BPC.WebAPI.XXX.Server 这个类库