ASP.NET Core Blazor 2:使用 Blazor Server (1)

Blazor Server 的登录与退出(一) 如果自学Blazor ,因为增加了许多知识点,有许多问题会是一头雾水,难以理清。Blazor Server 的登录与退出就是一个非常难以理清的问题,因为我有强迫症,既然用了Blazor,我难道又要退回去用Razor Page?新建立的Blazor Server程序,使用Identity的个人标识账户,它的登录与退出默认使用的是Razor Page,因为它能非常清晰地得到ClaimsPrincipal 的User,和不支持Razor组件,特别是所以想抛开Razor Page,它的登录与退出只能另想办法,好像一 阅读详情

  Blazor 是 ASP.NET Core 新添加的一个功能,它向 Web 应用程序添加客户端交互性。Blazor 有两个变种,本章将重点介绍 Blazor Server,另一种是 Blazor WebAssembly。解释它解决的问题和它是如何工作的。展示如何配置 ASP.NET Core应用程序来使用 Blazor Server,并描述使用 Razor 组件时可用的基本特性,这是 Blazor Server项目的构建块。
  Blazor Server使用 JavaScript 来接收浏览器事件,这些事件转发给 ASP.NET Core,使用 C#代码计算。事件对应用程序状态的影响发送回浏览器,并显示给用户。
  本章介绍 Blazor Server,解释它解决的问题,并描述了它的优缺点。展示如何配置ASP.NET Core 应用程序来启用 Blazor Server,并展示使用 Razor 组件时可用的基本特性,这些组件是 Blazor 的构建块。

1 准备工作

  本章继续使用上章项目。

2 理解 Blazor Server

2.1 Blazor Server 的优势

  Blazor 最大的吸引力在于它基于 C# 编写的 Razor Pages。这意味着不需要学习新框架(如Angular 或 React)和新语言,就可提高效率和响应能力。Blazor 很好地集成到 ASP.NET Core 的其余部分中,构建在前面章节中描述的特性之上,这使得它易于使用。

2.2 Blazor Server 的缺点

  Blazor 需要一个现代浏览器来建立和维护它的持久 HTTP 连接。而且,如果这种连接丢失,使用 Blazor 的应用程序就会停止工作,这使得它们不适合离线使用,也就是不能依赖连接或者连接速度很慢的地方。Blazor WebAssembly 解决了这些问题,但是,它自己的局限性。

3 从 Blazor 开始

3.1 为 Blazor Server 配置 ASP.NET Core

  Startup.cs 文件中添加服务和中间件。

services.AddServerSideBlazor();
endpoints.MapBlazorHub();

1.给布局添加 Blazor JavaScript 文件
  Blazor 依赖 JavaSaipt 代码与 ASP.NET Core 服务器进行通信,在 Views/Shared 文件夹的 _Layout.cshtml 中将JavaScript文件添加到控制器视图使用的布局中。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    <base href="~/" />
    </head>
<body>
    <div class="m-2">
        @RenderBody()
        </div>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

  script 元素指定 JavaScript 文件的名称,对它的请求被添加到请求管道中的中间件拦截,因此不需要额外的包将 JavaScript 代码添加到项目中。还必须添加基本元素以指定应用程序的根 URL。同样的元素必须添加到 Razor Pages 使用的布局中。2.创建 Blazor 导入文件
  添加一个名为 _Imports.razor 的文件。如果使用的是 Visual Sudio,可以使用 Razor View Imports 模板来创建这个文件,但是要确保使用 .Razor 文件扩展名。

@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Microsoft.EntityFrameworkCore
@using MyAdvanced.Models

3.2 创建 Blazor 组件

  这里有一个术语上的冲突:技术是 Blazor,但关键的构建块称为 Razor 组件。Razor 组件是在扩展名为 .Razor 的文件中定义的,并且必须以大写字母开头。组件可以在任何地方定义,但它们通常组合在一起,以帮助保持项目的组织性。
  创建一个 Blazor 文件夹,并添加一个名为 PeopleList. Razor 的 Razor 组件。

<table class="table table-sm table-bordered table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Dept</th>
            <th>Location</th>
        </tr>
    </thead>
    <tbody>
        @foreach (Person p in People)
        {
            <tr class="@GetClass(p.Location.City)">
                <td>@p.PersonId</td>
                <td>@p.Surname, @p.Firstname</td>
                <td>@p.Department.Name</td>
                <td>@p.Location.City, @p.Location.State</td>
            </tr>
        }
    </tbody>
</table>

<div class="form-group">
    <label for="city">City</label>
    <select name="city" class="form-control" @bind="SelectedCity">
        <option disabled selected>Select City</option>
        @foreach (string city in Cities)
        {
            <option value="@city" selected="@(city == SelectedCity)">
                @city
            </option>
        }
    </select>
</div>

@code
{
    [Inject]
    public DataContext Context { get; set; }

    public IEnumerable<Person> People =>
        Context.People.Include(p => p.Department).Include(p => p.Location);

    public IEnumerable<string> Cities => Context.Locations.Select(l => l.City);

    public string SelectedCity { get; set; }

    public string GetClass(string city) =>
        SelectedCity == city ? "bg-info text-white" : "";
}

  Razor 组件类似于 Razor Pages。视图部分依赖于在前面章节中看到的 Razor 特性,使用@表达式将数据值插入组件的 HTML中,或者以序列化方式为对象生成元素。这个@foreach 表达式为 Cities 序列中的每个值生成 option 元素。
  尽管 Razor 组件看起来很熟悉,但有一些重要的区别。第一个是没有页面模型类和 @mode 表达式。支持组件 HTML 的属性和方法直接在 @code 表达式中定义,该表达式与 Razor Pages 的 @functions 表达式对应。例如,要定义向视图部分提供 Person 对象的属性,只需要在@code 部分中定义一个 People 属性。
  而且,因为没有页面模型类,所以没有用于声明服务依赖关系的构造函数。相反,依赖注入会设置已被 [Inject] 特性修饰的属性值。最显著的区别是在 select 元素上使用了特殊属性 @bind,在 select 元素的值和 @code 部分中定义的 SelectedCity 属性之间创建一个数据绑定。使用 Razor 组件
  Razor 组件作为 Razor Pages 或控制器视图的一部分交付给浏览器。在 Views/Home 文件夹的 Index.cshtml 文件中使用 Razor 组件。

@model PeopleListViewModel
<h4 class="bg-primary text-white text-center p-2">People</h4>
<component type="typeof(MyAdvanced.Blazor.PeopleList)" render-mode="Server" />

  Razor 组件是使用组件元素应用的,对于组件元素有一个标签助手。组件元素使用 type 和 render-mode 属性配置。type 属性用于指定 Razor 组件。Razor 组件编译成类,就像控制器视图和 Razor Pages 一样。render-mode 属性用于选择组件如何使用 RenderMode 枚举中的值生成内容,如下表:

名称描述
StaticRazor 组件将其视图部分呈现为不支持客户端的静态 HTML
ServerHTML 文档连同组件的占位符一起发送到浏览器。组件显示的 HTML 通过持久 HTTP 连接发送
到浏览器并显示给用户
ServerPrerendered组件的视图部分包含在 HTML 中,并立即显示给用户。HTML 内容将通过持久 HTTP 连再次发送

  对于大多数应用程序,Server 选项是一个不错的选择。ServerPrerendered 在发送到浏览器的 HTML 文档中包含了 Razor 组件视图部分的静态再现。它充当占位符内容,这样在加载和执行 JavaScript 代码时,用户不会看到空的浏览器窗口。一旦建立了持久 HTTP 连接,占位符内容将被删除,替换为 Blazor 发送的动态版本。向用户显示静态内容的想法是好的,但它可以被混淆,因为 HTML元素没有连接到应用程序的服务器端部分,与任何用户交互失效或一旦动态内容到来HTML 元素就会被丢弃。
  要查看 Blazor 的运行情况,使用浏览器请求 http://localhost:5000/controllers。在使用 Blazor 时不需要提交表单,因为一旦更改了 select 元素的值,数据绑定就会响应。

  Razor 组件也可在 Razor Pages 中使用。将一个名为 Blazor.cshtml 的 Blazor 页面添加到 Pages 文件夹中。请求 http://localhost:5000/pages/blazor。

@page "/pages/blazor"
<h4 class="bg-primary text-white text-center p-2">Blazor People</h4>
<component type="typeof(MyAdvanced.Blazor.PeopleList)" render-mode="Server" />

4 理解 Razor 组件的基本特性

4.1 理解 Blazor 事件和数据绑定

  事件允许 Razor 组件响应用户的交互,Blazor 使用持久的 HTTP 连接将事件的详细信息发送到可以处理它的服务器。要査看 Blazor 事件的运行情况,为 Blazor文件夹添加 Events.razor 的 Razor 组件。

<div class="m-2 p-2 border">
    <button class="btn btn-primary" @onclick="IncrementCounter">
        Increment
    </button>
    <span class="p-2">Counter Value:@Counter</span>
</div>

@code
{
    public int Counter { get; set; } = 1;
    public void IncrementCounter(MouseEventArgs e)
    {
        Counter++;
    }
}

  向 HTML元素添加属性,可注册事件处理程序,其中属性名称为@onclick,后面跟着事件名称。在这个例子中,为 button 元素生成的 click 事件设置了一个处理方法。
  赋给属性的值是在触发事件时调用的方法的名称。该方法可以定义一个可选参数,该参数要么是 EventArgs 类的实例,要么是 EventArgs 派生的类,提供关于事件的附加信息。
  对于 onclick 事件,处理程序方法接收一个 MouseEventArgs 对象,该对象提供额外的细节,比如单击的屏幕坐标。
  Blazor JavaScript 代码在事件触发时接收事件,并通过持久 HTTP 连接将其转发给服务器。调用处理程序方法,并更新组件的状态。对组件的视图部分生成的内容的任何更改都将发送回 JavaScript 代码,JavaScript 代码将更新浏览器显示的内容。
  在本例中,单击事件将由 IncrementCounter方法处理,该方法会更改 Counter 属性的值。Counter 属性的值包含在组件呈现的 HTML 中,因此 Blazor 将更改发送到浏览器,以便 JavaScript 代码可以更新显示给用户的 HTML 元素。
  要显示 Events 组件,请替换 Pages 文件夹中 Blazor.cshtml 文件的内容。

@page "/pages/blazor"
<h4 class="bg-primary text-white text-center p-2">Events</h4>
<component type="typeof(MyAdvanced.Blazor.Events)" render-mode="Server" />

1.处理来自多个元素的事件
  为避免代码重复,一个处理程序方法可以接收来自多个元素的操作。以下在 Blazor 文件夹的 Events.razor 文件中处理事件:

</div>
<div class="m-2 p-2 border">
    <button class="btn btn-primary" @onclick="@(e=>IncrementCounter(e,1))">
        Increment Counter #2
    </button>
    <span class="p-2">Counter Value:@Counter[1]</span>
</div>

@code
{
    public int[] Counter { get; set; } = new int[] { 1, 1 };
    public void IncrementCounter(MouseEventArgs e, int index)
    {
        Counter[index]++;
    }
}

  Blazor 事件属性可与 lambda 函数一起使用,后者接收 EventArgs 对象并调用带有附加参数的处理程序方法。本例向 IncrementCounter 方法添加了一个索引参数,该参数用于确定应该更新哪个计数器值。
  当以编程方式生成元素时,也可以使用这种技术,如下:

@for (int i = 0; i < ElementCount; i++)
{
    int local = i;
    <div class="m-2 p-2 border">
        <button class="btn btn-primary" @onclick="@(() => IncrementCounter(local))">
            Increment Counter #@(i + 1)
        </button>
        <span class="p-2">Counter Value: @GetCounter(i)</span>
    </div>
}

@code
{
    public int ElementCount { get; set; } = 4;

    public Dictionary<int, int> Counters { get; } = new Dictionary<int, int>();

    public int GetCounter(int index) =>
        Counters.ContainsKey(index) ? Counters[index] : 0;

    public void IncrementCounter(int index) =>
        Counters[index] = GetCounter(index) + 1;
}

  本例使用 @for 表法式来生成元素,并使用循环变量作为处理程序方法的参数。还从处理程序方法中删除了 EventArgs 参数。2.避免处理程序方法名的陷阱
  在指定事件处理程序方法时,最常见的错误是包含括号@onclick="Incrementcounter()",当指定一个处理程序方法时,必须只指定事件名@onclick="IncrementCounter",可以将方法名指定为 Razor 表达式@onclick="@IncrementCounter"。
  在使用 lambda 函数时,有一组不同的规则,在 Razor 表达式中,lambda 函数的定义就像它在 C#类中的定义一样,这意味着定义参数,后跟箭头,再跟函数体,@onclick="@((e)=> HandleEvent(e, local)),如果不需要使用 EventArgs 对象,那么可以忽略 lambda 函数的参数,@onclick="@(()=> IncrementCounter (local))"。
  请求http://localhost:5000/pages/blazor,所有 button 元素生成的 click 事件由相同的方法处理,但是 lambda 函数提供的参数确保更新了正确的计数器。3.不使用处理程序方法处理事件
  简单的事件处理可直接在 lambda 函数中完成,而不需要使用处理程序方法:

<button class="btn btn-info" @onclick="@(()=>Counters.Remove(local))">Reset</button>

4.2 使用数据绑定

  事件处理程序和 Razor 表达式可用于创建 HTML 元素和 C# 值之间的双向关系,这对于允许用户进行更改的元素(如输入和选择元素)非常有用。为 Blazor 文件夹添加名为 Bindings.razor 的 Razor 组件:

<div class="form-group">
    <label>City:</label>
    <input class="form-control" value="@City" @onchange="UpdateCity" />
</div>
<div class="p-2 mb-2">City Value: @City</div>
<button class="btn btn-primary" @onclick="@(() => City = "Paris")">Paris</button>
<button class="btn btn-primary" @onclick="@(() => City = "Chicago")">Chicago</button>

@code 
{
    public string City { get; set; } = "London";
    public void UpdateCity(ChangeEventArgs e)
    {
        City = e.Value as String;
    }
}

  @onchange 属性将 UpdateCity 方法注册为来自输入元素的更改事件的处理程序。这些事件是使用 ChangeEventArgs 类描述的,该类提供了一个 Value 属性。每次接收到更改事件时,都会更新 City。
  input 元素的 value 属性创建了另一个方向的关系,这样当 City 属性的值发生变化时,元素的 value 也会变化。
  Pages 文件夹的 Blazor.cshtml文件中使用 Razor 组件:

<component type="typeof(MyAdvanced.Blazor.Bindings)" render-mode="Server" />

  请求http://localhost:5000/pages/blazor,更改 input 值或点击 button 会同时更改绑定的值。
  涉及变更事件的双向关系可表示为数据绑定,数据绑定允许值和事件都用单个属性配置,如下:

<div class="form-group">
    <label>City:</label>
    <input class="form-control" @bind="City" />
</div>
<div class="p-2 mb-2">City Value: @City</div>
<button class="btn btn-primary" @onclick="@(() => City = "Paris")">Paris</button>
<button class="btn btn-primary" @onclick="@(() => City = "Chicago")">Chicago</button>

@code 
{
    public string City { get; set; } = "London";
    //public void UpdateCity(ChangeEventArgs e)
    //{
    //    City = e.Value as String;
    //}
}

  @bind 属性用于指定在更改事件触发时更新的属性,以及在 Value 属性更改时更新的属性。1.更改绑定事件
  默认情况下,绑定中使用更改事件,为用户提供了合理的响应性,如下:

名称描述
@bind-value此属性用于选择数据绑定的属性
@bind-value:event此属性用于选择数据绑定的事件

  这些属性替代了@bind,如下所示:

<input class="form-control" @bind-value="City" @bind-value:event="oninput" />

  这个属性组合为 City 属性创建了一个绑定,该属性在触发 oninput 事件时(每次击键后)更新而不是只在输入元素失去焦点时更新。2.创建 DateTime 绑定
  Blazor 特别支持为 DateTime 属性创建绑定,允许使用特定区域性或格式字符串表示它们。参数如下:

名称描述
@bind:culture此属性用于选择 CultureInfo 对象(用于格式化 DateTime 值)
@bind:format此属性用于指定一个数据格式化字符串(用于格式化 DateTime 值)

  在 Blazor 文件夹的 Bindings.razor 文件中使用 DateTime 属性:

@using System.Globalization

<div class="form-group">
    <label>City:</label>
    <input class="form-control" @bind-value="City" @bind-value:event="oninput" />
</div>
<div class="p-2 mb-2">City Value: @City</div>
<button class="btn btn-primary" @onclick="@(() => City = "Paris")">Paris</button>
<button class="btn btn-primary" @onclick="@(() => City = "Chicago")">Chicago</button>

<div class="form-group mt-2">
    <label>Time:</label>
    <input class="form-control my-1" @bind="Time" @bind:culture="Culture"
        @bind:format="MMM-dd" />
    <input class="form-control my-1" @bind="Time" @bind:culture="Culture" />
    <input class="form-control" type="date" @bind="Time" />
</div>
<div class="p-2 mb-2">Time Value: @Time</div>

<div class="form-group">
    <label>Culture:</label>
    <select class="form-control" @bind="Culture">
        <option value="@CultureInfo.GetCultureInfo("en-us")">en-US</option>
        <option value="@CultureInfo.GetCultureInfo("en-gb")">en-GB</option>
        <option value="@CultureInfo.GetCultureInfo("fr-fr")">fr-FR</option>
    </select>
</div>

@code
{
    public string City { get; set; } = "London";
    public DateTime Time { get; set; } = DateTime.Parse("2050/01/20 09:50");
    public CultureInfo Culture { get; set; } = CultureInfo.GetCultureInfo("en-us");
}

  有三个输入元素用于显示相同的 DataTime 值,其中两个使用表中的属性配置。第一个元素配置了区域和格式字符串,<input class="form-control my-1" @bind="Time" @bind:culture="Culture" @bind:format="MMM-dd" />,使用在 select 元素中选择的区域以及显示缩写月份名称和数字日期的格式字符串来显示DateTime 属性。第二个输入元素只指定区域,这意味着将使用默认的格式化字符串。
  将 type 属性设置为 date、datetime-local、month或 time 时,不应指定区域或格式字符串,因为Blazor 自动将日期值格式化为区域无关的格式,浏览器将其转换为用户的语言环境。

5 使用类文件定义组件

  如果不喜欢 Razor 组件支持的代码和标记的混合,可以使用 C# 类文件来定义一部分组件或全部组件。

5.1 使用代码隐藏类

  Razor 组件的 @code 部分可在单独的类文件中定义,称为代码隐藏类或代码隐藏文件。Razor 组件的代码隐藏类定义为部分类,其名称与为其提供代码的组件相同。
  给 Blazor 文件夹添加名为 Split.razor 的 Razor 组件:

<ul class="list-group">
    @foreach (string name in Names)
    {
        <li class="list-group-item">@name</li>
    }
</ul>

  这个文件只包含 HTML 内容和 Razor 表达式,并呈现一个它希望通过 Names 属性接收的名称列表。要为组件提供其代码,请将一个名为 Split.razor.cs 的类文件添加到 Blazor 文件夹中:

using MyAdvanced.Models;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Linq;

namespace MyAdvanced.Blazor
{
    public partial class Split
    {
        [Inject]
        public DataContext Context { get; set; }
        public IEnumerable<string> Names => Context.People.Select(p => p.Firstname);
    }
}

  部分类必须在与其 Razor组件相同的名称空间中定义,并且具有相同的名称。
  在 Pages 文件夹的 Blazor.cshtml 文件中应用新的组件:

@page "/pages/blazor"
<h4 class="bg-primary text-white text-center p-2">Code-Behind</h4>
<component type="typeof(MyAdvanced.Blazor.Split)" render-mode="Server" />

5.2 定义 Razor 组件类

  Razor 组件可以完全在类文件中定义,尽管这样做的表达性可能不如使用 Razor 表达式。Blazor 文件夹中 添加 CodeOnly.cs类:

using MyAdvanced.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;
using System.Collections.Generic;
using System.Linq;

namespace MyAdvanced.Blazor
{

    public class CodeOnly : ComponentBase
    {
        [Inject]
        public DataContext Context { get; set; }

        public IEnumerable<string> Names => Context.People.Select(p => p.Firstname);

        public bool Ascending { get; set; } = false;

        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            IEnumerable<string> data = Ascending
                ? Names.OrderBy(n => n) : Names.OrderByDescending(n => n);

            builder.OpenElement(1, "button");
            builder.AddAttribute(2, "class", "btn btn-primary mb-2");
            builder.AddAttribute(3, "onclick",
                EventCallback.Factory.Create<MouseEventArgs>(this,
                    () => Ascending = !Ascending));
            builder.AddContent(4, new MarkupString("Toggle"));
            builder.CloseElement();

            builder.OpenElement(5, "ul");
            builder.AddAttribute(6, "class", "list-group");
            foreach (string name in data)
            {
                builder.OpenElement(7, "li");
                builder.AddAttribute(8, "class", "list-group-item");
                builder.AddContent(9, new MarkupString(name));
                builder.CloseElement();
            }
            builder.CloseElement();
        }
    }
}

  组件的基类是 ComponentBase,通常表示为带注释的 HTML 元素的内容是通过覆盖 BuildRenderTree 方法并使用 RenderTrceBuilder 参数创建的,创建内容会很麻烦,然后在 Blazor.cshtml 中像上面一样使用。

Blazor Service 实现身份验证 之前用 Blazor 做了几个小应用,但是一直没有去做身份验证系统,之前也没有ASP.NET的基础,C#也是最近学的,而且重要的是,网上居然几乎没有相关的资料,于是咱就结合网上的一些信息和微软的官方文档(微软的文档是我见过最好的文档了)做了一个身份鉴权的小Demo。在 Provider 下写自定义的基础认证服务,这里使用的session的形式做鉴权认证。Blazor 是微软的新型的web开发方案,用来做全栈开发真是太爽了。然后在项目的目录下创建Auth目录存放鉴权的基础设施。一个简单的登录页面示例; 阅读详情

相关推荐

Blazor —— 教你从零搭建 Blazor for Server-Side 项目

这篇文章不会介绍什么是 Blazor,若想理解基本概念,请自行百度或查看微软官方文档。这篇文章是偏向技术的,也就是说它不是概念,而是教你从零开始搭建一个 Blazor 项目,前提是你必须先掌握 ASP.NET CORE 的基本知识。

不忘初心 9081

Blazor Server开发技术总结

C# Blazor Server

shine_leo的专栏 3043

ASP.NET Core Blazor工具链全解析:从环境配置到开发实战

在Web开发领域,工具链是提升开发效率的核心基础设施。它通过集成化的开发环境、智能化的代码辅助和高效的构建流程,将开发者的创意快速转化为可运行的应用程序。从概念上讲,工具链涵盖了项目创建、代码编写、调试测试到构建部署的全流程支持,其技术价值在于标准化开发流程、降低技术门槛并保障代码质量。在.NET技术栈中,ASP.NET Core Blazor作为现代Web UI框架,其工具链设计充分体现了这一理念。通过.NET SDK与IDE的深度集成,Blazor工具链为开发者提供了热重载、智能感知和统一调试等关键能力

weixin_33816821的博客 496

如何取消Blazor Server烦人的重新连接?

相信很多Blazor的用户在开发内部系统上基本上都选择速度更快,加载更快的模式。但是由于是SignalR实现,所以在访问的时候会建立WebSocket通道,用于js交互和界面渲染,但是由于WebSocket是长连接,这样就会导致用户在界面的时候会一直建立链接,导致服务器宽度占用,所以微软默认会在无操作的情况下自动断开链接,然后会加上该死的重新链接的一个ui,很难看,导致很多用户看到灰色的效果。当然,微软也提供了如何处理这个情况的方案,下面我们会使用微软提供的方案解决这个问题。

xiaohucxy的博客 839

asp .net core blazor 是什么?

我想显从网页的显示历史变化来了解什么是asp .net core blazor 1、第一阶段:静态网页全部下载并显示阶段 在服务器端,程序员写好一个完整的.html网页。浏览一篇网页时,浏览器首先将整个网页下载下来,并显示出来。这个阶段有个很明显的缺点,当网页的部分内容变化比较频繁时,每次在浏览器和服务器之间都要传输一整个.html文件。而这个文件的大部分内容是重复的,只有少部分内容是不同的。...

freewzx2005的专栏 1409

创建 ASP.NET Core 应用与 Blazor Server 入门指南

本文通过构建一个示例应用程序,深入介绍ASP.NET Core中的控制器和视图创建,以及如何使用Blazor Server为Web应用增加客户端交互性。文中详细说明了如何配置和运行ASP.NET Core项目,展示了控制器和Razor页面的使用,以及Blazor Server组件的创建和事件处理。

weixin_42509888的博客 959

ASP.NET Core Blazor 3:使用 Blazor Server (2)

1 准备工作   继续使用上一章项目。   本章展示如何组合Razor组件来创建更复杂的特性。展示如何创建组件之间的父子关系,如何利用属性配置组件,以及如何创建自定义事件,以在发生重要更改时发出信号。还展示了组件如何从父组件接收内容,以及如何使用模板组件一致地生成内容,模板组件可以用一个或多个泛型类型参数定义。在本章结束时,演示了 Blazor应用程序如何对连接和应用程序错误做出反应。 2 结合...

噢~ 1192

linux 内核vxlan收发包流程

1.vxlan口收包处理流程 前面几章详细介绍了vxlan接口的使用,而且已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走,在此复习一下内核收发包流程(驱动层的数据处理这次不再解析,直接从__netif_receive_skb_core开始) #物理网卡处理中断,触发softirq i40e_intr └─napi_schedule_irqoff #i40e softirq把包放到per cpu backlog,触发softirq i40e_napi_p

魏言华的博客 3824

[.NET学习笔记] - 在ASP.NET Core MVC中使用Blazor组件

场景 .NET5发布了,突然对Blazor有了点兴趣,想尝尝鲜。 Blazor有两种模式,server-side与client-side(WASM)。这里打算在已有的MVC项目中使用Blazor组件,所以用的server-side。 use blazor component in ASP.NET Core 3.1 MVC。 解决方案 step1 startup.cs配置。 // ConfigureServices services.AddServerSideBlazor(); services.AddAnt

kyw的专栏 2169

MOSFET导通电阻Rdson全解析:物理组成、公式推导与工程选型要点

在功率电子设计中,MOSFET作为核心开关器件,其导通电阻Rdson直接决定导通损耗与系统效率。从半导体物理角度看,Rdson并非单一固定值,而是由源极电阻、沟道电阻、累积层电阻、JFET区电阻、漂移区电阻及衬底电阻等多个分量串联而成,并随栅极驱动电压、结温以及击穿电压等级发生显著变化。理解Rdson的物理来源与数学表达,有助于工程师在低压大电流与高压小电流等不同场景中合理选型、优化驱动电压并准确估算热损耗。文章从沟道电阻公式出发,深入剖析耐压与导通电阻的物理矛盾、温度系数的影响规律,并给出数据手册参数的正

weixin_29163857的博客 190

Android系统编译之Communication error with Jack server (35), try ‘jack-diagnose‘ or see Jack server log

jack server failed场景个人分析网上分析分析1分析2原因1:权限问题原因2:端口占用原因3:删除 TLSv1, TLSv1.1测试结论解决方案说明相关链接 场景 在进行Android系统开发时,在liunx编译时发生问题,描述如下: ninja: build stopped: subcommand failed. build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed make: *** [ninja_wrapper

weixin_43194854的博客 2401

.NET 10 中的 ASP.NET Core:Blazor、API 和 OpenAPI 的重大更新

微软发布.NET 10版本中ASP.NET Core的全面更新,涵盖Blazor、Minimal API等多个方面。Blazor获得最显著改进,包括安全示例更新、客户端指纹识别等功能。Minimal API新增验证支持和服务器发送事件功能。OpenAPI支持升级至3.1版本,提高文档生成质量。此外还优化了身份验证、异常处理及性能表现,并新增测试支持和JSON解析增强功能。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 5931

openclaw + ollama本地模型 + 飞书平台 windows平台部署教程

本教程将指导您在 Windows 10/11 环境下,通过 Ollama 运行本地模型,并结合 OpenClaw 接入飞书,搭建一个完全本地化的 AI 助手。

专注于技术研发行业技术主要有AI人工智能视觉识别、物联网技术、电商平台、app原生技术、微信小程序、鸿蒙语言开发、办公企业oa、ERP等,致力于做东半球最优秀的程序员 2172

使用VS 2019,.NET Core 3和Web API创建ASP.NET Core Blazor CRUD应用程序

目录 介绍 Blazor Blazor客户端应用程序 Blazor服务器应用程序 背景 先决条件 使用代码 第1步-创建数据库和表 第2步-创建ASP.NET Core Blazor服务器应用程序 运行以测试应用程序 调试组件 步骤3-使用实体框架 安装软件包 添加数据库连接字符串 创建模型类 创建dbConext类 在Startup中添加DbContext 创...

寒冰屋的专栏 5257

小梅哥Xilinx FPGA学习笔记11——亚稳态

亚稳态就是D触发器输入信号在其数据窗口期内发生变化,导致D触发器的输出进入一段时间的不稳定状态,有可能发生振荡,并最终随机稳定在高电平或者低电平。

m0_51430584的博客 631

高通 vs MTK vs 海思:三大平台 ISP 架构横向对比与实战差异分析

随着移动影像能力成为智能终端差异化竞争的核心维度,ISP(Image Signal Processor)架构日益重要。高通、MTK、海思三大 SoC 厂商在 ISP 设计上各具特色,不仅在图像处理链路、模块集成度、算法加速路径等方面存在显著差异,同时也决定了终端厂商在成像质量、调试复杂度与扩展能力上的实际表现。本文将基于真实平台项目经验,横向对比三大主流平台的 ISP 架构关键指标,系统分析其在实际开发过程中的能力边界、工程成本与调优空间,帮助工程师更精准地进行平台选型与优化策略制定。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3926

5分钟掌握 Megatron-Bridge 核心 AutoBridge API:HF 与 Megatron 模型互转只需 3 行代码

[![Megatron-Bridge 在 NeMo 框架中的定位与架构](https://raw.gitcode.com/gh_mirrors/me/Megatron-Bridge/raw/e97a67acbf1b7a8ae0a0e0f26c60fa9548e19bfe/Repo-Mbridge.png?utm_source=gitcode_repo_files)](https://link.gi

gitblog_00042的博客 712

YOLO11改进|注意力机制篇|引入ELA注意力机制

YOLO11添加ELA注意力机制

A1983Z的博客 3647

.NET开发技术推荐,如何使用ASP.NET Core和Blazor进行开发

当使用.NET开发MES(制造执行系统)时,前端和后端的开发方式可以根据项目需求、团队技能和项目规模进行选择。以下是一些常见的开发方式建议::ASP.NET Core 是一个跨平台的、高性能的、开源的 Web 框架,非常适合构建现代、可扩展的 Web 应用程序。它支持多种开发模式,包括 MVC(模型-视图-控制器)和 Web API,可以轻松地与数据库和其他服务进行交互。ASP.NET Core 还具有强大的依赖注入和中间件支持,使得应用程序的可扩展性和可维护性更高。

slty_123的博客 918

STM32开发 -- 4G模块开发详解(1)

这部分一直再看,资料都已经整理好了,但是一直没有汇总。接下来就详细的看一下,GSM这部分是怎么实现的。

不积跬步,无以至千里 5万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

ASP.NET Core 和 Blazor 更新

.NET Core 3.0 preview 8现在已经可用,它包含了对 ASP.NET Core 和 Blazor 的一系列新更新。更新内容如下: 项目模板更新 清理 Visual Studio 中的顶级模板 Visual Studio 中“Create a new project”对话框中的顶级 ASP.NET Core 项目模板不再出现在“Create a new ASP.NET Cor...

寒冰屋的专栏 2237

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

ASP.NET Core Blazor托管模型详解:交互式服务端与WebAssembly如何抉择

**ASP.NET Core Blazor 托管模型**决定了你的 C# 组件代码究竟运行在哪里:是在服务器上以**交互式服务端(Interactive Server)**模式运行,还是在浏览器中基于 **Blazor WebAssembly** 客户端运行,亦或是通过 **Blazor Hybrid** 嵌入原生桌面/移动应用。本文面向新手,用最少的代码带你理解三种托管模型的工作原理、优劣势,并

gitblog_00760的博客 935

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C# 与前端开发结合:利用 Blazor 和 ASP.NET Core 构建前后端分离的动态页面

前后端分离是一种将前端和后端功能解耦的架构模式。前端负责展示数据和与用户的交互,而后端负责处理业务逻辑和数据持久化。两者通过 API 进行通信,通常采用或GraphQL等标准协议。通过使用Blazor和,C# 开发者可以轻松地实现前后端分离的开发模式。Blazor 使得 C# 成为前端开发的强大工具,而 ASP.NET Core 提供了高效的 API 后端支持。前端可以通过 HTTP 请求与后端交互,使用 JavaScript 或 TypeScript 来处理动态页面,形成一个灵活的开发体系。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 3201

ASP.NET Core与Blazor性能对比:基于Benchmarks项目的实战分析

ASP.NET Core与Blazor作为.NET生态中重要的Web开发技术,它们的性能表现直接影响应用的用户体验和资源消耗。本文基于Benchmarks项目提供的权威测试数据,深入对比分析两者在不同场景下的性能差异,为开发者选择合适的技术栈提供实用参考。 ## 一、技术架构与性能特点解析 ASP.NET Core作为成熟的后端框架,采用传统的请求-响应模型,通过中间件管道处理HTTP请求,具

gitblog_00162的博客 708

您需要在Blazor应用程序上了解的所有知识,并使用VS 2019,.NET Core 3和Web API创建ASP.NET Core Blazor CRUD应用程序

Download shanuBlazorCRUD.zip - 435.9 KB 下载shanuBlazorCRUD.zip-435.9 KB 介绍 (Introduction) In this article, we will see how to create a simple CRUD application for ASP.NET Core Blazor using Visual Stud...

cunhan4654的博客 1926

Blazor Server Hello World 实战:用 ASP.NET Core 搭建最小的 Razor 组件应用骨架

本文以 [practical-aspnetcore](https://link.gitcode.com/i/164c24c717ff4983ab1411c534885068) 仓库中 [blazor-ss/HelloWorld](https://link.gitcode.com/i/95637f390de94c5b70d1a8b9d958c3b2) 示例为线索,讲解如何用极少的代码搭建一个可运行的

gitblog_00078的博客 166
上一篇: ASP.NET Core Blazor 1:创建准备项目
下一篇: ASP.NET Core Blazor 3:使用 Blazor Server (2)
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值