DevExpress XAF是一款强大的现代应用程序框架,允许同时开发ASP.NET和WinForms。DevExpress XAF采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。
.NET Aspire是一组工具、模板和包,用于构建可观察的、可生产的应用程序。DevExpress XAF团队花费了一些时间考虑Aspire的功能,试图找到最好的集成点,让XAF开发人员能够利用Aspire开箱即用的业务流程特性。
DevExpress技术交流群11:749942875 欢迎一起进群讨论
在最近的一篇文章中我们介绍了如何对一个 XAF Blazor 项目进行调整,来支持 .NET Aspire(点击这里回顾>>)。通过对启动逻辑进行一些修改——包括标准的 XAF 项目模板和 Aspire 的 Visual Studio 向导生成的代码,已经可以让 XAF Blazor 项目作为 Aspire 编排体系的一部分运行了。但那只是最小规模的编排,只有一个模块!接下来我们将会把部署方面的内容留到第三篇(敬请关注!),接下来得系列文章将介绍在示例项目中为实现以下三个场景所做的修改:
- 通过 OpenTelemetry 将自定义活动和指标记录到 Aspire 仪表盘
- 将 SQL Server 作为一个由 Aspire 协调运行的容器化依赖项
- 在编排中添加一个额外的服务,展示更复杂的系统结构
完整示例项目已托管在这个 GitHub 仓库中。下面基于我在第一篇文章中描述的项目初始状态,展开说明新的功能实现。
在上文中(点击这里回顾>>),我们为大家介绍了如何将SQL Server添加为容器依赖项,本文将继续介绍如何安排额外的应用程序服务,欢迎继续关注我们~
安排额外的应用程序服务
到目前为止,业务流程有两个部分:SQL Server和Blazor Server应用程序。现在,我将向应用程序系统添加一个额外的服务,它将从Blazor应用程序中的测试控制器调用。
首先创建一个新项目并将其添加到解决方案中,然后将对XafAspireDemo.ServiceDefaults的引用添加到新项目,并将对新项目的引用添加到项目XafAspireDemo.AppHost。
> dotnet new webapi -n XAFAspireDemo.DemoService > dotnet sln add XAFAspireDemo.DemoService/XAFAspireService.DemoService.csproj > dotnet add XAFAspireDemo.DemoService/XAFAspireService.DemoService.csproj reference XafAspireDemo.ServiceDefaults/XafAspireDemo.ServiceDefaults.csproj > dotnet add XafAspireDemo.AppHost reference XAFAspireDemo.DemoService/XAFAspireService.DemoService.csproj
在新的服务项目中添加了一个类Telemetry,类似于Blazor Server项目中的类,但是使用了它自己的标识符和名称。
using System.Diagnostics; using System.Diagnostics.Metrics; namespace XafAspireDemo.DemoService { public class Telemetry : IDisposable { public ActivitySource ActivitySource { get; } public Meter Meter { get; } public string MeterName => Meter.Name; public Counter<long> ImportantBusinessValueRetrievalCounter { get; } public Histogram<double> ImportantBusinessValueRetrievalDuration { get; } public Telemetry(string serviceName = "XafAspireDemo.DemoService", string version = "1.0.0") { ActivitySource = new ActivitySource(serviceName, version); Meter = new Meter(serviceName, version); ImportantBusinessValueRetrievalCounter = Meter.CreateCounter<long>( "important_business_value.retrieval_count" ); ImportantBusinessValueRetrievalDuration = Meter.CreateHistogram<double>( "important_business_value.retrieval_duration" ); } public void Dispose() { ActivitySource.Dispose(); Meter.Dispose(); } } }
将XAFAspireDemo.DemoService/Program.cs中的模板代码替换为:
using XafAspireDemo.DemoService; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApi(); builder.Services.AddAspireServiceDefaults(); builder.Services.ConfigureOpenTelemetry(builder.Configuration, builder.Environment); var telemetry = new Telemetry(); builder.Services.AddSingleton(telemetry); builder .Services.AddOpenTelemetry() .WithTracing(tracing => tracing.AddSource("XafAspireDemo.DemoService")) .WithMetrics(metrics => { metrics.AddMeter(telemetry.MeterName); }); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.UseHttpsRedirection(); app.MapGet( "/important-business-value", (Telemetry telemetry) => { using var activity = telemetry.ActivitySource.StartActivity( "ImportantBusinessValueRetrieval" ); var importantBusinessValue = Random.Shared.Next(1, 10000); telemetry.ImportantBusinessValueRetrievalCounter.Add(1); if (activity != null) { activity.Stop(); var durationMs = activity.Duration.TotalMilliseconds; telemetry.ImportantBusinessValueRetrievalDuration.Record(durationMs); } return Results.Ok(new { ImportantBusinessValue = importantBusinessValue }); } ) .WithName("GetImportantBusinessValue") .WithOpenApi(); app.MapDefaultAspireDevEndpoints(); app.Run();
到目前为止,这些都是熟悉的代码,只是需要指出一些细节:
- AddAspireServiceDefaults、ConfigureOpenTelemetry和MapDefaultAspireDevEndpoints这些帮助器与Blazor Server项目共享以保持一致性
- 启动模式与Blazor服务器应用程序中使用的模式非常相似
- /important-business-value端点的处理程序实现对激活和仪表使用与Blazor应用程序示例控制器中代码相同的模式
现在修改文件XafAspireDemo.AppHost/Program.cs,将新项目添加到编排中。注意更改了对WithHttpsEndpoint的现有调用,来传递一个显式名称。Aspire不喜欢多个无参数调用,因为它不会分配自动生成的名称。
... var db = sql.AddDatabase("XafAspireDemoDb"); --> var demoService = builder --> .AddProject<Projects.XAFAspireDemo_DemoService>("demoservice") --> .WithHttpsEndpoint(name: "demoservice-https"); builder .AddProject<Projects.XafAspireDemo_Blazor_Server>("xafaspiredemo-blazor-server") .WithEnvironment("ASPIRE_DEBUG", "true") --> .WithHttpsEndpoint(name: "xafaspiredemo-blazor-server-https") .WithReference(db) --> .WithReference(demoService) .WaitFor(db);
要从测试控制器调用新服务,需要为它提供一个HTTP客户端,修改XafAspireDemo.Blazor.Server/Startup.cs并添加这一行:
... services.ConfigureOpenTelemetry(Configuration, WebHostEnvironment); --> services.AddHttpClient(); services.ConfigureOpenTelemetryTracerProvider(builder => ...
现在可以使用HTTP客户端从XafAspireDemo.Blazor.Server/Controllers/ImportantBusinessOperationsController.cs中的控制器调用服务。
... { Thread.Sleep(new Random().Next(500, 5000)); }); --> var httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>(); --> var httpClient = httpClientFactory.CreateClient(); --> var response = await httpClient.GetFromJsonAsync<ImportantBusinessValueResponse>( --> "https://demoservice/important-business-value" --> ); --> logger.LogInformation( --> "Received important business value from service: {ImportantBusinessValue}", --> response?.ImportantBusinessValue --> ); } catch (Exception ex) { ...
一个有趣的细节:服务请求的URL使用主机名demoservice。因为主机将服务配置为依赖项,Blazor服务器的DNS解析允许访问该名称并将其解析为目标服务。
这就完成了更改!当我现在运行应用程序时,Aspire Dashboard显示了新的结构。日志输出现在包括来自新服务的项目,度量也包括在内(选择正确的资源来查看它们!),并且由于服务端点报告它自己的活动,现在您还可以在Traces页面中看到嵌套的活动。


未完待续,我们下期再见!更多产品资讯及授权,欢迎来电咨询:023-68661681
关于慧都科技
慧都是⼀家⾏业数字化解决⽅案公司,专注于软件、⽯油与⼯业领域,以深⼊的业务理解和⾏业经验,帮助企业实现智能化转型与持续竞争优势。
慧都科技是DevExpress的中国区的合作伙伴,DevExpress作为用户界面领域的优秀产品,帮助企业高效构建权限管理、数据可视化(如网格/图表/仪表盘)、跨平台系统(WinForms/ASP.NET/.NET MAUI)及行业定制解决方案,加速开发并强化交互体验。
欢迎任何形式的转载,但请务必注明出处,尊重他人劳动成果
转载请注明:文章转载自:DevExpress控件中文网 [https://www.devexpresscn.com/]
本文地址:https://www.devexpresscn.com/post/5231.html
相关产品: .NET开发框架eXpressApp Framework(XAF), DevExpress Universal Subscription,