Saturday, September 26, 2020

一文了解.Net Core 3.1 Web API基础知识

一、前言

  随着近几年前后端分离、微服务等模式的兴起,.Net Core也似有如火如荼之势 ,自16年发布第一个版本到19年底的3.1 LTS版本,以及将发布的.NET 5,.NET Core一路更迭,在部署和开发工具上也都支持了跨平台应用。一直对.Net Core有所关注,但未涉及太多实际应用,经过一番学习和了解后,于是分享出来。本文主要以.Net Core Web API为例,讲述.Net Core的基本应用及注意事项,对于想通过WebAPI搭建接口应用的开发者,应该能提供一个系统的轮廓和认识,同时和更多的.Net Core开发者交流互动,探本勘误,加强对知识的理解,并帮助更多的人。本文以贴近基本的实际操作为主,部分概念或基础步骤不再赘述,文中如有疏漏,还望不吝斧正。

二、Swagger调试Web API

开发环境:Visual Studio 2019

为解决前后端苦于接口文档与实际不一致、维护和更新文档的耗时费力等问题,swagger应运而生,同时也解决了接口测试问题。话不多说,直接说明应用步骤。

  1. 新建一个ASP.NET Core Web API应用程序,版本选择.ASP.NET Core 3.1;
  2. 通过Nuget安装包:Swashbuckle.AspNetCore,当前示例版本5.5.0;
  3. 在Startup类的ConfigureServices方法内添加以下注入代码:
    services.AddSwaggerGen(c =>   {    c.SwaggerDoc("v1", new OpenApiInfo    {     Title = "My API",     Version = "v1",     Description = "API文档描述",     Contact = new OpenApiContact     {      Email = "5007032@qq.com",      Name = "测试项目",      //Url = new Uri("")     },     License = new OpenApiLicense     {      Name = "BROOKE许可证",      //Url = new Uri("")     }    });       });

    Startup类的Configure方法添加如下代码:

    //配置Swagger   app.UseSwagger();      app.UseSwaggerUI(c =>   {    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");    c.RoutePrefix = "api";// 如果设为空,访问路径就是根域名/index.html,设置为空,表示直接在根域名访问;想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "swagger"; 则访问路径为 根域名/swagger/index.html   });

    Ctrl+F5进入浏览,按上述配置修改路径为 src="https://img2020.cnblogs.com/blog/23487/202009/23487-20200926103609678-1602760898.jpg" alt="" loading="lazy">

    然而到这里还没完,相关接口的注释说明我们看不到,通过配置
    services.AddSwaggerGen(c =>   {    c.SwaggerDoc("v1", new OpenApiInfo    {     Title = "My API",     Version = "v1",     Description = "API文档描述",     Contact = new OpenApiContact     {      Email = "5007032@qq.com",      Name = "测试项目",      //Url = new Uri("")     },     License = new OpenApiLicense     {      Name = "BROOKE许可证",      //Url = new Uri("")     }    });        var "{Assembly.GetExecutingAssembly().GetName().Name}.";    var  Path.Combine(AppContext.BaseDirectory,    });

    上述代码通过反射生成与Web API项目相匹配的然后右键Web API项目、属性、生成,配置


    这样,我们以三斜杠(///)方式给类方法属性等相关代码添加注释后,刷新Swagger页面,即可看到注释说明。
    如果不想将
    var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//获取应用程序所在目录var "CoreAPI_Demo.");c.Includetrue);

    同时,调整项目生成的

  4. 隐藏相关接口
    对于不想暴漏给Swagger展示的接口,我们可以给相关Controller或Action头加上:[ApiExplorerSettings(IgnoreApi = true)]

  5. 调整系统默认输出路径
    项目启动后,默认会访问自带的weatherforecast,如果想调整为其他路径,譬如打开后直接访问Swagger文档,那么调整Properties目录下的launchSettings.json文件,修改launchUrl值为api(前述配置的RoutePrefix值):
    { "$schema": "", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": {  "applicationUrl": "",  "sslPort": 0 } }, "profiles": { "IIS Express": {  "commandName": "IISExpress",  "launchBrowser": true,  "launchUrl": "api",  "environmentVariables": {  "ASPNETCORE_ENVIRONMENT": "Development"  } }, "CoreApi_Demo": {  "commandName": "Project",  "launchBrowser": true,  "launchUrl": "api",  "applicationUrl": "",  "environmentVariables": {  "ASPNETCORE_ENVIRONMENT": "Development"  } } }}

     

三、配置文件

以读取appsettings.json文件为例,当然你也定义其他名称的.json文件进行读取,读取方式一致,该文件类似于Web.config文件。为方便示例,定义appsettings.json文件内容如下:

{ "ConnString": "Data Source=(local);Initial Catalog=Demo;Persist Security Info=True;User ID=DemoUser;Password=123456;MultipleActiveResultSets=True;", "ConnectionStrings": { "MySQLConnection": "server=127.0.0.1;database=mydemo;uid=root;pwd=123456;charset=utf8;SslMode=None;" }, "SystemConfig": { "UploadFile": "/Files", "Domain": "" }, "JwtTokenConfig": { "Secret": "fcbfc8df1ee52ba127ab", "Issuer": "abc.com", "Audience": "Brooke.WebApi", "AccessExpiration": 30, "RefreshExpiration": 60 }, "Logging": { "LogLevel": {  "Default": "Information",  "Microsoft": "Warning",  "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*"}

 

1、配置文件的基本读取

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();   //读取方式一   var ConnString = Configuration["ConnString"];      var MySQLConnection = Configuration.GetSection("ConnectionStrings")["MySQLConnection"];   var UploadPath = Configuration.GetSection("SystemConfig")["UploadPath"];   var LogDefault = Configuration.GetSection("Logging").GetSection("LogLevel")["Default"];      //读取方式二   var ConnString2 = Configuration["ConnString"];   var MySQLConnection2 = Configuration["ConnectionStrings:MySQLConnection"];   var UploadPath2 = Configuration["SystemConfig:UploadPath"];   var LogDefault2 = Configuration["Logging:LogLevel:Default"];     }    }

以上介绍了2种读取配置信息的方式,如果要在Controller内使用,类似地,进行注入并调用如下:

public class ValuesController : ControllerBase {  private IConfiguration _configuration;  public ValuesController(IConfiguration configuration)  {   _configuration = configuration;  }  // GET: api/<ValuesController>  [HttpGet]  public IEnumerable<string> Get()  {   var ConnString = _configuration["ConnString"];   var MySQLConnection = _configuration.GetSection("ConnectionStrings")["MySQLConnection"];   var UploadPath = _configuration.GetSection("SystemConfig")["UploadPath"];   var LogDefault = _configuration.GetSection("Logging").GetSection("LogLevel")["Default"];   return new string[] { "value1", "value2" };  } }

 

2、读取配置文件到自定义对象

以SystemConfig节点为例,定义类如下:

public class SystemConfig {  public string UploadPath { get; set; }  public string Domain { get; set; }    }

调整代码如下:

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.Configure<SystemConfig>(Configuration.GetSection("SystemConfig"));  }    }

 然后Controller内进行注入调用:

[Route("api/[controller]/[action]")] [ApiController] public class ValuesController : ControllerBase {    private SystemConfig _sysConfig;  public ValuesController(IOptions<SystemConfig> sysConfig)  {      _sysConfig = sysConfig.Value;  }    [HttpGet]  public IEnumerable<string> GetSetting()  {   var UploadPath = _sysConfig.UploadPath;   var Domain = _sysConfig.Domain;   return new string[] { "value1", "value2" };  } }

3、绑定到静态类方式读取

定义相关静态类如下:

  public static class MySettings {  public static SystemConfig Setting { get; set; } = new SystemConfig(); } 

调整Startup类构造函数如下:

public Startup(IConfiguration configuration, IWebHostEnvironment env)  {      var builder = new ConfigurationBuilder()    .SetBasePath(env.ContentRootPath)    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);   Configuration = builder.Build();   //Configuration = configuration;   configuration.GetSection("SystemConfig").Bind(MySettings.Setting);//绑定静态配置类     }  

接下来,诸如直接使用:MySettings.Setting.UploadPath 即可调用。

 

四、文件上传

接口一般少不了文件上传,相比.net framework框架下webapi通过byte数组对象等复杂方式进行文件上传,.Net Core WebApi有了很大变化,其定义了新的IFormFile对象来接收上传文件,直接上Controller代码: 

后端代码

[Route("api/[controller]/[action]")] [ApiController] public class UploadController : ControllerBase {  private readonly IWebHostEnvironment _env;  public UploadController(IWebHostEnvironment env)  {   _env = env;  }  public ApiResult UploadFile(List<IFormFile> files)  {   ApiResult result = new ApiResult();
       //注:参数files对象去也可以通过换成: var files = Request.Form.Files;来获取
if (files.Count <= 0) { result.Message = "上传文件不能为空"; return result; } #region 上传 List<string> filenames = new List<string>(); var webRootPath = _env.WebRootPath; var rootFolder = MySettings.Setting.UploadPath; var physicalPath = $"{webRootPath}/{rootFolder}/"; if (!Directory.Exists(physicalPath)) { Directory.CreateDirectory(physicalPath); } foreach (var file in files) { var fileExtension = Path.GetExtension(file.FileName);//获取文件格式,拓展名 var saveName = $"{rootFolder}/{Path.GetRandomFileName()}{fileExtension}"; filenames.Add(saveName);//相对路径 var fileName = webRootPath + saveName; using FileStream fs = System.IO.File.Create(fileName); file.CopyTo(fs); fs.Flush(); }

No comments:

Post a Comment