精华内容
下载资源
问答
  • 有关如何在Blazor WebAssemblyBlazor Server应用程序中管理状态的示例。 获取 该项目旨在说明如何更好地管理Blazor应用程序中的状态。 它基于官方文档: 。 首先,请分叉存储库(可选),然后对其进行克隆。 ...
  • 蚂蚁设计西装外套 一组基于Ant Design和Blazor的企业级UI组件。 English | :sparkles: 产品特点 :rainbow: 专为Web应用程序设计的企业级UI。 :package: 开箱即用的一组高... Blazor WebAssembly 3.2 / .NET 5版本
  • s支持基于WebAssembly的客户端和基于SignalR的服务器端UI事件交互。 :artist_palette:支持渐进式Web应用程序(PWA)。 with使用C#(一种多范式静态语言)进行构建,以提供高效的开发体验。 :gear:.NETStanda
  • Chatter-WebAssembly 一个带有Room并具有登录和注册帐户的SignalR WebAssembly聊天演示,数据库为Sqlite 基于JwtBearer的Sqlite安全性 ...这段代码基于 ,是针对没有Javascript的纯Blazor变体制作的。
  • Blazor WebAssembly + ASP.NET Core + gRPC 此示例项目演示了如何使用Blazor,ASP.NET Core和gRPC的功能来创建Web应用程序,该应用程序可以与使用gRPC的后端进行通信,并具有最大的代码可重用性。 通过简单地通过....
  • 如何将Blazor WebAssembly部署到Firebase托管 这是有关如何执行以下操作的存储库:“ ”
  • 如何在Blazor WebAssembly中使用EF Core和Cosmos DB
  • Blazor WebAssembly项目的示例,该项目在服务器上使用Entity Framework Core进行数据访问。 您更喜欢Blazor Server吗? 没问题! 为服务器实现了相同的项目。 我创建了该系列博客文章以详细解释该项目(注意:该...
  • 反射IT.Blazor.Paging 使用OData或Web API的Blazor WebAssembly的分页解决方案
  • BlazorMaterialChat:在Blazor WebAssembly ASP.NET Coret中进行的聊天托管
  • Stimulsoft Reports.BlazorBlazor WebAssembly 示例 此存储库包含 Blazor WebAssembly 应用程序中使用 Stimulsoft Reports.Blazor 报告工具的示例的源代码,使用 C# 代码和 Razor 组件。 此产品和示例与 .NET ...
  • Blazor WebAssembly 应用的保护方式与单页应用 (SPA) 相同。 可通过多种方式向 SPA 进行用户身份验证,但最常用、最全面的方式是使用基于 OAuth 2.0 协议的实现,例如 OpenID Connect (OIDC)。 如果需要使用OIDC对...

    1.简介

    Blazor Server基于SignalR,建立连接之后可以通过cookie进行验证,配合Asp.Net Core Identity使用。

    Blazor WebAssembly 应用的保护方式与单页应用 (SPA) 相同。 可通过多种方式向 SPA 进行用户身份验证,但最常用、最全面的方式是使用基于 OAuth 2.0 协议的实现,例如 OpenID Connect (OIDC)。

    如果需要使用OIDC对应用进行身份验证和授权,需要安装在wasm里安装Nuget包Microsoft.AspNetCore.Components.WebAssembly.Authentication

    (安装的前提是你的blazor项目需要用aps.net core 作为host。这个包用于处理基础身份验证协议,建立在oidc-client.js库基础之上。)

    当然除了使用OIDC进行验证和授权之外,还可以使用SameSite cookie等。但是blazor wasm的设计上就决定了使用OAuth和OIDC是进行身份验证过的最佳选择。出于以下几个原因,我们这里使用JWT(Json Web Token)进行身份验证而不是使用cookie:

    • 可以减小攻击面,因为并非所有请求中都会发送令牌
    • 服务器终结点不要求针对跨站点请求伪造 (CSRF) 进行保护,因为会显式发送令牌。所以可将 Blazor WebAssembly 应用与 MVC 或 Razor Pages 应用一起托管
    • 令牌的权限比 cookie 窄。例如,令牌不能用于管理用户帐户或更改用户密码
    • 令牌的生命周期更短(默认为一小时),这限制了攻击时间窗口。还可随时撤销令牌。

    JWT分为三部分{header}.{payload}.{signature}, 解码之后各部分格式和含义如下:

    {
      "typ": "JWT",
      "alg": "RS256",
      "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
    }.{
      "exp": 1610059429,
      "nbf": 1610055829,
      "ver": "1.0",
      "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
      "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
      "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
      "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
      "iat": 1610055829,
      "auth_time": 1610055822,
      "idp": "idp.com",
      "tfp": "B2C_1_signupsignin",
      //还可以 自定义字段
    }.[Signature]
    
    字段说明
    typtoken的类型:jwt
    alg所使用的加密算法
    kid秘钥序,开发人员可以用它标识认证token的某一秘钥
    exp过期时间
    nbf在这个时间点之前,jwt都是不可用的
    ver版本
    issjwt的签发者
    subjwt所面向的用户
    aud接收jwt的一方
    nonce
    iatjwt签发时间
    auth_time
    idp
    tfp
    jtijwt的唯一身份标识,主要用来作为一次性token,回避重放攻击

    2. 使用OIDC进行身份验证的流程

    请先新建一个带有认证功能的Blazor WebAssembly项目便于接下来的理解,该模板的host项目已经添加了IdentityServer服务
    在这里插入图片描述
    验证流程:

    1. 当未登陆的用户点击了登陆按钮或者请求到应用了[Authorize]特性的页面上时,就会将该用户重定向到/authentication/login
    2. 在登陆页上,身份验证库Microsoft.AspNetCore.Components.WebAssembly.Authentication将会把请求重定向到授权服务上(接下来的文章中会介绍如何使用IdentityServer搭建授权服务)。该授权服务负责确定用户是否通过身份验证,并发送token作为响应。
      • 如果用户未通过身份验证,则会提示让用户进行登录。此处可以配合ASP.NET Core Identity使用
      • 如果用户已通过身份验证,则授权服务生成相应的token,并将浏览器重定向到/authentication/login-callback
    3. 当Blazor应用加载/authentication/login-callback时,就处理了身份验证相应。
      • 如果身份验证成功,则可以选择将用户重定向到原始访问的url上。
      • 如果因为任何原因验证失败,则会将用户重定向到authentication/login-failed,并显示错误。

    总结:整个工作流程涉及到三个url,这三个其实都在Shared/Authentication.razor里。:

    1. /authentication/login
    2. /authentication/login-callback
    3. /authentication/login-failed

    该nuget包用下表中显示的路由表示不同的身份验证状态。

    路由目标
    authentication/login触发登录操作。
    authentication/login-callback处理任何登录操作的结果。
    authentication/login-failed当登录操作由于某种原因失败时显示错误消息。
    authentication/logout触发注销操作。
    authentication/logout-callback处理注销操作的结果。
    authentication/logout-failed当注销操作由于某种原因失败时显示错误消息。
    authentication/logged-out指示用户已成功注销。
    authentication/profile触发操作以编辑用户配置文件。
    authentication/register触发操作以注册新用户。

    3. 授权

    对用户验证通过之后,就需要验证授权规则来控制用户可以具体执行哪些操作。常见的授权规则有以下几种:

    • 只要用户通过验证就授权
    • 基于角色的授权
    • 基于用户claim的授权
    • 基于策略的授权

    4. 验证库的使用

    4.1 配置依赖注入

    使用Microsoft.AspNetCore.Components.WebAssembly.Authentication包提供的 AddOidcAuthentication方法在服务容器中注册用户身份验证支持。这里以Google的OIDC服务为例进行配置:

    builder.Services.AddOidcAuthentication(options =>
    {
        //从appsettings.json里读取Local配置项并进行设置
        builder.Configuration.Bind("Local", options.ProviderOptions);
    });
    

    appsettings.json Local配置项:

    {
      "Local": {
        "Authority": "https://accounts.google.com/",
        "ClientId": "2.......7-e.....................q.apps.googleusercontent.com",
        "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
        "RedirectUri": "https://localhost:5001/authentication/login-callback",
        "ResponseType": "id_token"
      }
    }
    

    4.2 添加命令空间和js

    1. _Imports.razor里添加@using Microsoft.AspNetCore.Components.Authorization

    2. wwwroot/index.html里添加<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/ AuthenticationService.js"></script>。这个js用来处理OIDC的细节,应用内部会调用这个服务。

    4.3 添加组件

    4.3.1 配置

    1. CascadingAuthenticationState组件:用来提供经过验证的用户的信息。
    2. AuthorizaRouteView组件:用来确保用户是否可以访问给定的页面,如果未被授权则渲染RedirectToLogin组件。
    3. RedirectToLogin组件:用来将用户重定向到登录页。

    整体代码如下:

    <CascadingAuthenticationState>
        <Router AppAssembly="@typeof(Program).Assembly">
            <Found Context="routeData">
                <AuthorizeRouteView RouteData="@routeData" 
                    DefaultLayout="@typeof(MainLayout)">
                    <NotAuthorized>
                        @if (!context.User.Identity.IsAuthenticated)
                        {
                            <RedirectToLogin />
                        }
                        else
                        {
                            <p>
                                You are not authorized to access 
                                this resource.
                            </p>
                        }
                    </NotAuthorized>
                </AuthorizeRouteView>
            </Found>
            <NotFound>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p>Sorry, there's nothing at this address.</p>
                </LayoutView>
            </NotFound>
        </Router>
    </CascadingAuthenticationState>
    

    4.3.2 RedirectToLogin组件

    Shared/RedirectToLogin.razor组件,用来引导用户进行登录,传入验证成功之后的跳转页。

    @inject NavigationManager Navigation
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication
    @code {
        protected override void OnInitialized()
        {
            Navigation.NavigateTo(
                $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
        }
    }
    

    4.3.3 LoginDisplay组件

    Shared/LoginDisplay.razor组件。对于验证过的用户来说显示用户名等信息,并提供注销功能。对于未验证的用户则提供登录功能。

    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication
    @inject NavigationManager Navigation
    @inject SignOutSessionStateManager SignOutManager
    
    <AuthorizeView>
        <Authorized>
            Hello, @context.User.Identity.Name!
            <button class="nav-link btn btn-link" @onclick="BeginSignOut">
                Log out
            </button>
        </Authorized>
        <NotAuthorized>
            <a href="authentication/login">Log in</a>
        </NotAuthorized>
    </AuthorizeView>
    
    @code {
        private async Task BeginSignOut(MouseEventArgs args)
        {
            await SignOutManager.SetSignOutState();
            Navigation.NavigateTo("authentication/logout");
        }
    }
    

    5.常见组件和服务

    5.1 Authentication组件

    Pages/Authentication.razor下的RemoteAuthenticatorView(属于nuget包),用来处理不同的验证步骤。

    @page "/authentication/{action}"
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication
    
    <RemoteAuthenticatorView Action="@Action" />
    
    @code {
        [Parameter]
        public string Action { get; set; }
    }
    
    

    5.2 AuthorizeView 组件

    该组件可以根据用户是否经过授权来显示不同的UI,常用来设置页面内某个部分是否可见。该组件公开了一个AuthenticationState类型的变量context,可以使用该变量获取已登录的用户信息。

    <AuthorizeView>
        <Authorized>
            <h1>Hello, @context.User.Identity.Name!</h1>
            <p>You can only see this content if you're authorized.</p>
            <button @onclick="SecureMethod">Authorized Only Button</button>
        </Authorized>
        <NotAuthorized>
            <h1>Authentication Failure!</h1>
            <p>You're not signed in.</p>
        </NotAuthorized>
        <Authorizing>
            <h1>Authentication in progress</h1>
            <p>You can only see this content while authentication is in progress.</p>
        </Authorizing>
    </AuthorizeView>
    
    @code {
        private void SecureMethod() { ... }
    }
    

    如果未指定授权规则,则表示用户验证通过就表示已授权。

    AuthorizeView支持基于角色或基于策略的授权。配置如下:

    <AuthorizeView Roles="admin, superuser">
        <p>You can only see this if you're an admin or superuser.</p>
    </AuthorizeView>
    
    <AuthorizeView Policy="content-editor">
        <p>You can only see this if you satisfy the "content-editor" policy.</p>
    </AuthorizeView>
    

    基于策略的授权包含一个特例,即基于claim的授权。例如,可以定义一个要求用户具有某种claim的策略

    5.3 AuthenticationStateProvider 服务

    AuthenticationStateProviderAuthorizeViewCascadingAuthenticationState组件用于获取身份验证状态的基础服务。我们一般不直接使用这个,主要是因为当基础身份验证状态发生改变时不会自动通知UI组件。

    可以通过AuthenticationStateProvider服务来获取用户的Claim数据:

    @page "/"
    @using System.Security.Claims
    @using Microsoft.AspNetCore.Components.Authorization
    @inject AuthenticationStateProvider AuthenticationStateProvider
    
    <h3>ClaimsPrincipal Data</h3>
    
    <button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
    
    <p>@_authMessage</p>
    
    @if (_claims.Count() > 0)
    {
        <ul>
            @foreach (var claim in _claims)
            {
                <li>@claim.Type: @claim.Value</li>
            }
        </ul>
    }
    
    <p>@_surnameMessage</p>
    
    @code {
        private string _authMessage;
        private string _surnameMessage;
        private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
    
        private async Task GetClaimsPrincipalData()
        {
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            var user = authState.User;
    
            if (user.Identity.IsAuthenticated)
            {
                _authMessage = $"{user.Identity.Name} is authenticated.";
                _claims = user.Claims;
                _surnameMessage = 
                    $"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
            }
            else
            {
                _authMessage = "The user is NOT authenticated.";
            }
        }
    }
    

    刚才我们说了一般不要直接使用AuthenticationStateProvider,但是如果真要在页面中获取验证状态该怎么办?

    答案就是定义一个Task<AuthenticationState>类型的级联参数,父级的AuthorizeRouteViewCascadingAuthenticationState组件,会给这个参数赋值。反过来CascadingAuthenticationState会从AuthenticationStateProvider服务接收这个参数 。

    @page "/"
    
    <button @onclick="LogUsername">Log username</button>
    
    <p>@_authMessage</p>
    
    @code {
        [CascadingParameter]
        private Task<AuthenticationState> authenticationStateTask { get; set; }
    
        private string _authMessage;
    
        private async Task LogUsername()
        {
            var authState = await authenticationStateTask;
            var user = authState.User;
    
            if (user.Identity.IsAuthenticated)
            {
                _authMessage = $"{user.Identity.Name} is authenticated.";
            }
            else
            {
                _authMessage = "The user is NOT authenticated.";
            }
        }
    }
    

    然后在配置依赖注入:

    builder.Services.AddOptions();
    builder.Services.AddAuthorizationCore();
    

    5.3.1 自定义AuthenticationStateProvider服务

    重写GetAuthenticationStateAsync方法即可:

    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components.Authorization;
    
    public class CustomAuthStateProvider : AuthenticationStateProvider
    {
        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var identity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, "mrfibuli"),
            }, "Fake authentication type");
    
            var user = new ClaimsPrincipal(identity);
    
            return Task.FromResult(new AuthenticationState(user));
        }
    }
    

    然后配置依赖注入

    builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
    

    6. [Authorize]特性

    表示用户经过授权之后才可以访问页面,与AuthorizeView区别是一个属于页面级,一个属于UI块。

    1. 对所有的页面都需要进行授权:在_Imports.razor文件中使用Authorize特性。
    @using Microsoft.AspNetCore.Authorization
    @attribute [Authorize]
    
    1. 对某个页面进行授权:在页面上添加@attribute [Authorize]

    基于角色和策略的授权:

    @attribute [Authorize(Roles = "admin, superuser")]
    
    @attribute [Authorize(Policy = "content-editor")]
    

    7. 其它说明

    1. 不可以在Blaozr WASM应用中保存刷新令牌。只能在托管的host里保存。
    2. Access Token的作用域:验证库默认会添加openidprofile这两个scope。如果需要添加其它的scope可以调用:
    builder.Services.AddOidcAuthentication(options =>
    {
        ...
        options.ProviderOptions.DefaultScopes.Add("ScopeXXXXX");//输入scope
    });
    

    下一篇将会介绍如何与IdentityServer集成。


    参考:

    1. https://docs.microsoft.com/zh-cn/aspnet/core/blazor/security/webassembly/?view=aspnetcore-5.0#authentication-component
    2. https://docs.microsoft.com/zh-cn/aspnet/core/blazor/security/webassembly/standalone-with-authentication-library?view=aspnetcore-5.0&tabs=visual-studio
    3. https://docs.microsoft.com/zh-cn/aspnet/core/blazor/security/?view=aspnetcore-5.0#authorizeview-component
    展开全文
  • blazor webassembly standalone 模式, 前台是 webassembly, 后台可以是任意语言开发的API服务blazor webassembly hosted 模式, 前台是 webassembly, 后台是 aspnet core blazor server 模式, 前台是 webassembly, ...


    blazor webassembly standalone  模式, 前台是 webassembly, 后台可以是任意语言开发的API服务
    blazor webassembly hosted  模式,  前台是 webassembly, 后台是 aspnet core
    blazor server  模式, 前台是 webassembly, 后台是 aspnet core, 前台通过SignalR和后台通讯


    ================================

    精选

    ================================

    首选 meziantou 博客

    https://www.meziantou.net/archives-categories-blazor.htm

    https://jasonwatmore.com/post/2020/08/13/blazor-webassembly-jwt-authentication-example-tutorial

    https://chrissainty.com/containerising-blazor-applications-with-docker-containerising-a-blazor-webassembly-app/

    https://shauncurtis.github.io/articles/Blazor-Components.html

    https://nightbaker.github.io/

    https://www.cnblogs.com/ittranslator/category/1995890.html

    ================================

    其他

    ================================


    晓晨Master
    https://www.cnblogs.com/stulzq/category/1775987.html


    Building a Progressive Web App with Blazor
    https://devblogs.microsoft.com/visualstudio/building-a-progressive-web-app-with-blazor/
    A simple way to create a PWA with Blazor WebAssembly  
    https://wellsb.com/csharp/aspnet/create-pwa-from-blazor-app/
    c-sharpcorner.com tips for build blazor webassembly
    https://www.c-sharpcorner.com/article/tips-for-building-blazor-webassembly-app-in-net-6-and-visual-studio-code/
    Progressive Web Applications – From Zero to Hero (Blazor, ASP.NET Core, Vue.js, Angular Examples)
    https://www.dotnetcurry.com/aspnet-core/progressive-web-apps-blazor-vuejs-angular
    blazor server 和 blazor assembly 区别
    https://dotnettutorials.net/lesson/blazor-hosting-models/
    ebook
    https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/?wt.mc_id=academic-0000-chnoring
    微软 官方文档
    https://docs.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-5.0
    微软官方教程 aspnet blazor tutorial
    https://dotnet.microsoft.com/learn/aspnet/blazor-tutorial/intro
    https://docs.microsoft.com/en-us/learn/modules/build-blazor-webassembly-visual-studio-code/?WT.mc_id=DT-MVP-5003987

    blazor 教程
    https://blazor-university.com/


    理解官方提供的 blazor 项目模版
    https://www.pragimtech.com/blog/blazor-webAssembly/create-blazor-webassembly-app/

    学完: zzzprojects 出品的 blazor tutorial 稍微有点过时
    https://blazor-tutorial.net/create-blazor-application

    《进击吧!Blazor!》系列入门教程 

    https://www.cnblogs.com/MSReactor/category/1917442.html

    ============================================

    实例

    ============================================

    https://jasonwatmore.com/post/2020/08/13/blazor-webassembly-jwt-authentication-example-tutorial

    https://jasonwatmore.com/post/2020/09/27/blazor-webassembly-authentication-without-identity

    https://jasonwatmore.com/post/2020/11/09/blazor-webassembly-user-registration-and-login-example-tutorial

    使用Blazor开发内部后台系列
    https://zhuanlan.zhihu.com/p/389393062
    https://zhuanlan.zhihu.com/p/387942466
    https://zhuanlan.zhihu.com/p/395232158

    ============================================

    部署

    ============================================
    blazor webassembly standalone 模式如何部署
    https://hackernoon.com/build-and-deploy-a-blazor-app-without-touching-a-windows-machine-oxp22fj 

    https://www.c-sharpcorner.com/article/dockerizing-blazor-wasm-application/

    ============================================

    组件库

    ============================================

    https://blazority.com/datagrid/structure


    Ant Design of Blazor, https://antblazor.com/
    Ant Design Pro Blazor, https://pro.antblazor.com/
    Radzen Blazor Components开源免费组件包
    How To Get Started With The Radzen Blazor Components
    https://www.c-sharpcorner.com/article/how-to-get-started-with-the-radzen-blazor-components/

    展开全文
  • 但如果您创建的是 Blazor WebAssembly 应用程序,那么您的代码将在客户端的浏览器沙箱中运行,您的选择在某种程度上会受到限制。在本教程中,我将向您展示如何在 Blazor WebAssembly 应用程序进行 HTTP 请求。 ...

    图片

    在我的前篇文章《Blazor Server 应用程序中进行 HTTP 请求》中,我介绍了在 Blazor Server 应用程序中进行 HTTP 请求的相关技术,在 Blazor Server App 中您可以访问所有的 .NET 类库和组件。但如果您创建的是 Blazor WebAssembly 应用程序,那么您的代码将在客户端的浏览器沙箱中运行,您的选择在某种程度上会受到限制。在本教程中,我将向您展示如何在 Blazor WebAssembly 应用程序进行 HTTP 请求。

    Blazor WebAssembly 应用程序中的 HttpClient 概述

    Blazor WebAssembly 应用程序使用预置的 HttpClient 服务调用 Web API。这个预置的 HttpClient 是使用浏览器的 Fetch API[2] 实现的,会有一些限制。HttpClient 还可以使用 Blazor JSON 帮助程序或 HttpRequestMessage 对象进行 API 调用。默认情况下,您只能向同源服务器发送 API 调用请求,不过如果第三方 API 支持跨域资源共享(CORS)的话,您也可以调用其他服务器上的 API。

    命名空间 System.Net.Http.Json 为使用 System.Text.Json 执行自动序列化和反序列化的 HttpClient 提供了扩展方法。这些扩展方法将请求发送到一个 Web API URI 并处理相应的响应。常用的方法有:

    • GetFromJsonAsync:发送 HTTP GET 请求,并将 JSON 响应正文解析成一个对象。

    • PostAsJsonAsync:将 POST 请求发送到指定的 URI,并在请求正文中载有序列化为 JSON 的 value

    • PutAsJsonAsync:发送 HTTP PUT 请求,其中包含 JSON 编码的内容。

    要理解如何将这些方法与 HttpClient 一起使用,我们需要创建两个项目。第一个项目是一个 Web API 项目,它向客户端公开一个 Web API。第二个项目是 Blazor WebAssembly 应用程序,它向第一个项目中创建的 Web API 发送 HTTP 请求。

    实现一个 ASP.NET Core Web API

    在本节中,我们将实现一个支持跨域资源共享 (CORS) 的 Web API,以便 Blazor WebAssembly 应用程序可以调用此 API。在 Visual Studio 2019 中创建一个新的 Web API 项目 BlazorClientWebAPI。我们将创建一个简单的 API 来返回产品列表,所以首先要在项目中创建一个 Models 文件夹,并在其中添加如下的 Product 类。

    Product.cs

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    

    接下来,创建一个 Controllers 文件夹并在其中添加下面的 ProductsController。该控制器简单地从 GetProducts 方法返回一些模拟的产品数据。

    ProductsController.cs

    [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetProducts()
        {
            var products = new List<Product>()
            {
                new Product()
                {
                    Id = 1,
                    Name = "Wireless Mouse",
                    Price = 29.99m
                },
                new Product()
                {
                    Id = 2,
                    Name = "HP Headphone",
                    Price = 79.99m
                },
                new Product()
                {
                    Id = 3,
                    Name = "Sony Keyboard",
                    Price = 119.99m
                }
            };
     
            return Ok(products);
        }
    }
    

    现在如果您运行该项目,并尝试在浏览器中使用 URI api/products 访问该 API,您应该能看到以 JSON 格式返回的产品数据。

    图片

    在 ASP.NET Core Web API 中启用 CORS

    默认情况下,浏览器安全性不允许一个网页向除提供该网页的域之外的其他域发送请求。这种约束称之为同源策略。如果我们希望 Blazor WebAssembly 应用程序或其他客户端应用程序使用上述 Web API,那么我们必须启用跨域资源共享 (CORS)。打开 Startup.cs 文件,并在 ConfigureServices 方法中调用 AddCors 方法。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(policy =>
        {
            policy.AddPolicy("CorsPolicy", opt => opt
                .AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod());
        });
     
        services.AddControllers();
    }
    

    同时,在 Startup.cs 文件的 Configure 方法中添加以下代码行。

    app.UseCors("CorsPolicy");
    

    有关使用 ASP.NET Core 应用程序的 CORS 的详细信息,请参阅 《Enable Cross-Origin Requests (CORS) in ASP.NET Core》[3]。

    实现 Blazor WebAssembly 应用程序

    在创建上述 Web API 项目的同一解决方案中添加一个新的 Blazor WebAssembly 应用程序项目 BlazorClientWebAPIsDemo

    我们需要确保的第一件事是,在项目文件中有 System.Net.Http.Json 的引用。如果没有,那么您可以添加该引用。

    <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
       <PropertyGroup>
          <TargetFramework>net5.0</TargetFramework>
       </PropertyGroup>
       <ItemGroup>
          <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.1" />
          <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.1" PrivateAssets="all" />
          <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
       </ItemGroup>
    </Project>
    

    接下来,我们需要在 Program.cs 文件中配置 HttpClient 服务。确保提供了要从 Blazor WebAssembly 应用程序调用的 Web API 的基地址。

    Program.cs

    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");
     
        builder.Services.AddScoped(sp => new HttpClient
        {
            BaseAddress = new Uri("http://localhost:5000/api/")
        }); 
     
        await builder.Build().RunAsync();
    }
    

    为了使用产品 API,我们在 Pages 文件夹中创建一个 Products.razor 组件。该视图非常简单,因为它只是迭代产品列表并使用简单的 HTML 表格来显示它们。

    Products.razor

    @page "/products"
     
    <h1>Products</h1>
     
    @if (products == null)
    {
        <p><em>Loading...</em></p>
    }
    else
    {
        <table class="table">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Name</th>
                    <th>Price</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var forecast in products)
                {
                    <tr>
                        <td>@forecast.Id</td>
                        <td>@forecast.Name</td>
                        <td>@forecast.Price</td>
                    </tr>
                }
            </tbody>
        </table>
    }
    

    创建一个代码隐藏文件 Products.razor.cs,并将配置的 HttpClient 实例作为私有成员注入到该类中。最后,使用 GetFromJsonAsync 方法调用产品 API。

    Products.razor.cs

    public partial class Products
    {
        private List<Product> products;
     
        [Inject]
        private HttpClient Http { get; set; }
     
        protected override async Task OnInitializedAsync()
        {
            products = await Http.GetFromJsonAsync<List<Product>>("products");
        } 
    }
    

    您还需要在 Blazor WebAssembly 项目中创建一个 Product 类的本地副本,以将产品 API 的结果反序列化为产品对象列表。

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    

    运行该项目,您将看到从后端 Web API 加载了产品的页面。

    图片

    展开全文
  • CarChecker-Blazor示例应用程序 这是的示例应用程序,已在Build 2020上发布。您可以在Channel 9: 上查看此应用程序的按需。 要使用此功能,最好拥有Visual Studio 2019和Blazor发行版的最新.NET SDK,您可以在此处...
  • 引用自:...可以使用基于 Chromium 的浏览器 (Edge/Chrome) 中的浏览器开发工具调试 Blazor WebAssembly 应用。还可以使用以下集成开发环境 (IDE) 调试应用(注意:是要Edge/Chrome): Visual Studio .

    引用自:https://docs.microsoft.com/zh-cn/aspnet/core/blazor/debug?cid=kerryherger&tabs=visual-studio&view=aspnetcore-3.1

    可以使用基于 Chromium 的浏览器 (Edge/Chrome) 中的浏览器开发工具调试 Blazor WebAssembly 应用。 还可以使用以下集成开发环境 (IDE) 调试应用(注意:是要Edge/Chrome):

    • Visual Studio
    • Visual Studio for Mac
    • Visual Studio Code

    可用方案包括:

    • 设置和删除断点。
    • 在 IDE 中运行具有调试支持的应用。
    • 单步执行代码。
    • 在 IDE 中使用键盘快捷方式恢复代码执行。
    • 在“局部变量”窗口中,观察局部变量的值。
    • 请参阅调用堆栈,包括 JavaScript 和 .NET 之间的调用链。

    目前,无法执行以下操作:

    • 出现未经处理的异常时中断。
    • 于应用启动期间在调试代理运行之前命中断点。 这包括 Program.Main (Program.cs) 中的断点和组件的 OnInitialized{Async} 方法 中的断点,其中这些组件由请求自应用的第一页加载。

    先决条件

    调试需要使用以下浏览器之一:

    • Google Chrome(版本 70 或更高版本)(默认)
    • Microsoft Edge(版本 80 或更高版本)

    Visual Studio for Mac 需要版本 8.8(内部版本 1532)或更高版本:

    1. 选择 Microsoft:Visual Studio for Mac 页面上的“下载 Visual Studio for Mac”按钮,安装最新版本的 Visual Studio for Mac。
    2. 从 Visual Studio 中选择预览通道。 有关详细信息,请参阅安装 Visual Studio for Mac 的预览版本

     备注

    当前不支持 macOS 上的 Apple Safari。

    启用调试

    若要为现有 Blazor WebAssembly 应用启用调试,请更新启动项目中的 launchSettings.json 文件,使每个启动配置文件包含以下 inspectUri 属性:

    JSON

    "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"
    

    更新后,launchSettings.json 文件应类似于以下示例:

    JSON

    {
      "iisSettings": {
        "windowsAuthentication": false,
        "anonymousAuthentication": true,
        "iisExpress": {
          "applicationUrl": "http://localhost:50454",
          "sslPort": 44399
        }
      },
      "profiles": {
        "IIS Express": {
          "commandName": "IISExpress",
          "launchBrowser": true,
          "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        },
        "BlazorApp1.Server": {
          "commandName": "Project",
          "launchBrowser": true,
          "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
          "applicationUrl": "https://localhost:5001;http://localhost:5000",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        }
      }
    }
    

    inspectUri 属性具有以下作用:

    • 使 IDE 能够检测到该应用为 Blazor WebAssembly 应用。
    • 指示脚本调试基础结构通过 Blazor 的调试代理连接到浏览器。

    已启动的浏览器 (browserInspectUri) 上 WebSocket 协议 (wsProtocol)、主机 (url.hostname)、端口 (url.port) 和检查器 URI 的占位符值由框架提供。

    要在 Visual Studio 中调试 Blazor WebAssembly 应用,请按以下步骤执行:

    1. 创建新的 ASP.NET Core 托管 Blazor WebAssembly 应用。

    2. 按 F5 在调试器中运行应用。

       备注

      不支持“启动时不调试”(Ctrl+F5)。 当应用以调试配置运行时,调试开销始终会导致性能的小幅下降。

    3. 在客户端应用中,在 Pages/Counter.razor 中的 currentCount++; 行上设置断点。

    4. 在浏览器中,导航到 Counter 页,然后选择“单击此处”按钮以命中断点。

    5. 在 Visual Studio 中,检查“局部变量”窗口中 currentCount 字段的值。

    6. 按 F5 继续执行。

    调试 Blazor WebAssembly 应用时,还可以调试服务器代码:

    1. 在 OnInitializedAsync 的“Pages/FetchData.razor”页中设置断点。
    2. 在 Get 操作方法的 WeatherForecastController 中设置一个断点。
    3. 浏览到 Fetch Data 页,在 FetchData 组件中的首个断点向服务器发出 HTTP 请求前命中该断点。
    4. 按 F5 以继续执行,然后在服务器上命中 WeatherForecastController 中的断点。
    5. 再次按 F5 以继续执行,并查看浏览器中呈现的天气预报表。

     备注

    在运行调试代理之前,在应用启动期间不会命中断点。 这包括 Program.Main (Program.cs) 中的断点和组件的 OnInitialized{Async} 方法 中的断点,其中这些组件由请求自应用的第一页加载。

    如果应用托管在不同于 / 的应用程序基路径上,请更新 Properties/launchSettings.json 中的以下属性,以反映应用程序的基路径:

    • applicationUrl:

      JSON

      "iisSettings": {
        ...
        "iisExpress": {
          "applicationUrl": "http://localhost:{INSECURE PORT}/{APP BASE PATH}/",
          "sslPort": {SECURE PORT}
        }
      },
      
    • 每个配置文件的 inspectUri

      JSON

      "profiles": {
        ...
        "{PROFILE 1, 2, ... N}": {
          ...
          "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/{APP BASE PATH}/_framework/debug/ws-proxy?browser={browserInspectUri}",
          ...
        }
      }
      

    前面设置中的占位符:

    • {INSECURE PORT}:不安全的端口。 默认情况下提供随机值,但允许使用自定义端口。
    • {APP BASE PATH}:应用程序的基路径。
    • {SECURE PORT}:安全的端口。 默认情况下提供随机值,但允许使用自定义端口。
    • {PROFILE 1, 2, ... N}:启动设置配置文件。 通常,应用会默认指定多个配置文件(例如,IIS Express 的配置文件和 Kestrel 服务器使用的项目配置文件)。

    在下面的示例中,应用托管在 /OAT 上,并在 wwwroot/index.html 中将应用程序基路径配置为 <base href="/OAT/">

    JSON

    "applicationUrl": "http://localhost:{INSECURE PORT}/OAT/",
    

    JSON

    "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/OAT/_framework/debug/ws-proxy?browser={browserInspectUri}",
    

    有关将自定义应用基路径用于 Blazor WebAssembly 应用的信息,请参阅 托管和部署 ASP.NET Core Blazor

    在浏览器中调试

    本部分中的指南适用于在 Windows 上运行的 Google Chrome 和 Microsoft Edge。

    1. 在开发环境中运行该应用的调试版本。

    2. 启动浏览器并导航到应用程序的 URL(例如 https://localhost:5001)。

    3. 在浏览器中,尝试通过按 Shift+Alt+d 启动远程调试。

      浏览器必须在已启用远程调试的情况下运行,而这并不是默认设置。 如果远程调试处于禁用状态,将呈现“无法找到可调试的浏览器选项卡”错误页,并且其中包含关于在调试端口打开的情况下启动浏览器的说明。 按照适用于你的浏览器的说明操作,接下来将打开一个新的浏览器窗口。 关闭上一个浏览器窗口。

    1. 在启用远程调试的情况下运行浏览器后,按上一步中的调试键盘快捷方式会打开新的调试程序选项卡。

    2. 片刻后,“源”选项卡显示 file:// 节点中应用的 .NET 程序集的列表。

    3. 在组件代码(.razor 文件)和 C# 代码文件 (.cs) 中,当代码执行时将命中你设置的断点。 命中断点后,正常单步执行代码 (F10) 或恢复代码执行 (F8)。

    Blazor 提供调试代理,该代理实现 Chrome DevTools Protocol,并使用特定于 .NET 的信息扩展该协议。 按下调试键盘快捷方式后,Blazor 会将 Chrome 开发者工具指向代理。 代理连接到要调试的浏览器窗口(因此需要启用远程调试)。

    浏览器源映射

    浏览器源映射允许浏览器将编译后的文件映射回其原始源文件,并且通常用于客户端调试。 但是,Blazor 当前不直接将 C# 映射到 JavaScript/WASM。 相反,Blazor 在浏览器中进行 IL 解释,因此源映射不相关。

    疑难解答

    如果遇到错误,以下提示可能有所帮助:

    • 在“调试程序”选项卡中,在浏览器中打开开发人员工具。 在控制台中,执行 localStorage.clear() 以删除所有断点。
    • 确认你已安装并信任 ASP.NET Core HTTPS 开发证书。 有关详细信息,请参阅 在 ASP.NET Core 强制实施 HTTPS
    • Visual Studio 要求在“工具” > “选项” > “调试” > “常规”中选择“对 ASP.NET 启用 JavaScript 调试(Chrome、Edge 和 IE)”选项。 这是 Visual Studio 的默认设置。 如果调试不起作用,请确认已选中该选项。

    OnInitialized{Async} 中的未命中断点

    Blazor 框架的调试代理需要一小段时间才能启动,因此 OnInitialized{Async} 生命周期方法中的断点可能不会命中。 建议在方法主体开头添加延迟,以便在命中断点之前,为调试代理指定一段时间来启动。 你可以根据 if 编译器指令包括延迟,以确保应用的发布版本不存在延迟。

    OnInitialized:

    C#

    protected override void OnInitialized()
    {
    #if DEBUG
        Thread.Sleep(10000)
    #endif
    
        ...
    }
    

    OnInitializedAsync:

    C#

    protected override async Task OnInitializedAsync()
    {
    #if DEBUG
        await Task.Delay(10000)
    #endif
    
        ...
    }
    

    Visual Studio (Windows) 超时

    如果 Visual Studio 引发了调试适配器启动因已达到超时而失败的异常,可使用注册表设置调整超时:

    控制台

    VsRegEdit.exe set "<VSInstallFolder>" HKCU JSDebugger\Options\Debugging "BlazorTimeoutInMilliseconds" dword {TIMEOUT}
    

    前述命令中的 {TIMEOUT} 占位符以毫秒为单位。 例如, 1 分钟指定为 60000

    展开全文
  • 目标 用 C# 代替 javascript 做前端开发。... 前端开发的趋势是组件化,可以创建 .net standard 类库(对应vs2019模板类型:Razor类库),把Blazor组件包装起来,然后在Blazor Server或者Blazor Webasse...
  • Blazor Webassembly + WebApi多语言实现Blazor WebAssembly多语言准备工作开始WebApi多语言准备工作开始 Blazor WebAssembly多语言 准备工作 新建Blazor WebAssembly项目 开始 在csproj中添加...
  • Blazor Server和Blazor WebAssembly应用程序中Syncfusion Blazor UI组件的本地化示例 如何运行应用程序 在命令提示符下使用以下命令行克隆重新发布。 git clone ...
  • 因为Blazor Server不存在跨域问题,所以这里我们针对的是Blazor Webassembly。浏览器跨域问题是啥不用做过多解释,当blazor请求其它服务提供的接口时,使用的HttpClient类本质调用的还是浏览器的fetch函数,所以依然...
  • 新建Blazor Webassembly项目 前几天的build大会,Blazor Webassembly已经正式release了。我们更新最新版的Core SDK就会安装正式版的模板。 新建项目选Blazor Webassembly App项目模板 新建GreenPanel组件 在pages...
  • 如果你已经了解关于 gRPC 和 gRPC-Web 的一切,你可以跳到 添加 gRPC 服务到一个Blazor WebAssembly 应用程序 一节。如果你只是想要一些简单的 Blazor WebAssembly + gRPC-Web 应用程序,请看这个仓库 ...
  • 使用ASP.NET Blazor WebAssembly构建的论坛软件。 文档: 。 技术 Blazor WebAssembly 5.0.1 实体框架核心5.0.1 SQL服务器 特征 主题 多语言 细化权限 Markdown编辑器 您可以使用自己的ASP.NET身份 在本地运行 ...
  • 如果要支持Blazor WebAssembly的本地化,应该如何实现呢?下面,我们就按照本地化问题操作中所涉及的所有主要问题以提问的方式进行说明。 1.本地化的核心原理是什么? 答:就是显式地在Program.Main方法中设置 ...
  • 通过 Serverless 加速 Blazor WebAssembly

    千次阅读 2020-03-18 18:14:51
    本文为 Serverless 社区成员撰稿。...我正在开发 Ant Design 的 Blazor 版本,预览页面部署在 Github Pages 上,但是加载速度很不理想,往往需要 1 分钟多钟才完成。 项目地址:https://github.com/ElderJam...
  • 第一步 发布blazor wasm 在工程上右键选择 发布,发布到文件夹,默认到 bin/debug/release/publish 下,然后点 【发布】按钮,发布成功后,在 publish 文件夹内能看到 wwwroot和 web.config。 第二步 将发布的...
  • Program.cs 的代码: using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions....
  • https://nightbaker.github.io/spa/csharp/webassembly/blazor/2021/08/09/blazor-optimization/
  • 相关内容: ASP.NET Core Blazor Webassembly 之 数据绑定 ASP.NET Core Blazor Webassembly 之 组件 ASP.NET Core Blazor 初探之 Blazor WebAssembly ASP.NET Core Blazor 初探之 Blazor Server 关注我的公众号...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,049
精华内容 419
关键字:

blazorwebassembly