时间:2021年05月12日 | 作者 : aaronyang | 分类 : .NET CORE | 浏览: 1029次 | 评论 0 人
打开第14章笔记的PracticalApps项目,我们用vs2019新建一个webapi
在vscode命令是 dotnet new webpi
新建后,默认会有个示例WeatherForecastController
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindService.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } } }
继承了ControllerBase,相比MVC的更简单,因为不会提供View那样的页面,还要Razor。
【Route】特性 用来注册weatherforecast相对URL,以便客户端使用该URL发出HTTP请求,这些HTTP请求将由控制器处理。例如地址栏:https://localhost:5001/weatherforecast/ 的http请求。一些开发人员喜欢前面加个api/,这是在混合项目区分mvc和web",如果输入[controller]就是当前类名,如果输入 [Route("api/forecast")] 就是 https://localhost:5001/api/forecast
运行后,默认swagger显示webapi的测试页面,方便调试
ASP.NET CORE2.1引入【ApiController】,支持Rest行为,比如针对无效模型自动HTTP 400响应。
HttpGet就是get请求,现在我们添加一个Get方法
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindService.Controllers { [ApiController] [Route("api/forecast")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } //Get /api/forecast [HttpGet] public IEnumerable<WeatherForecast> Get() { return Get(5); } //Get /api/forecast/7 [HttpGet("{days:int}")] public IEnumerable<WeatherForecast> Get(int days) { var rng = new Random(); return Enumerable.Range(1, days).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } } }
[HttpGet("{days:int}")]格式模式,days约束为int类型了。
运行后:
运行后,浏览器输入 https://localhost:44372/api/forecast/14
Web最常用的格式json,因为在使用Angular,vue,react,json更合适
NorthwindService项目添加NorthwindContextLib和NorthwindEntitesLib的引用
打开Startup.cs文件,添加AddDbContext
拷贝下数据库到webapi根目录,然后添加以下代码
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "NorthwindService", Version = "v1" }); }); string databasePath = System.IO.Path.Combine("Northwind.db"); services.AddDbContext<Northwind>(options => options.UseSqlite($"Data Source={databasePath}")); services.AddControllers(options => { Console.WriteLine("默认输出格式"); foreach (IOutputFormatter formatter in options.OutputFormatters) { var mediaFormat = formatter as OutputFormatter; if (mediaFormat == null) { Console.WriteLine($"{formatter.GetType().Name}"); } else { Console.WriteLine("{0},MediaType:{1}", mediaFormat.GetType().Name, String.Join(",", mediaFormat.SupportedMediaTypes)); } } }).AddXmlDataContractSerializerFormatters().AddXmlSerializerFormatters().SetCompatibilityVersion(CompatibilityVersion.Version_3_0); }
设置版本兼容性的好处,https://docs.microsoft.com/zh-cn/aspnet/core/mvc/compatibility-version?view=aspnetcore-3.0
启动web服务,注意四个默认的输出格式化程序,包括将null值转换为204 No Content的格式化程序以 支持纯文本和JSON响应的格式化程序。如下所示
缓存Redis:https://redis.io
现在我们要对客户增删改查
新建一个Repositories文件夹,新建ICustomerRepository
public interface ICustomerRepository { Task<Customer> CreateAsync(Customer c); Task<IEnumerable<Customer>> RetrieveAllAsync(); Task<Customer> RetrieveAsync(string id); Task<Customer> UpdateAsync(string id, Customer c); Task<bool?> DeleteAsync(string id); }
实现
public class CustomerRepository : ICustomerRepository { /// <summary> /// 线程安全的字典,缓存客户 /// </summary> private static ConcurrentDictionary<string, Customer> customersCache; private Northwind db; public CustomerRepository(Northwind db) { this.db = db; if (customersCache == null) { customersCache = new ConcurrentDictionary<string, Customer>(db.Customers.ToDictionary(c=>c.CustomerID)); } } public async Task<Customer> CreateAsync(Customer c) { c.CustomerID = c.CustomerID.ToUpper(); EntityEntry<Customer> added = await db.Customers.AddAsync(c); int affected = await db.SaveChangesAsync(); if (affected == 1) { return customersCache.AddOrUpdate(c.CustomerID, c, UpdateCache); } else { return null; } } public async Task<bool?> DeleteAsync(string id) { id = id.ToUpper(); var c = db.Customers.Find(id); if (c != null) { db.Customers.Remove(c); int affected = await db.SaveChangesAsync(); if (affected == 1) { return customersCache.TryRemove(id, out c); } else { return null; } } else { return null; } } public Task<IEnumerable<Customer>> RetrieveAllAsync() { return Task.Run<IEnumerable<Customer>>(()=> customersCache.Values); } public Task<Customer> RetrieveAsync(string id) { return Task.Run(() => { id = id.ToUpper(); customersCache.TryGetValue(id, out Customer c); return c; } ); } public Customer UpdateCache(string id,Customer c) { if(customersCache.TryGetValue(id,out Customer old)) { if (customersCache.TryUpdate(id, c, old)) { return c; } } return null; } public async Task<Customer> UpdateAsync(string id, Customer c) { id = id.ToUpper(); c.CustomerID = c.CustomerID.ToUpper(); db.Customers.Update(c); int affected = await db.SaveChangesAsync(); if (affected == 1) { return UpdateCache(id, c); } return null; }
HttpGet和HttpHead
HttpPost
HttpPut和HttpPatch
HttpDelete
操作方法返回.NET类型,如果注册了合适的序列化器,那么WebAPI会自动将它们序列化为HTTP请求的Accept标头中设置的请求数据格式。例如JSON。
要对响应进行更多控制,可以使用返回.NET类型的ActionResult包装器。
返回不同类型,返回IActionResult,如果返回单个类型,状态码不同,返回类型设置为ActionResult<T>
建议使用 [ProducesResponseType]特性装饰操作方法,指示客户端应该期望在响应中包含所有已知类型和HTTP状态码。然后可以公开这些信息,以记录客户端应该如何与Web服务交互。后面章节将介绍 安装代码分析器,以便在不像在这样装饰的操作方法时发出警告。
例如
[HttpGet("{id}")]
[ProducesResponseType(200,Type=typeof(Product))]
[ProducesResponseType(404)]
public IActionResult Get(string id)
Controllerbase类有些方法,可以很容易地返回类型
ok:返回HTTP200,其中包含客户端要的资源,通常Http Get
CreatedAtRoute:返回201,其中包含到新资源的路径。通常响应POST请求
Accepted:返回202,表明请求正在处理但尚未完成。通常用于响应对需要很长时间才能完成的后台进程的请求。
NoContentResult:返回204. 通常响应Http Put请求,以更新现有资源
BadRequest:返回带有可选消息字符串的HTTP 400状态码
NotFound:返回能够自动填充 ProblemDetails主体 HTTP 404状态码
打开startup.cs,在ConfigureServices方法注册接口和实现
services.AddScoped<ICustomerRepository, CustomerRepository>();
在Controller文件夹新建 CustomersController.cs
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using NorthwindEntitesLib; using NorthwindService.Repositories; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindService.Controllers { [ApiController] [Route("api/[controller]")] public class CustomersController : ControllerBase { private ICustomerRepository repo; public CustomersController(ICustomerRepository repo) { this.repo = repo; } [HttpGet] [ProducesResponseType(200, Type = typeof(IEnumerable<Customer>))] public async Task<IEnumerable<Customer>> GetCustomers(string country) { if (string.IsNullOrWhiteSpace(country)) { return await repo.RetrieveAllAsync(); } else { return (await repo.RetrieveAllAsync()).Where(customer => customer.Country == country); } } //GET api/customers/{id} [HttpGet("{id}", Name = nameof(GetCustomer))] [ProducesResponseType(200, Type = typeof(Customer))] [ProducesResponseType(404)] public async Task<IActionResult> GetCustomer(string id) { var c = await repo.RetrieveAsync(id); if (c == null) { return NotFound(); //404 } else { return Ok(c);//200 ok with in body } } //Post api/customers //body customer:{JSON,XML} [HttpPost] [ProducesResponseType(201, Type = typeof(Customer))] [ProducesResponseType(400)] public async Task<IActionResult> Create([FromBody] Customer c) { if (c == null) { return BadRequest(); } if (!ModelState.IsValid) { return BadRequest(ModelState); } var added = await repo.CreateAsync(c); return CreatedAtRoute(nameof(GetCustomer), new { id = added.CustomerID.ToLower() }, added); } //PUT api/customers/{id} //body customer:{JSON,XML} [HttpPut("{id}")] [ProducesResponseType(204)] [ProducesResponseType(400)] [ProducesResponseType(404)] public async Task<IActionResult> Update(string id,[FromBody] Customer c) { id = id.ToUpper(); c.CustomerID = c.CustomerID.ToUpper(); if(c==null || c.CustomerID != id) { return BadRequest(); //400 bad request } if (!ModelState.IsValid) { return BadRequest(ModelState); //400 bad request } var exist = await repo.RetrieveAsync(id); if (exist == null) { return NotFound(); //404 } await repo.UpdateAsync(id, c); return new NoContentResult();//2014 no content } [HttpDelete("{id}")] [ProducesResponseType(204)] [ProducesResponseType(400)] [ProducesResponseType(404)] public async Task<IActionResult> Delete(string id) { var ext = await repo.RetrieveAsync(id); if (ext == null) { return NotFound(); } var deleted = await repo.DeleteAsync(id); if(deleted.HasValue && deleted.Value) { return new NoContentResult(); } else { return BadRequest($"CustomerID为{id}存在,但是删除失败"); } } } }
更多信息:HTTP API问题细节的建议标准:https://tools.ietf.org/html/rfc7807
ProblemDetails类实现问题细节的更多信息:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.problemdetails
如果想获得控制权,那么可以创建ProblemDetails实例并包含其他信息。
在CustomersController类定义的顶部导入Microsoft.AspNetCore.Http名称
在Delete方法的顶部添加语句,检查id是否与bad匹配,如果匹配,就返回自定义的ProblemDetails对象
if (id == "bad") { var problemDetails = new ProblemDetails { Status = StatusCodes.Status400BadRequest, Type = "https://localhost:44372/customers/failed-to-delete", Title = $"Customer ID {id} found but failed to delete", Detail = "更多信息,比如公司名,国家名等等", Instance = HttpContext.Request.Path }; return BadRequest(problemDetails); }
启动服务后,打开浏览器,输入
https://localhost:44372/api/customers
https://localhost:44372/api/customers/?country=Germany
https://localhost:44372/api/customers/alfki
在vscode中,你安装swagger,在vs2019中创建项目就自带了。
在vscode中 安装Rest Client扩展Http请求
vscode中,命令中输入rest client,回车后,多个请求,使用###符号分隔
输入:
###
GET https://localhost:44372/api/customers/?country=Germany Http/1.1
###
GET https://localhost:44372/api/customers/?country=USA Http/1.1
###
GET https://localhost:44372/api/customers/?country=ALFKI Http/1.1
单击Send Request就可以了。
当然还是建议swagger或者 postman自己测试api
启用Swagger
在NorthwindService.csproj中
在Startup.cs中的ConfigureServices
可通过以下链接了解Swagger如何支持API的多个版本-
using System.Web.Http; namespace RESTServices.Controllers.v1 { [Route("api/v1/Test")] public class TestV1Controller : ApiController { ... }
.EnableSwagger(c => c.MultipleApiVersions( (apiDesc, version) => { var path = apiDesc.RelativePath.Split('/'); var pathVersion = path[1]; return CultureInfo.InvariantCulture.CompareInfo.IndexOf(pathVersion, version, CompareOptions.IgnoreCase) >= 0; }, vc => { vc.Version("v2", "Swashbuckle Dummy API V2"); //add this line when v2 is released // ReSharper disable once ConvertToLambdaExpression vc.Version("v1", "Swashbuckle Dummy API V1"); } ))
输入ALFKI,然后单击蓝色的Execute
结果可以看见,响应body和响应头信息
我们拷贝这个ResponseBody内容,方便下面的测试
=====www.ayjs.net==============
回到顶部,单击POST/api/Customers,展开端点,单击Try it out
输入下面的json
{ "customerID": "AY", "companyName": "AY的公司", "contactName": "杨洋", "contactTitle": "开发者", "address": "合肥市高新区", "city": "合肥", "region": null, "postalCode": "230000", "country": "China", "phone": "15255112222", "fax": "030-0226545", "orders": null }
单击Execute
返回201表示创建了客户
移动到顶部,单击 GET /api/Customers
执行后的结果,能查询到,说明插入成功了
单击DELETE /api/Customers/{id} 展开节点,单击try it out,输入 AY,单击执行,返回204表示删除成功
再次单击一次,由于数据不在了,所以返回404
输入bad,单击execute,返回自定义的详情错误信息
使用HttpClient类从任何.NET Core应用程序中调用Northwind服务
Net Core2.1引入了HttpClientFactory
如何启动Http请求: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests
下面示例使用NorthwindMvc网站作为Web服务的客户端。因为两者都需要在Web服务器上托管。先配置不同端口号。
API使用htpps使用5001,MVC的http使用5000,https使用5002
解决方案 添加第16章的NorthwindMvc项目
打开Program.cs,修改地址
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindMvc { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder.UseUrls("http://localhost:5000", "https://localhost:5002"); }); } }
打开Startup.cs 在ConfigureServices添加一条语句,使指定了客户端的HttpClientFactory能够使用HTTPS(用于端口5001)调用Northwind Web API服务,并请求JSON作为默认响应格式,如下:
services.AddHttpClient("NorthwindService",options=> { options.BaseAddress = new Uri("https://localhost:5001"); options.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json",1.0)); });
打开Controllers/HomeController.cs
添加IHttpClientFactory相关代码,并且创建新的操作方法Customers
private readonly ILogger<HomeController> _logger; private readonly IHttpClientFactory clientFactory; private Northwind db; public HomeController(ILogger<HomeController> logger, Northwind injectedContext,IHttpClientFactory httpClientFactory) { _logger = logger; db = injectedContext; clientFactory = httpClientFactory; } public async Task<IActionResult> Customers(string country) { string uri; if (string.IsNullOrWhiteSpace(country)) { ViewData["Title"] = "所有客户"; uri = "api/customers"; } else { ViewData["Title"] = $"{country} 的客户"; uri = $"api/customers/?country={country}"; } var client = clientFactory.CreateClient("NorthwindService"); var req = new HttpRequestMessage(HttpMethod.Get,uri); HttpResponseMessage res = await client.SendAsync(req); string jsonString = await res.Content.ReadAsStringAsync(); IEnumerable<Customer> model = JsonConvert.DeserializeObject<IEnumerable<Customer>>(jsonString); return View(model); }
在Views/Home文件夹中创建一个名为Customers.cshtmpl的Razor文件
@using NorthwindEntitesLib; @model IEnumerable<Customer> <h2>@ViewData["Title"]</h2> <table class="table"> <tr> <th>公司名字</th> <th>联系人名字</th> <th>地址</th> <th>电话</th> </tr> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(m=>item.CompanyName)</td> <td>@Html.DisplayFor(m => item.ContactName)</td> <td> @Html.DisplayFor(m => item.Address) @Html.DisplayFor(m => item.City) @Html.DisplayFor(m => item.Region) @Html.DisplayFor(m => item.Country) @Html.DisplayFor(m => item.PostalCode) </td> <td> @Html.DisplayFor(m => item.Phone)</td> </tr> } </table>
打开Home/Index.cshtml增加一个链接,打开Customer页面
<form asp-action="Customers" method="get"> <input placeholder="输入国家名" name="country" /> <input type="submit" /> </form>
由于mvc和api不是一个端口号,所以存在跨源资源共享的问题。
启用CORS来允许来自指定域的请求
https://docs.microsoft.com/zh-cn/aspnet/core/security/cors
在NorthwindService项目中打开Program.cs
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindService { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder.UseUrls("https://localhost:5001"); }); } }
指定5001端口号,并且在Startup.cs中允许
services.AddCors();
然后Configure方法添加一条语句使用cors,并允许来自任何网站(如https://localhost:5002) HTTP get put post delete请求
app.UseCors(options => { options.WithMethods("GET", "POST", "PUT", "DELETE"); options.WithOrigins("https://localhost:5002"); });
启动项目,测试,先启动NorthwindService
右键NorthwindService项目,选择“在终端打开” 输入 dotnet run
右键NorthwindMvc项目,选择“在终端打开” 输入 dotnet run
浏览器地址栏输入:https://localhost:5002/
如果输入http://localhost:5000/ 会自动跳到 https://localhost:5002/这个地址
输入Germany,点击提交
会出现这个错误,先不管了
健康检查API
打开NorthwindService 安装以下这个Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
安装过后
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <UserSecretsId>0ea0d690-19a9-45a1-b23b-6f3331e0fd72</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="5.0.6" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\NorthwindContextLib\NorthwindContextLib.csproj" /> <ProjectReference Include="..\NorthwindEntitesLib\NorthwindEntitesLib.csproj" /> </ItemGroup> <ItemGroup> <None Update="Northwind.db"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
然后我们在Startup.cs的ConfigureServices添加一句代码,支持健康检查。
services.AddHealthChecks().AddDbContextCheck<Northwind>(); //默认情况下,数据库上下文检查调用EF Core的CanConnectAsync方法。添加完了,然后在Configure使用
Configure中使用
app.UseHealthChecks("/ayhealthcheck");
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using NorthwindContextLib; using NorthwindService.Repositories; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace NorthwindService { 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 { Title = "NorthwindService", Version = "v1" }); }); string databasePath = System.IO.Path.Combine("Northwind.db"); services.AddDbContext<Northwind>(options => options.UseSqlite($"Data Source={databasePath}")); services.AddControllers(options => { Console.WriteLine("默认输出格式"); foreach (IOutputFormatter formatter in options.OutputFormatters) { var mediaFormat = formatter as OutputFormatter; if (mediaFormat == null) { Console.WriteLine($"{formatter.GetType().Name}"); } else { Console.WriteLine("{0},MediaType:{1}", mediaFormat.GetType().Name, String.Join(",", mediaFormat.SupportedMediaTypes)); } } }).AddXmlDataContractSerializerFormatters().AddXmlSerializerFormatters().SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddScoped<ICustomerRepository, CustomerRepository>(); services.AddCors(); services.AddHealthChecks().AddDbContextCheck<Northwind>(); //默认情况下,数据库上下文检查调用EF Core的CanConnectAsync方法。添加完了,然后在Configure使用 } // 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.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NorthwindService v1")); } app.UseCors(options => { options.WithMethods("GET", "POST", "PUT", "DELETE"); options.WithOrigins("https://localhost:5002"); }); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseHealthChecks("/ayhealthcheck"); } } }
启动项目,打开浏览器测试,输入https://localhost:5001/ayhealthcheck
可以根据需要扩展健康检查响应
https://blogs.msdn.microsoft.com/webdev/2018/08/22/asp-net-core-2-2-0-preview1-healthcheck/
本章介绍了如何使用特性手动装饰控制器类,从而使Swagger能够记录Web服务。
在NC2.2以上版本,一些API分析器可以反映控制器类的情况,有些类已经用[ApiController]特性注解以方便记录。分析器往往会采用一些API约定。
安装
端点路由需要对app.UseRouting()和app.UseEndpoints();
app.UseRouting() 用于标记进行路由决策的管道位置
app.UseEndpoints()用于标记所选端点执行的管道位置
端点路由使用路由模板语法与AspNet MVC使用的相同。并且使用AspNet Mvc5引入的Route特性。
MVC控制器 Razor Pages和SignalR之类的框架过去通常是通过调用UseMvc()或类似的方法启用的,但现在它们已被添加到UseEndpoint()中,他们都与中间件一起被集成到同一路由系统中。
在NorthwindService项目Startup.cs的Configure方法中的 UseEndpoints之前添加一条语句。
引入
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
app.Use(next => (context) => { var endpoint = context.GetEndpoint(); if (endpoint != null) { Console.WriteLine("Name:{0};Route:{1};Metadata:{2}", endpoint.DisplayName, (endpoint as RouteEndpoint)?.RoutePattern, string.Join(",",endpoint.Metadata)); } return next(context); });
启动api ,输入一个api调用
输出
Name:NorthwindService.Controllers.WeatherForecastController.Get (NorthwindService);Route:Microsoft.AspNetCore.Routing.Patterns.RoutePattern;Metadata:Microsoft.AspNetCore.Mvc.ApiControllerAttribute,Microsoft.AspNetCore.Mvc.ControllerAttribute,Microsoft.AspNetCore.Mvc.RouteAttribute,Microsoft.AspNetCore.Mvc.HttpGetAttribute,Microsoft.AspNetCore.Routing.HttpMethodMetadata,Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor,Microsoft.AspNetCore.Routing.RouteNameMetadata,Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter,Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilterFactory,Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilterFactory,Microsoft.AspNetCore.Mvc.ApiControllerAttribute,Microsoft.AspNetCore.Mvc.ActionConstraints.HttpMethodActionConstraint
Name:NorthwindService.Controllers.WeatherForecastController.Get (NorthwindService);Route:Microsoft.AspNetCore.Routing.Patterns.RoutePattern;Metadata:Microsoft.AspNetCore.Mvc.ApiControllerAttribute,Microsoft.AspNetCore.Mvc.ControllerAttribute,Microsoft.AspNetCore.Mvc.RouteAttribute,Microsoft.AspNetCore.Mvc.HttpGetAttribute,Microsoft.AspNetCore.Routing.HttpMethodMetadata,Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor,Microsoft.AspNetCore.Routing.RouteNameMetadata,Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter,Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilterFactory,Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilterFactory,Microsoft.AspNetCore.Mvc.ApiControllerAttribute,Microsoft.AspNetCore.Mvc.ActionConstraints.HttpMethodActionConstraint
更多端点路由的更多信息:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing
微软已经使用端点路由代替了NC2.1更早版本的使用的基于 IRouter的路由
其他通讯技术
WCF,
gRPC是可以在任何环境中运行的现代开源高性能RPC框架。
二者都是使用一种契约优先的API开发方式支持与语言无关的实现。可以使用.proto文件编写契约,然后使用它们自己的语言语法工具 转换为各种编程语言。
微软已经正式支持gRPC与ASP.NET Core
https://docs.microsoft.com/zh-cn/aspnet/core/grpc/aspnetcore
Swagger工具: https://swagger.io/tools
=====www.ayjs.net==============
抖音:wpfui 工作wpf,兴趣学习flutter
目前在合肥市某公司上班,已经厌弃,如果你的公司看的上我,加我QQ私聊
AYUI8全源码 Github地址:前往获取
杨洋(AaronYang简称AY,安徽六安人)和AY交流
高中学历,2010年开始web开发,2015年1月17日开始学习WPF
声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费
不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo
查看捐赠AYUI7.X MVC教程 更新如下:
第一课 第二课 程序加密教程
额 本文暂时没人评论 来添加一个吧
发表评论