天天看點

(3) MasaFramework 入門第三篇,使用MasaFramework

作者:opendotnet

首先我們需要建立一個

MasaFramework

模闆的項目,項目名稱

TokenDemo

,項目類型如圖所示

(3) MasaFramework 入門第三篇,使用MasaFramework

删除

Web/TokenDemo.Admin

項目,建立

Masa Blazor Pro

項目模闆

項目,項目位置在

src/Web

項目

(3) MasaFramework 入門第三篇,使用MasaFramework

項目類型選擇

ServerAndWasm

,為了讓我們支援倆種模式

(3) MasaFramework 入門第三篇,使用MasaFramework

建立完成以後的目錄,然後在

TokenDemo.Admin

中添加項目引用

TokenDemo.Caller

配置

EntityFrameworkCore

Sqlite

修改

TokenDemo.Service

項目的包依賴為預覽版

<ItemGroup>
<PackageReference Include="Masa.BuildingBlocks.Dispatcher.Events" Version="1.0.0-preview.18" />
<PackageReference Include="Masa.Contrib.Data.Contracts" Version="1.0.0-preview.18" />
<PackageReference Include="Masa.Contrib.Data.EFCore.Sqlite" Version="1.0.0-preview.18" />
<PackageReference Include="Masa.Contrib.Dispatcher.Events" Version="1.0.0-preview.18" />
<PackageReference Include="Masa.Contrib.Dispatcher.IntegrationEvents.EventLogs.EFCore" Version="1.0.0-preview.18" />
<PackageReference Include="FluentValidation" Version="11.5.1" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
<PackageReference Include="Masa.Utils.Extensions.DependencyInjection" Version="1.0.0-preview.18" />
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0-preview.18" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
           

Masa.Contrib.Data.Contracts

提供了資料過濾[1]的能力, 但它不是必須的

然後會出現報錯

LogMiddleware

将代碼修改為以下代碼

namespace TokenDemo.Service.Infrastructure.Middleware;

public class LogMiddleware<TEvent> : EventMiddleware<TEvent>
where TEvent : not, IEvent
{
private readonly ILogger<LogMiddleware<TEvent>> _logger;

public LogMiddleware(ILogger<LogMiddleware<TEvent>> logger)
 {
 _logger = logger;
 }

public override async Task HandleAsync(TEvent action, EventHandlerDelegate next)
 {
var typeName = action.GetType().FullName;

 _logger.LogInformation("----- command {CommandType}", typeName);

await next();
 }
}
           

ValidatorMiddleware

将代碼修改為以下代碼

namespace TokenDemo.Service.Infrastructure.Middleware;

public class ValidatorMiddleware<TEvent> : EventMiddleware<TEvent>
where TEvent : not, IEvent
{
private readonly ILogger<ValidatorMiddleware<TEvent>> _logger;
private readonly IEnumerable<IValidator<TEvent>> _validators;

public ValidatorMiddleware(IEnumerable<IValidator<TEvent>> validators, ILogger<ValidatorMiddleware<TEvent>> logger)
 {
 _validators = validators;
 _logger = logger;
 }

public override async Task HandleAsync(TEvent action, EventHandlerDelegate next)
 {
var typeName = action.GetType().FullName;

 _logger.LogInformation("----- Validating command {CommandType}", typeName);

var failures = _validators
 .Select(v => v.Validate(action))
 .SelectMany(result => result.Errors)
 .Where(error => error != )
 .ToList();

if (failures.Any())
 {
 _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, action, failures);

throw new ValidationException("Validation exception", failures);
 }

await next();
 }
}
           

OrderEventHandler

将代碼修改為以下代碼

namespace TokenDemo.Service.Infrastructure.Handlers;

public class OrderEventHandler
{
readonly IOrderRepository _orderRepository;

public OrderEventHandler(IOrderRepository orderRepository)
 {
 _orderRepository = orderRepository;
 }

 [EventHandler(Order = 1)]
public async Task HandleAsync(QueryOrderListEvent @event)
 {
 @event.Orders = await _orderRepository.GetListAsync();
 }
}

public class OrderEventAfterHandler : IEventHandler<QueryOrderListEvent>
{
public async Task HandleAsync(QueryOrderListEvent @event, CancellationToken cancellationToken = new CancellationToken())
 {
await Task.CompletedTask;
 }
}
           

修改

appsettings.json

添加

Sqlite

位址

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
 }
 },
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Data Source=Catalog.db;"
 }
}
           

修改

Program.cs

代碼

using TokenDemo.Service.Infrastructure;

var builder = WebApplication.CreateBuilder(args);

builder.Services
 .AddAuthorization()
 .AddAuthentication(options =>
 {
 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 })
 .AddJwtBearer(options =>
 {
 options.Authority = "";
 options.RequireHttpsMetadata = false;
 options.Audience = "";
 });

builder.Services.AddMasaDbContext<ShopDbContext>(dbContextBuilder =>
{
 dbContextBuilder
 .UseSqlite() //使用Sqlite資料庫
 .UseFilter(); //資料資料過濾
});

builder.Services.AddAutoInject();
var app = builder.Services
 .AddEndpointsApiExplorer()
 .AddSwaggerGen(options =>
 {
 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
 {
 Name = "Authorization",
 Type = SecuritySchemeType.ApiKey,
 Scheme = "Bearer",
 BearerFormat = "JWT",
 In = ParameterLocation.Header,
 Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer xxxxxxxxxxxxxxx\"",
 });
 options.AddSecurityRequirement(new OpenApiSecurityRequirement
 {
 {
new OpenApiSecurityScheme
 {
 Reference = new OpenApiReference
 {
 Type = ReferenceType.SecurityScheme,
 Id = "Bearer"
 }
 },
new string[] {}
 }
 });
 })
 .AddFluentValidationAutoValidation().AddFluentValidationClientsideAdapters()
 .AddEventBus(eventBusBuilder =>
 {
 eventBusBuilder.UseMiddleware(typeof(ValidatorMiddleware<>));
 eventBusBuilder.UseMiddleware(typeof(LogMiddleware<>));
 })
 .AddServices(builder);

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
 app.UseSwagger();
 app.UseSwaggerUI();
}
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseHttpsRedirection();

app.Run();
           

添加EFCore遷移依賴

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
           

程式包管理器控制台

中輸入

Add-Migration Init

生成

Init

的遷移檔案(如果出現

error NETSDK1082: Microsoft.AspNetCore.App 沒有運作時包可用于指定的 RuntimeIdentifier“browser-wasm”

這個錯誤的話就先把

TokenDemo.Admin.WebAssembly

項目移除)

使用

Update-Database

生成

Sqlitem

然後就可以看到項目中生成了

Catalog.db

檔案

啟動

TokenDemo.Service.Order

我們就可以看到Swagger的界面了

如何對接接口

打開

TokenDemo.Caller

項目中的``Callers\OrderCaller.cs`檔案

修改

BaseAdderss

TokenDemo.Service.Order

的服務位址

打開

TokenDemo.Service.Order

項目的

Services\OrderService.cs

檔案并且修改代碼

namespace TokenDemo.Service.Services;

public class OrderService : ServiceBase
{
public OrderService(IServiceCollection services) : base(services)
 {
 App.MapGet("/order/list", QueryList).Produces<List<Infrastructure.Entities.Order>>()
 .WithName("GetOrders");
 }

public async Task<IResult> QueryList(IEventBus eventBus)
 {
var orderQueryEvent = new QueryOrderListEvent();
await eventBus.PublishAsync(orderQueryEvent);
return Results.Ok(orderQueryEvent.Orders);
 }
}
           

然後在通過指令行啟動

TokenDemo.Service.Order

項目

(3) MasaFramework 入門第三篇,使用MasaFramework

打開

TokenDemo\Admin

項目的

Pages\Home\Index.razor

檔案并且修改代碼

@page "/"
@using TokenDemo.Caller.Callers
@inherits LayoutComponentBase
@inject NavigationManager Nav
@inject OrderCaller OrderCaller
@code {

protected override async Task OnAfterRenderAsync(bool firstRender)
 {
 Nav.NavigateTo(GlobalVariables.DefaultRoute,true);
var data = await OrderCaller.GetListAsync();
await base.OnAfterRenderAsync(firstRender);
 }

}

           

并且在

await base.OnAfterRenderAsync(firstRender);

這裡打一個斷點用于檢視是否擷取到消息

打開

TokenDemo.Admin.Server

項目的

Program.cs

,添加以下代碼

builder.Services.AddCaller(typeof(TokenDemo.Caller.Callers.OrderCaller).Assembly);
           

然後啟動

TokenDemo.Admin.Server

項目,進入斷點

(3) MasaFramework 入門第三篇,使用MasaFramework

得到結果

結尾

通過上文我們可以基本将

MasaFramework

的使用掌握,前端和後端的接口也掌握了

目前是

MasaFramework

的第三篇入門,我會繼續學習

MasaFramework

并且分享給大家

來自token的分享

MASA Framework[2]

學習交流:737776595

參考資料

[1]

資料過濾: https://docs.masastack.com/framework/building-blocks/data/data-filter

[2]

MASA Framework: https://docs.masastack.com/framework/getting-started/overview