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

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

MasaFrameworkを使用する

最終更新 2023/03/26 10:54
token的技术分享
読了目安 6 分
カテゴリ
.NET
タグ
.NET C# MASA Framework

まず、MasaFramework テンプレートのプロジェクトを作成します。プロジェクト名は TokenDemo とし、プロジェクトの種類は図の通りです:

Web/TokenDemo.Admin プロジェクトを削除し、新しい Masa Blazor Pro プロジェクトテンプレートを作成します。プロジェクトの場所は src/Web プロジェクトです:

プロジェクトの種類は ServerAndWasm を選択し、2つのモードをサポートします:

作成完了後のディレクトリ。次に 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 はデータフィルタリングの機能を提供しますが、必須ではありません。その後エラーが発生するため、LogMiddleware のコードを次のように変更します:

namespace TokenDemo.Service.Infrastructure.Middleware;

public class LogMiddleware<TEvent> : EventMiddleware<TEvent>
    where TEvent : notnull, 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 : notnull, 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 != null)
            .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 を使用して Sqlite を生成します。

すると、プロジェクトに Catalog.db ファイルが生成されます。

TokenDemo.Service.Order を起動すると、Swagger の画面が表示されます。

インターフェースの接続方法

TokenDemo.Caller プロジェクトの Callers\OrderCaller.cs ファイルを開き、BaseAdderssTokenDemo.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 プロジェクトを起動します:

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 プロジェクトを起動し、ブレークポイントに入ります:

結果が得られます。

まとめ

以上の内容で、MasaFramework の基本的な使用方法を掌握でき、フロントエンドとバックエンドのインターフェースも理解できました。

現在は MasaFramework の3回目の入門記事です。引き続き MasaFramework を学び、皆さんと共有していきます。

token からの共有でした。

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2026/04/22

各OSバージョンの.NETサポート状況(250707更新)

仮想マシンとテストマシンを使用して、各OSバージョンの.NETサポート状況を確認します。OSインストール後、対応するランタイムをインストールし、Stardustエージェントを実行できることを確認します(合格条件)。

続きを読む