一文说通Blazor for Server-Side的项目结构

用C#代替Javascript来做Web应用,是有多爽?

今天聊聊 Blazor。

Blazor 是一个 Web UI 框架。这个框架允许开发者使用 C# 来创建可运行于浏览器的具有完全交互 UI 的 Web 应用。

可以理解为,这是一个 C# 语言的 Vue / Angular / React,可以和 HTML、CSS 一起实现可重用的 Web UI,可以和服务器共享代码和库。

Blazor 拥有现代 Web 框架具备的所有功能,包括:

  • 用于构建 composable UI 的组件模型

  • 路由

  • 布局

  • 表格和验证

  • 依赖注入

  • JavaScript 互操作

  • 开发期间在浏览器中实时重新加载

  • 服务器端渲染

  • 在浏览器和 IDE 中全面调试 .NET

  • 能够通过 asm.js 在较早版本的(非 WebAssembly )浏览器上运行

Blazor 有两种托管模型:

  • Blazor WebAssembly (blazorwasm)

  • Blazor Server (blazorserver)

两种模型从应用层面没有太大的区别,但从实际运行和布署上,两个模型还是有相当的区别的。

Blazor WebAssembly 应用跑在浏览器上,要求浏览器支持 WebAssembly。换句话说,早期的一些浏览器并不支持 WebAssembly,所以也无法使用。同时,应用在首次运行时,需要下载应用和应用依赖项和运行时到本地,所以会有个加载延时。但是,这种模型可以全部运行在客户端,充分利用客户端资源,对服务器压力小。

Blazor Server 则相反,应用跑在服务器上,通过SignalR来处理 UI 更新、事件处理。所以,它加载速度快,可以充分利用服务器功能,并可以运行早期的浏览器。不过,因为应用需要跟服务器通讯,所以,不支持脱机工作,服务器压力大。

简单的区别就这么多,详细的内容,我会另开一文来说。

今天我们主说 Blazor for Server-Side ,也就是上面介绍的 Blazor Server 模型。

一、创建空项目

我们先创建一个Web空项目:

% dotnet new sln -o demo
The template "Solution File" was created successfully.
% cd demo 
% dotnet new web -o demo
The template "ASP.NET Core Empty" was created successfully.Processing post-creation actions...
Running 'dotnet restore' on demo/demo.csproj...Determining projects to restore...Restored /demo/demo/demo.csproj (in 148 ms).Restore succeeded.
% dotnet sln add demo/demo.csproj 
Project `demo/demo.csproj` added to the solution.

创建完成。看一下目录结构:

% tree .
.
├── demo
│   ├── Program.cs
│   ├── Properties
│   │   └── launchSettings.json
│   ├── Startup.cs
│   ├── appsettings.Development.json
│   ├── appsettings.json
│   └── demo.csproj
└── demo.sln

这就是我们的基础项目了。后面所有的项目,都会在这个基础上进行修改和增加。

二、添加 Blazor 服务

打开Startup.cs文件。

1. 修改 ConfigureServices

ConfigureServices中添加:

services.AddRazorPages();
services.AddServerSideBlazor();

这两行代码中,services.AddRazorPages()是添加Razor服务。

RazorBlazor名字很像,但本身并没有关系。Razor是一种服务器标记语言,类似于PHP

这里添加Razor,只是因为我习惯用Razor,并没有特殊性。如果你习惯用 MVC,这儿也可以换成services.AddMvc(),是一样的。

下面一行services.AddServerSideBlazor(),才是真正的内容:添加Blazor Server-Side服务。

2. 修改 Configure

Configure中添加:

app.UseStaticFiles();
app.UseEndpoints(endpoints =>
{endpoints.MapBlazorHub();
});

其中,app.UseStaticFiles()表明我们会用到静态文件。文件默认要求放在wwwroot目录下,所以可以把目录也建了。

app.UseEndpoints,需要使用Blazor路由,所以要改成endpoints.MapBlazorHub()

这儿就完成了。

3. 加入路由

接下来,我们需要建立路由。在项目中建一个目录Pages。这是Blazor默认的单页面目录。然后在里面建一个_Host.cshtml

@page "/"
@namespace demo.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Demo</title><base href="~/" />
</head>
<body><app><component type="typeof(App)" render-mode="ServerPrerendered" /></app><script src="_framework/blazor.server.js"></script>
</body>
</html>

然后在Startup.cs文件的Configure中加入回退路由:

app.UseEndpoints(endpoints =>
{endpoints.MapBlazorHub();endpoints.MapFallbackToPage("/_Host");
});

这里把这个_Host.cshtml登记为回退路由,作用是把所有请求到 Razor 的页面,先路由到这个页面中,由这个页面做最终合成。

这个页面中必须有的元素为:

  • @page,定义这个页面的访问点

  • @namespace,当前页面的namespace

  • addTagHelper,标记帮助

  • base,定义这个页面的路由起始

  • app,这一句是这个页面的核心。我们后边创建的Razor页面,会以一个组件的形式,放在这个位置

  • script,用来跟服务器通讯

上面的代码中,调用到一个typeof(App),这个App,是路由组件。下面我们来创建这个路由 - 创建一个App.razor

<Router AppAssembly="@typeof(Program).Assembly"><Found Context="routeData"><RouteView RouteData="@routeData" /></Found><NotFound>Page Not found</NotFound>
</Router>

这个模板的用处,是在 Dotnet 编译时.razor时,为带有@page的类提供指定的路由模板属性RouteAttribute,同时,也映射出了上面说的App类。

运行。浏览器中会出现Page Not Found。这是我们在App.razor里定义的,表明我们没有找到任何可用的路由。

三、创建一个页面

下面,我们来创建一个页面index.razor

@page "/"<h1>Hello, world!</h1>

这个页面简单。

@page,告诉路由这个页面的URL是/

再运行,我们就看到了这个页面。

@page定义的是这个页面的路由。路由有以下几种样式,我简单列一下:

  • 直接路由:/page

  • 参数路由:/page/{page_id}

  • 约束路由:/page/{page_id: int}

四、创建一个布局模板

我们先在项目中创建一个目录Shared,用来存放各种组件和模板。在目录中,我们创建一个布局模板 - MainLayout.razor

@using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase<div><h3>This is layout</h3>
</div>
@Body

这里面有几个重点:

  • 布局模板必须继承自类LayoutComponentBase

  • @Body定义了引用布局的页面的内容位置

  • Body的数据类型是RenderFragment,在Microsoft.AspNetCore.Components中,需要引用

其实这些操作,都是C#的结构,只不过用了Razor,换了一种写法

下面,我们给刚才的Index.razor加入布局模板:

@using demo.Shared
@layout MainLayout

只要在Index.razor代码的最上边加上这两行就行。这两行中:

@layout是定义这个页面用哪个布局模板的;而@using是引用这个模板的位置,就是 C# 中的using

运行,我们就看到,这个布局加到页面前边了。

五、设置默认布局引用

上面的例子,是把布局给到一个页面。

我们也可以设置所有页面的默认布局模板,通过改动路由模板App.razor

@using demo.Shared<Router AppAssembly="@typeof(Program).Assembly"><Found Context="routeData"><RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /></Found><NotFound>Page Not Found</NotFound>
</Router>

对方前边的文件内容,这一段,仅仅在RouteView中加了一个DefaultLayout

现在,所有的页面都默认加上了布局模板。

六、设置默认命名空间引用

上面的例子,在App.razorIndex.razor中,我们都引用了demo.Shared命名空间。

Blazor提供了一个默认的文件,叫_Imports.razor,用来存放所有.razor文件中共同的引用。

@using demo.Shared

我们把引用加到这个文件中,同时把上面两个.razor中的引用去掉,就完成了。

*这儿也多说一句:布局模板也可以在这里引用。布局模板的引用优先级是:页面引用 > _Imports.razor引用 > App.razor 引用。

以上就是Blazor Server的项目结构。做好这个结构后,所有的功夫,就只在 Razor 页面了。

(全文完)

本文的代码在https://github.com/humornif/Demo-Code/tree/master/0017/demo

喜欢就来个三连,让更多人因你而受益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Factory Method(工厂方法)--对象创建型模式

Factory Method&#xff08;工厂方法&#xff09;–对象创建型模式 一、意图 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。 二、动机 1.在软件系统中&#xff0c;经常面临着创建对象的工作;由于需求的变化…

[计组]寄存器和存储器的区别

寄存器存在于CPU中&#xff0c;速度很快&#xff0c;数目有限&#xff1b; 存储器是内存&#xff0c;速度稍慢&#xff0c;但数量很大。 寄存器的功能是存储二进制代码&#xff0c;是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码&#xff0c;故存…

全内存的redis用习惯了?那能突破内存限制类redis产品ssdb呢?

首先说一下背景&#xff0c;在双十一的时候&#xff0c;我们系统接受X宝的订单推送&#xff0c;原先的实现方式是使用 redis 的 List 作为推送数据的承载&#xff0c;在非大促的场景下&#xff0c;一切运行正常&#xff0c;内存占用大概3-4G&#xff0c;机器是16G内存。由于提前…

Prototype(原型)--对象创建模式

Prototype&#xff08;原型&#xff09;–对象创建模式 一、意图 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。 二、动机 1.在软件系统中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作&#xff1b;由于需求的变化&#xff0c;这些…

[计组]寄存器的基本含义

寄存器基本含义&#xff1a; 寄存器是CPU内部用来存放数据的一些小型存储区域&#xff0c;用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路&#xff0c;但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的&#xff0c…

认证授权方案之授权揭秘 (上篇)

一、前言回顾&#xff1a;认证授权方案之授权初识从上一节中&#xff0c;我们在对授权系统已经有了初步的认识和使用&#xff0c;可以发现&#xff0c;asp.net core为我们提供的授权策略是一个非常强大丰富且灵活的认证授权方案&#xff0c;能够满足大部分的授权场景。在Config…

Singleton(单件)--对象创建模式

Singleton&#xff08;单件&#xff09;–对象创建模式 一、意图 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 二、动机 1.在软件系统中&#xff0c;经常有这样一些特殊的类&#xff0c;必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的…

[计组]断定方式

断定方式: 微地址的形成方法之一。 断定方式&#xff1a;根据机器状态决定下一条微指令的地址&#xff0c;下一条微指令的地址包含在当前微指令的代码中。 这是一种直接给定微地址和测试判定地址相结合的方式。为了实现多路分支&#xff0c;将微地址的若干低位作为可断定的部分…

龙芯团队 在移值 MIPS64 下的.NET Core 进度速报

写在开始前我们的主要业务基于 dotnet core 2.x 与 3.1 完成&#xff0c;目前 dotnet core 3.1 支持的 CPU 架构列表中还不包含龙芯&#xff0c;且在 gitlab issue 中表示官方当前没有对 MIPS 的支持计划。更具体操作系统与 CPU 架构列表见 [Download .NET Core 3.1](https://d…

Adapter(适配器)--类对象结构型模式

Adapter&#xff08;适配器&#xff09;–类对象结构型模式 一、意图 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本接口不兼容而不能一起工作的那些类可以一起工作。 二、动机 1.在软件系统中&#xff0c;由于应用环境的变化&#xff0c;常常需要将“一…

[计组]压缩BCD码指二进制编码的十进制

压缩BCD码指二进制编码的十进制 压缩BCD码指一个字节8位存储2位BCD码。比如32用8421BCD码表示如下&#xff1a;非压缩BCD码表示&#xff1a;00000011 00000010&#xff1b;压缩BCD码表示&#xff1a;0011 0010&#xff1b;使用BCD码表示10进位制数字比较好理解&#xff0c;且占…

如何使用ABP框架(2)三层架构与领域驱动设计的对比

本文来自长沙.NET技术社区&#xff0c;原创&#xff1a;邹溪源。全文共有8500字&#xff0c;读完需耗时10分钟。题图来自pixabay简述上一篇简述了ABP框架中的一些基础理论&#xff0c;包括ABP前后端项目的分层结构&#xff0c;以及后端项目中涉及到的知识点&#xff0c;例如DTO…

Bridge(桥接)--对象结构模式

Bridge&#xff08;桥接&#xff09;–对象结构模式 一、意图 将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立的变化。 二、动机 1.由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;乃至多个纬度的变化。 2.如何应对这种“多维度…

自然数,实数,有理数,整数,分数,无理数

自然数&#xff1a;即非负整数 实数&#xff1a;包括有理数和无理数 有理数&#xff1a;整数、分数 整数包括&#xff1a;0、正整数和负整数 分数&#xff1a;包括正分数和负分数 无理数&#xff1a;无限不循环小数 自然数用以计量事物的件数或表示事物次序的数。即用数码…

数学中R,Z,N,Q都代表什么意思?

N&#xff1a;非负整数集合或自然数集合{0,1,2,3,…n} R&#xff1a;实数集合(包括有理数和无理数&#xff09; Z&#xff1a;整数集合{…,-1,0,1,…} Q&#xff1a;有理数集合 N*/ N&#xff1a;正整数集合{1,2,3,…n} 在数学中没有用Z*表示的概念。 其他常见集合符号&a…

Composite(组合)--对象结构型模式

Composite&#xff08;组合&#xff09;–对象结构型模式 一、意图 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 二、动机 1.软件在某些情况下&#xff0c;客户代码过多的依赖于对象容器复杂的内部实现结构…

魔幻艰难的2020上半年!

阅读本文大概需要 2.8分钟。告诉大家一个很震惊的消息&#xff01;2020年已度过一半&#xff01;在过去这半年的时间里&#xff0c;这个世界发生了巨大变化&#xff0c;并且很难恢复如初。2019年的最后一天&#xff0c;罗胖在跨年演讲中借用何帆老师的一句话与众人共勉&#xf…

[SpringBoot2]ajax函数中data参数的数据设置方式

ajax函数中data参数的数据设置方式&#xff1a;

Blazor带我重玩前端(二)

概览Blazor目前有两种托管模式&#xff0c;一种是Server-Side模式&#xff0c;一种是WebAssembly模式。官方首先支持的是Service-Side模式&#xff0c;使用WebAssembly模式&#xff0c;需要更新到最新版VS2019。小编目前的精力是更多的专注于Blazor-WebAssembly模式的研究&…

Decorator(装饰)--对象结构型模式

Decorator&#xff08;装饰&#xff09;–对象结构型模式 一、意图 1.动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;Decorator模式相比生成子类更为灵活。 二、动机 1.在某些情况下我们可能会“过度地使用继承来扩展对象的功能”&#xff0c; 由于继承为类…