在本文中,我将展示如何使用DfaGraphWriter服务在ASP.NET Core 3.0应用程序中可视化你的终结点路由。上面文章我向您演示了如何生成一个有向图(如我上篇文章中所示),可以使用GraphVizOnline将其可视化。最后,我描述了应用程序生命周期中可以检索图形数据的点。
作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/13335749.html
译文地址:https://andrewlock.net/adding-an-endpoint-graph-to-your-aspnetcore-application/
在本文中,我仅展示如何创建图形的“默认”样式。在我的下一批那文章中,我再创建一个自定义的writer来生成自定义的图如上篇文章所示。
使用DfaGraphWriter可视化您的终结点ASP.NET Core附带了一个方便的类DfaGraphWriter可用于可视化ASP.NET Core 3.x应用程序中的终结点路由:
public class DfaGraphWriter { public void Write(EndpointDataSource dataSource, TextWriter writer); }此类只有一个方法Write。EndpointDataSource包含描述您的应用程序的Endpoint集合,TextWriter用于编写DOT语言图(如您在前一篇文章中所见)。
现在,我们将创建一个中间件,该中间件使用DfaGraphWriter将该图编写为HTTP响应。您可以使用DI 将DfaGraphWriter和EndpointDataSource注入到构造函数中:
public class GraphEndpointMiddleware { // inject required services using DI private readonly DfaGraphWriter _graphWriter; private readonly EndpointDataSource _endpointData; public GraphEndpointMiddleware( RequestDelegate next, DfaGraphWriter graphWriter, EndpointDataSource endpointData) { _graphWriter = graphWriter; _endpointData = endpointData; } public async Task Invoke(HttpContext context) { // set the response context.Response.StatusCode = 200; context.Response.ContentType = "text/plain"; // Write the response into memory await using (var sw = new StringWriter()) { // Write the graph _graphWriter.Write(_endpointData, sw); var graph = sw.ToString(); // Write the graph to the response await context.Response.WriteAsync(graph); } } }这个中间件非常简单-我们使用依赖注入将必要的服务注入到中间件中。将图形写入响应有点复杂:您必须在内存中将响应写到一个 StringWriter,再将其转换为 string,然后将其写到图形。
这一切都是必要的,因为DfaGraphWriter写入TextWriter使用同步 Stream API调用,如Write,而不是WriteAsync。如果有异步方法,理想情况下,我们将能够执行以下操作:
// Create a stream writer that wraps the body await using (var sw = new StreamWriter(context.Response.Body)) { // write asynchronously to the stream await _graphWriter.WriteAsync(_endpointData, sw); }如果DfaGraphWriter使用了异步API,则可以如上所述直接写入Response.Body,而避免使用in-memory string。不幸的是,它是同步的,。如果您尝试使用上面的模式,则可能会得到如下所示内容的InvalidOperationException异常,具体取决于所写图形的大小:
System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.如果图形很小,则可能不会出现此异常,但是如果您尝试映射中等规模的应用程序(例如带有Identity的默认Razor Pages应用程序),则可以看到此异常。
让我们回到正轨上-我们现在有了一个图形生成中间件,所以让我们把它添加到管道中。这里有两个选择:
使用终结点路由将其添加为终结点。
从中间件管道中将其添加为简单的“分支”。
通常建议使用前一种方法,将终结点添加到ASP.NET Core 3.0应用程序,因此从这里开始。
将图形可视化器添加为终结点为了简化终结点注册代码,我将创建一个简单的扩展方法以将GraphEndpointMiddleware作为终结点添加:
public static class GraphEndpointMiddlewareExtensions { public static IEndpointConventionBuilder MapGraphVisualisation( this IEndpointRouteBuilder endpoints, string pattern) { var pipeline = endpoints .CreateApplicationBuilder() .UseMiddleware<GraphEndpointMiddleware>() .Build(); return endpoints.Map(pattern, pipeline).WithDisplayName("Endpoint Graph"); } }然后,我们可以在Startup.Configure()中的UseEndpoints()方法中调用MapGraphVisualisation("/graph")将图形终结点添加到我们的ASP.NET Core应用程序中:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/healthz"); endpoints.MapControllers(); // Add the graph endpoint endpoints.MapGraphVisualisation("/graph"); }); }这就是我们要做的。该DfaGraphWriter已经在DI中可用,因此不需要额外的配置。导航至:5000/graph将以纯文本形式生成我们的终结点图:
digraph DFA { 0 [label="/graph/"] 1 [label="/healthz/"] 2 [label="/api/Values/{...}/ HTTP: GET"] 3 [label="/api/Values/{...}/ HTTP: PUT"] 4 [label="/api/Values/{...}/ HTTP: DELETE"] 5 [label="/api/Values/{...}/ HTTP: *"] 6 -> 2 [label="HTTP: GET"] 6 -> 3 [label="HTTP: PUT"] 6 -> 4 [label="HTTP: DELETE"] 6 -> 5 [label="HTTP: *"] 6 [label="/api/Values/{...}/"] 7 [label="/api/Values/ HTTP: GET"] 8 [label="/api/Values/ HTTP: POST"] 9 [label="/api/Values/ HTTP: *"] 10 -> 6 [label="/*"] 10 -> 7 [label="HTTP: GET"] 10 -> 8 [label="HTTP: POST"] 10 -> 9 [label="HTTP: *"] 10 [label="/api/Values/"] 11 -> 10 [label="/Values"] 11 [label="/api/"] 12 -> 0 [label="/graph"] 12 -> 1 [label="/healthz"] 12 -> 11 [label="/api"] 12 [label="http://www.likecs.com/"] }我们可以使用GraphVizOnline进行可视化显示如下: