Web API-添加Swagger,SQL Server,记录并导出到Excel

1124 篇文章 54 订阅
634 篇文章 16 订阅

目录

介绍

要求

1.创建一个新的Web API项目

2.将Swagger添加到项目

3.将项目连接到SQL Server数据库

4.登录到SQL Server

5.添加“导出到Excel”

总结


介绍

2016年发布以来,ASP.NET Core取得了惊人的进展,而且每个版本似乎都变得更好,更友好且对开发人员更友好。

Web API是对旧的WCF服务的巨大改进(我们甚至不谈论SOAP ...),并且那里有大量的入门资源。本文只是重新编写轮子而已,它只是您要做的以下步骤的备忘单

  1. 创建一个新的Web API项目
  2. Swagger添加到您的项目
  3. 将项目连接到SQL Server数据库
  4. 将日志添加到项目中,以便所有异常或日志消息都保存在SQL Server表中(而不是转储到IIS .txt日志文件中的某个位置)
  5. CRUDE添加到您的项目。不,那不是错字。我们将拥有常规的Create-Read-Update-Delete函数,以及...只是为了展示它的简单性。我们将添加一个端点,使用Open XML库将数据导出到真实的.xlsx文件,仅此而已。

除了第五项之外,这是我使用每个Web API都要执行的4个步骤,因此我认为最好尽可能快速,轻松地记录需要执行的步骤,我们有更多时间专注于完成实际工作!

现在,我已经提供了一个含有从本文的示例代码的MikesBank.zip文件,但我强烈建议你使用它。

Visual Studio 2017ASP.NET Core几乎每个月都在变化... 从零开始创建自己的项目并遵循这些说明是一个更好的主意,使用Microsoft在阅读本文时提供的任何新模板,而不是使用我提供的示例,在您读完本段时,该示例可能已经过时了一半。

祝您阅读愉快!

要求

要阅读本文,您将需要:

  • C#知识
  • Visual Studio 2017
  • 已安装.NET Core v2.2 SDK(或更高版本)
  • SQL Server Management Studio(或者您可以修改连接字符串,以指向您自己的数据库风格)

我建议您先按照以下说明更新 VS2017.NET Core的副本。在撰写本文时,我尝试导入一个VS2017很高兴接受的nuget软件包,但是随后抛出了很多编译错误,因为该nuget软件包比我的.NET Core版本更高,拒绝使用我的旧版本。

1.创建一个新的Web API项目

这个问题已经讨论了很多次了,我相信大家都知道该怎么做。

  1. 启动Visual Studio 2017,然后选择File\New\Project
  2. Visual C\ .NET Core下,选择“ASP.NET Core Web应用程序,并为您的项目命名(我的名字MikesBank),然后单击OK                   
  3. 在下一个屏幕上,确保已选择API,它是一个.NET Core应用程序,然后单击确定

Visual Studio 2017将为您创建一个基本的API项目,该项目将返回一些硬编码的数据。

如果您在Chrome中运行该项目,则会看到几项JSON数据。

但是,如果您仍在使用Internet Explorer,则可能会收到一条奇怪的消息,询问您是否要从本地主机打开或保存values.json19个字节)? ”是的,这是2019年,而他们仍在这样做。我不知道为什么

作为开发人员,您可以(并且应该)通过添加2010年开始的StackOverflow文章中描述的注册表项来解决此问题。这将使Internet Explorer实际上显示JSON数据,而不是困扰我们。

因此,我们现在有了Web API的起点。现在,让我们变得更好!

2.Swagger添加到项目

考虑到Visual Studio对开发人员的友好程度,当我们告诉我们正在创建Web API项目时,没有提供为我的API创建Swagger页面作为选项,我总是感到惊讶。但是,添加起来很容易。

要将Swagger添加到您的项目中:

1、右键单击您的项目名称,然后选择管理NuGet软件包... ”

2、点击浏览标签,然后搜索并安装swashbuckle.aspnetcore

3、现在,您可以关闭此“nuget软件包管理器屏幕。

4、打开startup.cs ”文件,并对Configure()函数进行以下更改:

app.UseSwagger();

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json","MikesBank API");
    c.RoutePrefix = string.Empty;
});

5、请注意,该RoutePrefix...将使Swagger页面成为默认页面。因此,当我调试时,URL指向根路径时,将显示Swagger页面,例如:

https://localhost:44350/

6、接下来,我将简单的修改构造函数,并添加一个新的env变量:

public Startup(IHostingEnvironment env, IConfiguration configuration)
{
    Configuration = configuration;
    this.env = env;
}

private IHostingEnvironment env { get; }

有了这个,我们可以对ConfigureServices()函数进行更改:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    var pathIncludeXmlComments = $@"{env.ContentRootPath}\{env.ApplicationName}.xml";
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
        {
            Version = "v1",
            Title = "MikesBank API",
            Description = "For CodeProject"
        });

        if (System.IO.File.Exists(pathIncludeXmlComments))
            c.IncludeXmlComments(pathIncludeXmlComments);
    });
}

这有点臃肿,但是可以解决Swagger的问题。在我们的Web API控制器中添加注释通常很有用,Swagger会在其网页中显示这些注释。但是,如果.XML文件不存在,它会完全崩溃我们的应用程序,所以我非常小心,如果这仅包括注释.xml文件不存在。

7、代码更改都已完成,但是现在,我们只需要对项目设置进行一些更改。再次右键单击您的项目名称,然后选择属性。然后,选择构建选项卡。

8、在错误和警告部分,将“ ;1591” 添加到要忽略的警告列表中。如果我们选择在Web API控制器中添加注释,那就太好了!但是,如果我们还没有添加注释,我不喜欢Visual Studio为我们的代码添加下划线。这不是错误/警告,因此我忽略此警告以忽略此类警告。

1701;1702;1591

9、仍在此屏幕上的输出部分中,选中XML文档文件:” 框。

10、现在,跳至调试选项卡,然后从启动浏览器textbox中删除api/values” ,使其保持空白。

如果现在运行项目,您将看到Swagger网站,以及VS2017为我们创建的示例端点的列表。

看起来不错!如果要运行简单的获取所有值功能,则可以单击第一GET行,单击试用 ”按钮,然后单击执行 ”按钮,然后将看到带有两个内容的像以前一样使用硬编码的值的响应正文。

好的,它不像PostmanFiddler那样复杂,但是它是免费的,友好的并且非常有用。

使Swagger在此页面上包含注释就像在端点上方添加summaryremarks段一样简单:

/// <summary>
/// This is the Summary, describing the endpoint
/// </summary>
/// <remarks>
/// These are the Remarks for the endpoint
/// </remarks>
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
    return new string[] { "value1", "value2" };
}

请记住,Swagger本身确实会定期更新,并且在您阅读本文时(或者再次)更新一次,或者,如果您在搜索Swagger代码没有构建/显示时遇到的问题,请查看最新的文档。

3.将项目连接到SQL Server数据库

好的,现在让我们将Web API链接到SQL Server数据库。为此,请再次进入“nuget软件包管理器,搜索并安装以下三个软件包:

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.EntityFrameworkCore.SqlServer.Design

如果您更喜欢剪切而不是搜索,那么另一种方法是单击工具\Nuget软件包管理器\软件包管理器控制台,然后运行以下3个命令:

install-package Microsoft.EntityFrameworkCore.SqlServer
install-package Microsoft.EntityFrameworkCore.Tools
install-package Microsoft.EntityFrameworkCore.SqlServer.Design

无论哪种方式,这都会添加连接到SQL Server所需的3个程序包。

现在,我更喜欢使用数据库优先方法,在该方法中,我已经有一个实时运行的数据库,然后将其链接到我的Web API。在这篇文章中,我已经创建了我的本地服务器上的SQL Server数据库称为Southwind,它包含四个表,LocationDepartmentEmployeeLogging

如果您想继续学习,我提供了一个Southwind.sql ”脚本,它将为您创建该数据库、表和数据。

实际上,我们可以使Visual Studio根据这些表的结构为我们创建类。为此,请打开软件包管理器控制台(单击工具\Nuget软件包管理器\软件包管理器控制台),然后输入以下命令,将您的数据库的连接字符串替换为我的连接字符串:

Scaffold-DbContext "Server=localhost;Database=Southwind;
Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

这将为我们神奇地创建一个SouthwindContext类,以及四个类,每个数据库表一个。请注意,如果需要,可以通过使用-Tables参数,然后列出表名称,来要求某些(但不是全部)数据库表为其创建类。

Scaffold-DbContext "Server=localhost;Database=Southwind;
Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer 
-OutputDir Models -Tables "Course","Lesson","User"

另请注意,如果您的代码当前未事先成功构建,则此Scaffold-DbContext命令将不起作用。因此,在运行该命令之前,请检查您的代码是否可以正常构建。

您可以在此处查看其他选项。

接下来,我们需要告知我们的appsettings.json文件有关数据库连接的信息,因此请打开此文件,并将其添加到顶部:

"ConnectionStrings": {
  "SouthwindDatabase": "Server=.;Database=Southwind;Trusted_Connection=True;"
},

现在,打开startup.cs,并将其添加到ConfigureServices()函数中:

var ConnectionString = Configuration.GetConnectionString("SouthwindDatabase");
services.AddDbContext<SouthwindContext>(options =>
    options.UseSqlServer(ConnectionString)
);

在继续之前,我们需要确保此代码成功构建,但是现在,由于缺少两个using语句,因此它不会。您可以在Startup.cs顶部手动添加它们:

using Microsoft.EntityFrameworkCore;
using MikesBank.Models;

...或者您可以在上面的代码中单击SouthwindContextUseSqlServer,然后使用“CTRL” +“.”使Visual Studio 为您添加using语句。

如果您尝试再次构建,则它现在应该可以成功构建,我们可以继续。

现在,我们具有将数据库CRUD操作添加到Web API的所有构造块。

删除Controllers文件夹中的ValuesController.cs文件,然后右键单击Controllers文件夹,选择添加\控制器,选择最后一个选项使用实体框架进行操作的API控制器,然后单击添加

现在,您可以选择一个模型,并获取Visual Studio为您创建一组端点。我将选择Employee模型:

然后,单击添加按钮,就这样,我们为其中一个表设置了一组CRUD端点。

我们甚至可以进入控制器文件(在我的示例中为EmployeeController.cs),并修改注释,以使其对Swagger更友好。只需删除现有注释,然后将光标放在[HttpGet]上方的空白行上,键入///Visual Studio将为您提供占位符以键入您的注释。

/// <summary>
/// Load a list of all employee records from the database
/// </summary>
/// <returns>
/// An enumerable list of Employee records
/// </returns>
[HttpGet]
public async Task<ActionResult<IEnumerable<Employee>>> GetEmployee()
{
  return await _context.Employee.ToListAsync();
}

如果我们现在运行项目,将显示Swagger页面,我们可以为Employees端点选择的GET,并获取所有employees列表。

在这一点上,我(个人)会做一个小小的改变:通常情况下,当我得到Employee记录的列表,我不希望包括每条记录的整个层次(其中每个employee属于哪个department,并且这个department所在的location),我只想要Employee记录,仅此而已。

您可以通过打开Employee.cs文件并在virtual字段之前添加[JsonIgnore]来防止序列化整个层次结构(您还需要使用CTRL +“.”技巧来获取Visual Studio为此添加一条using语句)

[JsonIgnore]
public virtual Department Dep { get; set; }
[JsonIgnore]
public virtual Employee EmpManager { get; set; }
[JsonIgnore]
public virtual ICollection<Employee> InverseEmpManager { get; set; }

您还可以更改Startup.csAddMvc()设置,以防止JSON.Net在获取每个Employee记录的太多父/所有者时有点失控:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .AddJsonOptions(
        options => options.SerializerSettings.ReferenceLoopHandling = 
                               Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );

进行此更改后,我仅收到Employee记录列表,仅此而已。

这就是我们使Web API连接到SQL Server数据库以及向SQL Server数据库读取/写入数据的方式。我很乐意为此效劳,但是正如您所看到的,Visual Studio为我们做了(几乎)所有工作。我们只需要记住要采取的步骤。

4.登录到SQL Server

现在,当发生错误/异常时,我真的不喜欢它,并且错误字符串只是进入存储在IIS服务器上某个位置的一些随机.txt文件。将消息发送到SQL Server上的Logging表要有用得多,因此我们可以跟踪此类问题,也许可以在日志查看器 ”屏幕上列出这些问题,以供管理员跟踪,保存堆栈跟踪等等。

当然,有一个陷阱:如果由于无法连接数据库而引发了异常,那么……好吧……肯定不会将异常消息存储在数据库中,因为它找不到!

当然,我们可以使用第三方(例如nLog)来处理日志,但是就我个人而言,我更喜欢自己做。

首先,如您所见,我的SQL Server数据库中有一个Logging表。

没有什么复杂的。的Log_Severity,(异常)Log_MessageLog_StackTrace字段将全部来自刚刚发生的任何异常,我有一个Log_Source字段,我们可以填充该字段来说明应用程序的哪个区域引发了异常。

哦,我的Update_Time字段(我的每个表中都有一个)始终包含UTC timezone中的日期时间。我们很可能在不同国家/地区拥有用户,他们希望在当地时间知道何时发生异常。

要在我们的代码中使用此(或任何其他)表结构,这是我们需要做的。

  1. 在我们的项目中创建一个名为LogProvider的新文件夹。
  2. 我提供了一个LogProvider.zip文件,将.zip文件中的4个文件解压缩到该文件夹​​中。
  3. 在这些文件的每个文件中,命名空间当前设置为MikesBank.LogProvider。您将需要将其更改为自己的命名空间(取决于您为项目命名的名称)。
  4. SqlHelper.csDBLogger.cs 文件中,特定于我的Logging数据库表的代码。如果表具有不同的名称或字段,则需要更改此代码。
  5. Startup.cs,添加行using MikesBank.LogProvider;
  6. Configure()函数中,我们需要注入一个额外的依赖项:
public void Configure(IApplicationBuilder app, 
                     IHostingEnvironment env, ILoggerFactory loggerFactory)

现在,我们可以在Configure()函数中添加以下几行:

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
//  The following "AddContext" comes from our DBLoggerExtensions class.
//  We will log any errors of Information of higher. 
//  (Trace=0, Debug=1, Information=2, Warning=3, Error=4, Critical=5, None=6)
loggerFactory.AddContext(LogLevel.Information, 
             Configuration.GetConnectionString("SouthwindDatabase"));

此时,如果您尝试构建项目,则可能会收到一条错误消息,说ILoggerFactory中不包含AddContext” 的定义。要解决此问题,我们需要告诉它扩展方法在哪里。在Startup.cs的顶部,添加以下行:

using MikesBank.LogProvider;

现在,让我们开始吧。

现在,在EmployeesController.cs,可以添加日志记录。为此,我需要添加一个新变量:

private readonly ILogger logger;

以及新的using声明...

using Microsoft.Extensions.Logging;

然后,我可以修改构造函数:

public EmployeesController(SouthwindContext context, ILoggerFactory loggerFactory)
{
    _context = context;
    logger = loggerFactory.CreateLogger<EmployeesController>();
}

就是这样!

现在,您可以高兴地滑动是尽可能多的LogInformationLogWarningLogErrors。例如:

[HttpGet]
public async Task<ActionResult<IEnumerable<Employee>>> GetEmployee()
{
    logger.LogInformation("Loading a list of Employee records");
    return await _context.Employee.ToListAsync();
}

不过,这只是一个恼人的问题。运行此代码,并调用GET端点之后,我确实在Logging中收到了员工记录的加载列表消息,但我也从幕后获得了大量消息。就个人而言,我发现这些内容使查找我真正感兴趣的Log消息变得异常困难,并且希望将其关闭。

为此,您可以进入appsettings.Development.json文件,并修改MicrosoftSystem库中将包括的日志消息类型。如果将它们更改为Warning,则您的日志将不会填满所有这些额外的Entity Framework消息。

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Warning",
      "Microsoft": "Warning"
    }
  }
}

显然,这是可选的,也许您会希望在开发版本中看到这些详细信息。由你决定。

最后一件事。

我对某些API的最大烦恼之一是可怕的“HTTP响应500:内部服务器错误。当您自己的API抛出此异常时,通常是因为出了点问题,您的代码也没有费心去解决问题或优雅地处理它。

而且,当然,因为您还没有捕获到异常,所以您当然不会尝试将其发送到日志,以便您的开发人员和支持团队可以调查原因。因此,请将每个端点包装在try...catch中,并确保所有异常消息最终出现在Logging表中。

这很容易做到,但是以后会少掉很多头发。

public async Task<ActionResult<IEnumerable<Employee>>> GetEmployee()
{
    try
    {
        logger.LogInformation("Loading a list of Employee records");
        return await _context.Employee.ToListAsync();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "An exception occurred in the GetEmployee() endpoint");
        return new BadRequestObjectResult(ex.Message);
    }
}

显然,在生产版本中,您可能不希望如上所述返回完整的异常消息,并且可以根据需要进行修改。

5.添加导出到Excel”

是的,我知道...很可能,我们没人会添加Web API端点,该端点返回一个原始Excel文件,其中包含来自一个表的所有数据。但是,我们已经走了这么远,并且因为它是如此的简单,所以让我们看看我们将如何做到。如果没有其他要求,这对您的其他ASP.NET Core项目也很有用。

首先,我们需要最后一次进入“NuGet软件包管理器,并安装DocumentFormat.OpenXml软件包。即使我们的服务器上没有Excel,这也使我们可以创建Excel文件(* .xlsx)。

接下来,在您的项目中创建一个名为Helpers的文件夹,并将附加的CreateExcelFile.cs保存到该文件夹​​中。

有了此文件后,我们就可以开始了。

将导出端点添加到控制器的操作非常简单,只需加载数据,然后调用StreamExcelDocument函数,将要导出的数据和要使用的文件名传递给它即可:

[HttpGet("ExportToExcel")]
public async Task<IActionResult> ExportEmployeesToExcel()
{
    try
    {
        List<Employee> employees = await _context.Employee.ToListAsync();
        FileStreamResult fr = ExportToExcel.CreateExcelFile.StreamExcelDocument
                             (employees, "Employees.xlsx");
        return fr;
    }
    catch (Exception ex)
    {
        return new BadRequestObjectResult(ex);
    }
}

多么简单!

作为一个在金融行业工作过的人,让我告诉你,拥有一个简单的、可重用的导出到Excel”功能是非常棒的。这是我的客户要求的第一个功能,每次……他们喜欢自己的Excel

总结

就是这样!

现在,我们有了一个不错的ASP.NET Core Web API项目,它具有友好的Swagger页面,SQL Server连接和日志记录。如果我们真的想在下一次工作面试中留下深刻的印象,并且能够告诉他们您的API支持“CRUDE” ,那么还可以加上导出到Excel ”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值