Blazor

Blazor他是一个开源的Web框架,不,这不是重点,重点是它可以使c#开发在浏览器上运行Web应用程序.它其实也简化了SPA的开发过程.

Blazor = Browser + Razor

为什么选择Blazor?

Blazor可以让.NET附有全栈开发功能,它可以使Web开发变得轻松而高效.而且Blazor是开源的,它得到了社区的大力支持,而且发展速度会很快.

它还拥有SPA的一些功能比如:

  • 路由
  • 依赖注入
  • 服务端渲染
  • Layout

    等等

创建应用

如果说无法在看到Blazor WebAssembly App那么执行如下命令即可.

dotnet new -i Microsoft.AspNetCore.Components.WebAssembly.Templates::3.2.0-preview5.20216.8

项目结构如下所示

我们可以看到上图中的项目结构

  • BlazorServerCRUDSample.Client:该项目工程中包含了客户端的相关代码页面等文件
  • BlazorServerCRUDSample.Server:该项目工程中包含了webapi.
  • BlazorServerCRUDSample.Shared:该类库中用于存放客户端和服务端之间的共享代码.

BlazorServerCRUDSample.Server

控制器代码如下所示

    [Route("api/[controller]")]
public class StudentController : Controller
{
private readonly Shared.Data.AppContext _dbcontext; public StudentController(Shared.Data.AppContext dbcontext)
{
this._dbcontext = dbcontext;
}
[HttpGet]
public async Task<List<Student>> Get()
{
return await _dbcontext.Students.AsQueryable().ToListAsync();
}
[HttpGet("{id}")]
public async Task<Student> Get(int id)
{
return await _dbcontext.Students.FindAsync(id);
}
[HttpPost]
public async Task Post([FromBody] Student student)
{
student.CreateTime = DateTime.Now;
if (ModelState.IsValid)
await _dbcontext.AddAsync(student);
await _dbcontext.SaveChangesAsync();
}
[HttpPut]
public void Put([FromBody] Student student)
{
if (ModelState.IsValid)
_dbcontext.Update(student);
_dbcontext.SaveChanges();
}
[HttpDelete("delete/{id}")]
public void Delete(int id)
{
var entity = _dbcontext.Students.Find(id);
_dbcontext.Students.Remove(entity);
_dbcontext.SaveChanges();
} }
    public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
} public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseConfiguration(new ConfigurationBuilder()
.AddCommandLine(args)
.Build())
.UseStartup<Startup>()
.Build();
}

对于Startup类,我们可以看到在开发模式下,启动Blazor调试,并且我们可以看到我们通过UseClientSideBlazorFiles来启动我们的客户端Startup


public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddResponseCompression();
services.AddDbContext<AppContext>(options =>
{
options.UseSqlServer("Data Source=.;Initial Catalog=BlazorServerCRUDSample;User ID=sa;Password=sa;MultipleActiveResultSets=true;");
});
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression(); if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBlazorDebugging();
} app.UseStaticFiles();
app.UseClientSideBlazorFiles<Client.Startup>(); app.UseRouting(); app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
});
}
}

BlazorServerCRUDSample.Client

如下所示我创建了一个列表页面,在代码中我们可以看到@page他定义了该页面的url,当然在razor中也是这样的,而且下最下面我通过HttpClient进行我们的api调用,在这 System.Net.Http.Json这篇文章中我们也可以看到他简直就是为了我们blazor而生的大大减少了我们的代码量.

而且在我的代码中最后一部分有一个@functions片段,它包含了页面所有的业务逻辑,在我们页面初始化时我们通过OnInitializedAsync方法进行调用我们的api然后将其进行填充赋值并填充到我们的html中.

@page "/fetchstudent"
@inject HttpClient Http
@using BlazorServerCRUDSample.Shared.Models <h1>Students</h1>
<p>
<a href="/addstudent">Create New</a>
</p>
@if (students == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class='table'>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>CreateTime</th>
</tr>
</thead>
<tbody>
@foreach (var student in students)
{
<tr>
<td>@student.Id</td>
<td>@student.Name</td>
<td>@student.Description</td>
<td>@student.CreateTime</td>
<td>
<a href='/editstudent/@student.Id'>Edit</a> |
<a href='/delete/@student.Id'>Delete</a>
</td>
</tr> }
</tbody>
</table>
} @functions {
Student[] students;
protected override async Task OnInitializedAsync()
{
students = await Http.GetJsonAsync<Student[]>("api/student");
}
}

如下代码中我们还是对我们的页面提供了url,其中Id是将从url中的参数传递到我们的@functions代码中,在Id上面指定 [Parameter] 属性,该属性指定的就是url中的参数值.在这我们通过使用 @bind 来将我们的html组件和类对象进行双向绑定.

@page "/editstudent/{Id}"
@inject HttpClient Http
@using BlazorServerCRUDSample.Shared.Models
@inject Microsoft.AspNetCore.Components.NavigationManager Navigation <h2>Edit Student</h2>
<hr />
<div class="row">
<div class="col-md-4">
<form @onsubmit="@(async () => await UpdateStudent())">
<div class="form-group">
<label for="Name" class="control-label">Name</label>
<input for="Name" class="form-control" @bind="@student.Name" />
</div>
<div class="form-group">
<label asp-for="Description" class="control-label">Description</label>
<textarea asp-for="Description" class="form-control" @bind="@student.Description"> </textarea>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
<input type="submit" value="Cancel" @onclick="@cancel" class="btn btn-warning" />
</div>
</form>
</div>
</div> @functions {
[Parameter]
public string id { get; set; }
public Student student = new Student();
protected override async Task OnInitializedAsync()
{
student = await Http.GetJsonAsync<Student>("/api/Student/" + Convert.ToInt32(id));
}
protected async Task UpdateStudent()
{
await Http.SendJsonAsync(HttpMethod.Put, "api/Student", student);
Navigation.NavigateTo("/fetchstudent");
}
void cancel()
{
Navigation.NavigateTo("/fetchstudent");
}
}

在ConfigureServices方法中,可以在依赖项注入容器中注册本地服务。

   public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
} public void Configure(IComponentsApplicationBuilder app)
{
app.AddComponent<App>("app");
}
}

BlazorWebAssemblyHost可以用于在DI容器中定义接口和实现。

    public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
BlazorWebAssemblyHost.CreateDefaultBuilder()
.UseBlazorStartup<Startup>();
}

Blazor可以基于服务端运行但是需要注意服务端的话需要为每一个客户端打开连接,并且我们必须一直与服务端保持连接才行.如果说切换到WebAssembly客户端版本,限制是完全不同的,但是目前来说的话他首次需要下载一些运行时文件到浏览器中.

通过如上代码我们可以看到一个简单的blazor应用程序的建立,详细代码的话大家可以看一下github仓库中的内容.通过源码的话直接启动BlazorServerCRUDSample.Server即可,希望可以通过本示例帮助到你~共同学习共同进步.

Reference

https://github.com/hueifeng/BlazorCRUDSample

https://www.cnblogs.com/shanyou/p/12825845.html

Blazor一个简单的示例让我们来起飞的更多相关文章

  1. 使用Express创建一个简单的示例

    1.安装Express 使用npm包安装工具来安装Express安装包,打开npm命令行,输入: npm install -g express 2.创建一个工程 本示例是在windows下创建的,项目 ...

  2. Postman----登录接口返回的reponse中token值传递给其他接口的一个简单接口测试示例

    注: 在进行接口测试时,我们都需要使用登录,并且其他的接口都要在登录后进行,那么必不可少的会使用到将登录接口的reponse返回结果中的某些参数值需要进行返回,并传递给其他接口,这样才可以进行登录后的 ...

  3. mxnet:基础知识和一个简单的示例

    NDArray与NumPy的多维数组类似,但NDArray提供了更多的功能:GPU和CPU的异步计算:自动求导.这使得NDArray能更好地支持机器学习. 初始化 from mxnet import ...

  4. 一个简单的示例在spring boot中实现国际化

    最近在网上找了一个有关账单管理的spring boot项目,其中有一部分是涉及显示国际化信息的,即将页面上的中英文进行转换.因为在这之前这部分内容没有接触过,所以在这记录下过程. 中文效果图如下所示: ...

  5. Hibernate操作指南-搭建一个简单的示例(基于Java Persistence API JPA)

  6. Hibernate操作指南-搭建一个简单的示例(基于原生API和注解)

  7. Hibernate操作指南-搭建一个简单的示例(基于原生API和XML)

  8. python+requests----登录接口reponse中token传递给其他接口使用的一个简单小示例介绍

    #!/usr/bin/env python # coding=UTF-8 import requests def login(): url = "https://xxxx.xxx.xxx/v ...

  9. IDDD 实现领域驱动设计-一个简单的 CQRS 示例

    上一篇:<IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)> 学习架构知识,需要有一些功底和经验,要不然你会和我一样吃力,CQRS.EDA.ES.Saga ...

随机推荐

  1. lr事务

    事务:transaction(性能里面的定义:客户机对服务器发送请求,服务器做出反应的过程) 用于模拟用户的一个相对完整的业务操作过程:如登录,查询,交易等操作(每次http请求不会用来作为一个事务) ...

  2. 谨慎使用keySet:对于HashMap的2种遍历方式比较

    HashMap存储的是键值对,所以一般情况下其遍历同List及Set应该有所不同. 但java巧妙的将HashMap的键值对作为一个整体对象(java.util.Map.Entry)进行处理,这优化了 ...

  3. Android UIAutomator自动化测试

    描述:UiAutomator接口丰富易用,可以支持所有Android事件操作,事件操作不依赖于控件坐标,可以通过断言和截图验证正确性,非常适合做UI测试. UIAutomator不需要测试人员了解代码 ...

  4. 选择IT行业的自我心得,希望能帮助到各位!(四)

    俗话说,只有尝过人生的苦,吃过人生的亏,你才能吃一见长一智,人生教会了我们该如何去吃亏,该如何做人,该如何和人打交道,生活会让我们低下无数的头,就看你怎么去面对这些曲折该如何告诉自己不能就被这样打到, ...

  5. Obtain The String CodeForces - 1295C binary_search+思维

    妈耶,,,被B题卡到哭,C题一发就过了... 字符串问题.首先用vector记录每个字符出现的位置,然后对字符串t的每个字符,用二分查找函数查找,注意用upper_bound查找,对于字符i,首先用变 ...

  6. 关于树的重心--POJ 1655

    树的重心的定义: 在一棵树中,找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 通俗来说就是以这个点为根节点,找到他最大的衣蛾子树,然后 ...

  7. JAVA的synchronized写法

    使用关键字synchronized的写法比较多,常用的有如下几种,代码如下: public class MyService { synchronized public static void test ...

  8. SpringCloud(三)学习笔记之Ribbon

    spring Cloud Ribbon 是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制. 客户端负载均衡即是当浏览器向后台发出请求的时候,客户端会向 Eureka Serve ...

  9. 基于MySQL Binlog的Elasticsearch数据同步实践

    一.为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品.订单等数据的多维度检索. 使用 Elasticsearch 存储业务数 ...

  10. 纯css画三角形

    纯css画三角形与border元素相关 设置border的属性 width: 100px; height: 100px; border-style: solid; border-width: 100p ...