目前我们的MainLayout还是默认的,这里我们需要修改为BootstrapBlazor的Layout,并且处理一下菜单。

修改MainLayout

BootstrapBlazor已经自带了一个Layout组件,这个组件里常用功能已经很全了,所以我们直接使用这个组件即可。

<Layout SideWidth="0" IsPage="true" IsFullSide="true" IsFixedHeader="true" IsFixedFooter="true"
ShowFooter="true" ShowCollapseBar="true" OnCollapsed="@OnCollapsed" Menus="@_menuItems">
<Header>
<span class="ms-3 flex-sm-fill d-none d-sm-block">BlazorLearn</span>
<div class="flex-fill d-sm-none">
</div>
<Logout ImageUrl="images/argo-c.png" DisplayName="@_user.Name" UserName="@_user.UserName">
<LinkTemplate>
<LogoutLink Url="/api/account/logout"></LogoutLink>
</LinkTemplate>
</Logout>
</Header>
<Side>
<div class="layout-banner">
<img class="layout-logo" src="data:images/Argo.png" />
<div class="layout-title">
<span>BlazorLearn</span>
</div>
</div>
</Side>
<Main>
<CascadingValue Value="this" IsFixed="true">
@Body
</CascadingValue>
</Main>
<Footer>
<div class="text-center flex-fill">
<a href="/" target="_blank">BlazorLearn</a>
</div>
</Footer>
</Layout> @code
{
private bool IsCollapsed { get; set; } private List<MenuItem>? _menuItems; [NotNull]
private UserEntity? _user; private Task OnCollapsed(bool collapsed)
{
IsCollapsed = collapsed;
return Task.CompletedTask;
} protected override void OnInitialized()
{
base.OnInitialized();
_user = UserEntity.Where(x => x.UserName == Furion.App.User.FindFirstValue(ClaimTypes.Name)).First();
if (_user == null)
{
return;
}
_menuItems = CreateMenuItems(MenuEntity.Where(x => x.Roles!.Any(y => y.Id == _user.RoleId)).ToList(), 0);
} private List<MenuItem> CreateMenuItems(List<MenuEntity> menus, int parentId)
{
var selectedMenus = new List<MenuItem>();
var selectedMenuEntities = menus.Where(x => x.ParentId == parentId).ToList(); foreach (var menuEntity in selectedMenuEntities)
{
var menuItem = new MenuItem(menuEntity.Name!, menuEntity.Url, menuEntity.Icon);
menuItem.Items = CreateMenuItems(menus, menuEntity.Id);
selectedMenus.Add(menuItem);
}
return selectedMenus;
}
}

这里没什么需要多说的,每个参数的意义在文档里都比较清楚,如果需要查询具体的含义,可以看这里

这里需要注意的是,Menus里面必须要定义一个变量,不能直接放一个方法,否则此方法每次跳转都会执行,导致菜单不正常。

另外Logout是一个独立的组件,这个组件其实叫Logout并不贴切,它是一个带有头像,欢迎信息以及下拉菜单的用户信息组件。

这里我们只放一个LogoutLink登出菜单。

修改AdminHandler

如果你直接启动项目,会发现Layout不见了,因为我们的Layout里面做了比较多的处理,会有一个需要权限验证的请求。这个请求不会携带Resource,所以不会返回true。就导致Layout一直不显示,所以我们需要处理这种情况,我们目前修改为Resource里不是RouteData的全部都通过验证。

    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
{
if (!int.TryParse(context.User.FindFirst(ClaimTypes.Role)?.Value, out var roleId))
{
return Task.FromResult(false);
}
if (context.Resource is RouteData routeData)
{
var routeAttr = routeData.PageType.CustomAttributes.FirstOrDefault(x =>
x.AttributeType == typeof(RouteAttribute));
if (routeAttr == null)
{
return Task.FromResult(true);
}
else
{
var url = routeAttr.ConstructorArguments[0].Value as string;
var permission = MenuEntity
.Where(x => x.Roles!.Any(y => y.Id == roleId) && x.Url == url).First();
if (permission != null)
{
return Task.FromResult(true);
}
}
}
else
{
return Task.FromResult(true);
} return Task.FromResult(false);
}

这样我们再启动应该就可以看到Layout了。

修改LoginController

我们之前只有一个登录,所以我们写了一个LoginController,现在我们需要加入登出,所以我们直接把LoginController改为AccountController,然后内容改为PostLoginGetLogout

public class AccountController: IDynamicApiController
{
public async Task<object> PostLogin([FromBody]LoginVo loginVo)
{
if (string.IsNullOrEmpty(loginVo.UserName))
{
return new { code = 50000, message = "用户名不能为空" };
}
if (string.IsNullOrEmpty(loginVo.Password))
{
return new { code = 50000, message = "密码不能为空" };
} var password = MD5Encryption.Encrypt(loginVo.Password);
var user = await UserEntity.Where(x =>
x.UserName == loginVo.UserName && x.Password == password).Include(x => x.Role).FirstAsync();
if (user != null)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName!));
identity.AddClaim(new Claim(ClaimTypes.Role, user.Role!.Id.ToString()));
await Furion.App.HttpContext.SignInAsync(new ClaimsPrincipal(identity), new AuthenticationProperties(){IsPersistent = true, ExpiresUtc = loginVo.RememberMe? DateTimeOffset.Now.AddDays(5): DateTimeOffset.Now.AddMinutes(30)}); return new { code = 20000, message = "登录成功" };
}
return new { code = 50000, message = "用户名或密码错误" };
} [Authorize]
public async Task<IActionResult> GetLogout()
{
await Furion.App.HttpContext.SignOutAsync();
return new RedirectResult("/Login");
}
}

这里我们直接给Logout[Authorize],只有登录以后才能访问。

代码在github:https://github.com/j4587698/BlazorLearnj,分支lesson9。

从零开始Blazor Server(9)--修改Layout的更多相关文章

  1. [Asp.Net Core] Blazor Server Side 扩展用途 - 配合CEF来制作带浏览器核心的客户端软件 (二) 可运行版本

    前言 大概3个星期之前立项, 要做一个 CEF+Blazor+WinForms 三合一到同一个进程的客户端模板. 这个东西在五一的时候做出了原型, 然后慢慢修正, 在5天之前就上传到github了. ...

  2. [Asp.Net Core] Blazor Server Side 扩展用途 - 配合CEF来制作客户端浏览器软件

    前言 大家用过微信PC端吧? 这是用浏览器做的. 用过Visual Studio Code吧? 也是用浏览器做的. 听说, 暴雪客户端也包含浏览器核心?? 在客户端启动一个浏览器, 并不是什么难事了. ...

  3. ASP.NET Core Blazor 初探之 Blazor Server

    上周初步对Blazor WebAssembly进行了初步的探索(ASP.NET Core Blazor 初探之 Blazor WebAssembly).这次来看看Blazor Server该怎么玩. ...

  4. 在Blazor Server 项目中使用 EF Core Sqlite

    按照教程创建了一个 Blazor Server 项目 教程地址: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/build-a-blaz ...

  5. Blazor Server 和 WebAssembly 应用程序入门指南

    翻译自 Waqas Anwar 2021年3月12日的文章 <A Beginner's Guide To Blazor Server and WebAssembly Applications&g ...

  6. SQL SERVER 2005修改数据库名称,包括物理文件名和逻辑名称

    SQL SERVER 2005修改数据库名称,包括物理文件名和逻辑名称   原来数据库名称为 aa,物理文件名称为 aa.mdf 和 aa_log.ldf:   需要修改数据库名称为 bb,物理文件名 ...

  7. SQL server 创建 修改表格 及表格基本增删改查 及 高级查询 及 (数学、字符串、日期时间)函数[转]

    SQL server 创建 修改表格 及表格基本增删改查 及 高级查询 及 (数学.字符串.日期时间)函数   --创建表格 create table aa ( UserName varchar(50 ...

  8. 安装完sql server 后修改计算机名后不能进行发布的订阅的解决办法

    由于需要需要配置一个发布订阅,可是一直报告:" sql server 复制需要有实际的服务器名称才能连接到服务器,不支持通过别名.ip地址或其他任何备用名称进行连接.请指定实际的服务器名称“ ...

  9. ArcGIS for Server 的修改IP问题

      ArcGIS for Server 的修改IP问题   1. [[email protected] ~]$ vi /home/arcgisserver/serverconfig/config ...

  10. 使用Blazor Server 线路处理程序 (circuit handler)跟踪打开的SignalR连接

    Blazor服务器允许定义线路处理程序(circuit handler)代码,该处理程序(handler)允许在更改用户线路状态时运行此代码. 线路处理程序(circuit handler)是通过从C ...

随机推荐

  1. μC/OS-Ⅲ系统中的任务就续表

    μC/OS-Ⅲ支持任意数目的不同优先级.一般情况下64级优先级就足够了. 在μC/OS-Ⅲ中所有已经就绪等待运 行的任务都被放入一个我为的“就续表”(ready list)中.就续表包括两部分:一个就 ...

  2. JS实现元素拖动

    实现1 参考文献:http://www.cnblogs.com/cloudgamer/archive/2008/11/17/Drag.html 1.1 拖放效果 <!DOCTYPE html P ...

  3. XSS 简单理解

    什么是XSS? XSS(Cross Site Scripting),即跨站脚本攻击,是一种常见于web application中的计算机安全漏洞.XSS通过在用户端注入恶意的可运行脚本,若服务器端对用 ...

  4. 36.中国特色社会主义的体制中有这样的现象:地方省政府要坚持党的领导和按 照国务院的指示进行安全生产。请编写一个java应用程序描述上述的体制现象。 要求如下: (1)该应用程序中有一个“党中央”接口:CentralPartyCommittee,该接口中 有个“坚持党的领导”方法:void partyLeader() (2)该应用程序中有一个“国务院”抽象类:StateCouncil,该抽象类中有

    //接口:CentralPartyCommittee package jieKou; public interface CentralPartyCommittee { void partyLeader ...

  5. LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

    #6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  6. 活字格Web应用平台学习笔记4 - 添加记录

    今天继续学习活字格基础教程,目标是创建一个页面,增加记录. 开始之前,系统会自动把上一次的工程文件加载进来. 这是做好后的样子. 我点添加员工的超链接: 先后加了2条员工的信息进来. 不错,设计界面是 ...

  7. iOS多线程编程之线程的状态(转载)

    一.简单介绍 线程的创建: self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil]; ...

  8. jdbc连接1(可以注入)

    package demo3class; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Prepa ...

  9. Java学习第二周学习笔记

    20145307<Java程序设计>第二周学习总结 教材学习内容总结 Java语言中的很多基本语法都和C语言类似,以下Java中的基本语法 标识符 标识符是程序中自定义的一些名称. 由26 ...

  10. SpringBoot集成WebSocket【基于纯H5】进行点对点[一对一]和广播[一对多]实时推送

    代码全部复制,仅供自己学习用 1.环境搭建 因为在上一篇基于STOMP协议实现的WebSocket里已经有大概介绍过Web的基本情况了,所以在这篇就不多说了,我们直接进入正题吧,在SpringBoot ...