• (3) MasaFramework 入门第三篇,使用MasaFramework


    首先我们需要创建一个MasaFramework模板的项目,项目名称TokenDemo,项目类型如图所示

    删除Web/TokenDemo.Admin项目,新建Masa Blazor Pro项目模板

    项目,项目位置在src/Web项目

    项目类型选择ServerAndWasm,为了让我们支持俩种模式

    创建完成以后的目录,然后在TokenDemo.Admin中添加项目引用TokenDemo.Caller

    配置EntityFrameworkCoreSqlite

    修改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
        where TEvent : notnull, IEvent
    {
        private readonly ILogger> _logger;
    
        public LogMiddleware(ILogger> 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
        where TEvent : notnull, IEvent
    {
        private readonly ILogger> _logger;
        private readonly IEnumerable> _validators;
    
        public ValidatorMiddleware(IEnumerable> validators, ILogger> 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
    {
        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(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>allPrivateAssets>
    		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitiveIncludeAssets>
    		PackageReference>
    		<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.15">
    		  <PrivateAssets>allPrivateAssets>
    		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitiveIncludeAssets>
    		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`文件

    修改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>()
                .WithName("GetOrders");
        }
    
        public async Task 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的第三篇入门,我会继续学习MasaFramework并且分享给大家

    来自token的分享

    MASA Framework

    学习交流:737776595

  • 相关阅读:
    前端开发面试题—JavaScript循环语句
    软考高级-系统架构师-案例分析-数据库真题考点汇总
    meta视口标签
    反转链表的升级版——链表内指定区间反转
    项目工作中,管理者如何合理安排任务优先级?
    Flink Watermark 机制
    计算机网络常见概念
    ORI-GB-NP半乳糖介导冬凌草甲素/姜黄素牛血清白蛋白纳米粒的研究制备方法
    Python 图形化界面基础篇:更改字体、颜色和样式
    ubuntu 22.04 更新NVIDIA显卡驱动,重启后无网络图标等系统奇奇怪怪问题
  • 原文地址:https://www.cnblogs.com/hejiale010426/p/17227910.html