有一个Razor组件(UserProfile.razor)试图使用AuthenticationState CascadingParameter获取登录用户的信息。当在任何Blazor页面中使用此(UserProfile.razor)时(即它返回用户的信息。但是当同一个组件(UserProfile.razor)被用在任何一个Razor页面(即index.cshtml),则_authState始终为null。
有什么办法能修好吗?
Index.cshtml
@page
@using static MyApp.Components.UserProfile;
@model IndexModel
@{
ViewData["Title"] = "Profile";
ViewData["ActivePage"] = ManageNavPages.Index;
}
<div class="row">
<div class="col-6 d-flex flex-column justify-content-between">
<div>
<h2 class="mb-3">Hello, @Model.FriendlyUserName!</h2>
<div class="my-3">
<label class="form-label">Your username is</label>
<input asp-for="Username" class="form-control" placeholder="Please choose your username." disabled />
</div>
<p>
You cannot change that. However, you can update your
other personal information on the right.
</p>
</div>
<div>
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post">
<button type="submit" class="btn btn-lg btn-danger">Logout</button>
</form>
</div>
</div>
<div class="col-6">
<component type="typeof(Components.UserProfile)"
render-mode="ServerPrerendered" />
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Index.cshtml.cs
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace MyApp.Areas.Identity.Pages.Account.Manage
{
public class IndexModel : PageModel
{
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
public IndexModel(
UserManager<User> userManager,
SignInManager<User> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public User _user { get; set; } = null!;
public string FriendlyUserName
{
get
{
if (!String.IsNullOrWhiteSpace(_user.FirstName))
{
if (!String.IsNullOrWhiteSpace(_user.LastName))
{
return $"{_user.FirstName} {_user.LastName}";
}
else
{
return _user.FirstName;
}
}
else
{
return _user.UserName;
}
}
}
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string Username { get; set; }
//public string FirstName { get; set; }
//public string LastName { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[TempData]
public string StatusMessage { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[BindProperty]
public InputModel Input { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class InputModel
{
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[Required]
[DataType(DataType.Text)]
[Display(Name = "FirstName")]
public string FirstName { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "LastName")]
public string LastName { get; set; }
}
private async Task LoadAsync(User user)
{
var userName = await _userManager.GetUserNameAsync(user);
Username = userName;
Input = new InputModel
{
FirstName = user.FirstName,
LastName = user.LastName
};
}
public async Task<IActionResult> OnGetAsync()
{
_user = await _userManager.GetUserAsync(User);
if (_user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
await LoadAsync(_user);
return Page();
}
}
}
UserProfile.razor
@using Microsoft.AspNetCore.Identity;
@using System.ComponentModel.DataAnnotations;
@using Microsoft.EntityFrameworkCore;
@using MyApp.Pages;
<EditForm Model="@Input" OnValidSubmit="OnSubmit">
<h2>User Details</h2>
</EditForm>
@code {
[CascadingParameter]
public Task<AuthenticationState>? _authState { get; set; }
protected override async Task OnParametersSetAsync()
{
if (_authState is not null) //_authState is always null when this component is used in razor page i.e. Index.cshtml
{
var authenticationState = await _authState;
}
}
}
1条答案
按热度按时间m2xkgtsf1#
如Microsoft documentation所述:
级联值和参数提供了一种方便的方法,使数据沿组件层次结构从祖先组件向下流动到任意数量的后代组件。
这意味着来自示例化组件的Blazor页面的数据被转发到组件。
剃刀页面不是Blazor因此,没有数据从Razor页面转发到Blazor页面。这是一种不同的(旧的)技术。Razor页面/视图有their own conventions for authentication。
将Blazor组件放在Razor页面中并不是一个好主意,因为您将失去Blazor功能。主
Index.cshtml
是例外,因为它启动了Blazor应用程序。但是,此时不转发数据。通过大量的努力,你可能会让它工作,但然后你重新设计Blazor。很有黑客的味道。如果没有基础Blazor组件,即如果你想直接访问
AuthenticationState
,你需要在blazor组件中注入AuthenticationStateProvider
,而不是使用这个Cascading参数。请参阅here的详细信息。像这样的东西其实不需要转发:所以使用DI。