Blazor 服务器 - 'Code Behind' 模式:OnInitializedAsync():找不到合适的方法来覆盖
Blazor Server - 'Code Behind' pattern: OnInitializedAsync(): no suitable method found to override
我有一个 Blazor(服务器)应用程序,它 运行 非常好,并且遵守 Microsoft.CodeAnalysis.FxCopAnalyzers
和 StyleCop.Analyzers
设置的所有规则。
大量删减的剃须刀页面如下:
@inherits OwningComponentBase<MyService>
@inject IModalService ModalService
@inject IJSRuntime JSRuntime
// UI code
@code
{
private readonly CancellationTokenSource TokenSource = new CancellationTokenSource();
ElementReference myElementReferenceName;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await this.myElementReferenceName.FocusAsync(this.JSRuntime);
}
protected override async Task OnInitializedAsync()
{
....
}
public void Dispose()
{
this.TokenSource.Cancel();
}
protected void ShowModalEdit(object someObject)
{
.....
Modal.Show<MyPage>("Edit", parameters);
}
}
注#1:我使用 @inherits OwningComponentBase<MyService>
基于 Daniel Roth's suggestion
注#2:我正在使用 Chris Sainty's Modal component 组件
但是,当我尝试将所有代码从 @code {...}
部分移动到“代码隐藏”部分 class(“MyPage.razor.cs”)时,我 运行 进入以下错误....
'MyPage' does not contain a definition for 'Service' and no accessible
extension method 'Service' accepting .....
'MyPage.OnAfterRenderAsync(bool)': no suitable method found to override
'MyPage.OnInitializedAsync()': no suitable method found to override
The type 'MyPage' cannot be used as type parameter 'T' in the generic
type or method 'IModalService.Show(string, ModalParameters,
ModalOptions)'. There is no implicit reference conversion from
'MyPage' to 'Microsoft.AspNetCore.Components.ComponentBase'.
建议?
您的 MyPage.razor.cs
应继承自 ComponentBase
class,您的 Mypage.razor
应继承自 MyPage.razor.cs
。
在您的“代码隐藏”class 中,您应该为您正在注入的每个服务使用 [Inject]
属性,并使它们至少具有 protected
属性,以便能够在你的剃须刀组件。
下面是我的一个测试应用程序的示例,请注意它使用 .net-core 3.0,在 3.1 中你可以使用部分 classes。
Index.razor
@page "/"
@inherits IndexViewModel
<div class="row">
<div class="col-md">
@if (users == null)
{
<p><em>Hang on while we are getting data...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th class="text-danger">Id</th>
<th class="text-danger">Username</th>
<th class="text-danger">Email</th>
<th class="text-danger">FirstName</th>
<th class="text-danger">LastName</th>
</tr>
</thead>
<tbody>
@foreach (var user in users)
{
<tr>
<td>@user.Id</td>
<td>@user.Username</td>
<td>@user.Email</td>
<td>@user.FirstName</td>
<td>@user.LastName</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
IndexViewModel.cs
public class IndexViewModel : ComponentBase, IDisposable
{
#region Private Members
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private bool disposedValue = false; // To detect redundant calls
[Inject]
private IToastService ToastService { get; set; }
#endregion
#region Protected Members
protected List<User> users;
[Inject] IUsersService UsersService { get; set; }
protected string ErrorMessage { get; set; }
#endregion
#region Constructor
public IndexViewModel()
{
users = new List<User>();
}
#endregion
#region Public Methods
#endregion
#region Private Methods
protected override async Task OnInitializedAsync()
{
await GetUsers().ConfigureAwait(false);
}
private async Task GetUsers()
{
try
{
await foreach (var user in UsersService.GetAllUsers(cts.Token))
{
users.Add(user);
StateHasChanged();
}
}
catch (OperationCanceledException)
{
ShowErrorMessage($"{ nameof(GetUsers) } was canceled at user's request.", "Canceled");
}
catch (Exception ex)
{
// TODO: Log the exception and filter the exception messages which are displayed to users.
ShowErrorMessage(ex.Message);
}
}
private void ShowErrorMessage(string message, string heading ="")
{
//ErrorMessage = message;
//StateHasChanged();
ToastService.ShowError(message, heading);
}
private void ShowSuccessMessage(string message, string heading = "")
{
ToastService.ShowSuccess(message, heading);
}
protected void Cancel()
{
cts.Cancel();
}
#endregion
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
cts.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
当我使用部分 class 方法并尝试构建 Identity 时遇到此错误。我改成 base class aprroach 解决了。
部分class我正在使用
添加一个组件后说 MyComponent,添加一个 class MyComponent.razor.cs
用于注入服务
使用
[注入]
public建筑服务服务{得到;放; }
基本 class 方法
添加一个组件后说 MyComponent,添加一个 class MyComponent.razor.cs
更改 class 名称并使其继承自 componentBase
我的组件库:组件库
并将其放在 MyComponent.razor
的顶部
@inherits MyComponentBase
使用 protected 关键字使您的方法可访问
TLDR
确保 razor.cs
文件中的名称空间正确
更长的解释
在我的例子中,当我把 class 放在错误的命名空间时,我得到了这个错误。 page.razor.cs
文件与 page.razor
文件位于同一目录中,它包含部分 class .
然而,即使文件位于 path/to/dir
,page.razor.cs
的命名空间为 path.to.another.dir
,这导致了抛出此错误。只需将命名空间更改为 path.to.dir
即可为我修复此错误!
以上几点都非常正确。 FWIW,只是为了添加我在这个问题上发现的一件奇怪的事情;我无法让那个错误消失。一切都被宣布为它应该的样子。一旦你排除了所有潜在的编码问题,我发现退出 VS,重新进入,重建清除它。这几乎就像 VS 不会放过那个错误。
花了两天时间清理、重建……结果是剪切和粘贴错误。我从另一个类似 class 复制了 razor 文件,并错误地将其留在了顶部:
@inject Microsoft.Extensions.Localization.IStringLocalizer<Person> localizer
'Person' 是错误的 class,它没有被任何 include 语句定义。由于某些奇怪的原因,唯一的错误是“OnInitialized() 找不到要覆盖的方法。”
我在升级到 6.0 时发现了这个。我不得不从使用 base 类 切换到使用 partial 类!
我有一个 Blazor(服务器)应用程序,它 运行 非常好,并且遵守 Microsoft.CodeAnalysis.FxCopAnalyzers
和 StyleCop.Analyzers
设置的所有规则。
大量删减的剃须刀页面如下:
@inherits OwningComponentBase<MyService>
@inject IModalService ModalService
@inject IJSRuntime JSRuntime
// UI code
@code
{
private readonly CancellationTokenSource TokenSource = new CancellationTokenSource();
ElementReference myElementReferenceName;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await this.myElementReferenceName.FocusAsync(this.JSRuntime);
}
protected override async Task OnInitializedAsync()
{
....
}
public void Dispose()
{
this.TokenSource.Cancel();
}
protected void ShowModalEdit(object someObject)
{
.....
Modal.Show<MyPage>("Edit", parameters);
}
}
注#1:我使用 @inherits OwningComponentBase<MyService>
基于 Daniel Roth's suggestion
注#2:我正在使用 Chris Sainty's Modal component 组件
但是,当我尝试将所有代码从 @code {...}
部分移动到“代码隐藏”部分 class(“MyPage.razor.cs”)时,我 运行 进入以下错误....
'MyPage' does not contain a definition for 'Service' and no accessible extension method 'Service' accepting .....
'MyPage.OnAfterRenderAsync(bool)': no suitable method found to override
'MyPage.OnInitializedAsync()': no suitable method found to override
The type 'MyPage' cannot be used as type parameter 'T' in the generic type or method 'IModalService.Show(string, ModalParameters, ModalOptions)'. There is no implicit reference conversion from 'MyPage' to 'Microsoft.AspNetCore.Components.ComponentBase'.
建议?
您的 MyPage.razor.cs
应继承自 ComponentBase
class,您的 Mypage.razor
应继承自 MyPage.razor.cs
。
在您的“代码隐藏”class 中,您应该为您正在注入的每个服务使用 [Inject]
属性,并使它们至少具有 protected
属性,以便能够在你的剃须刀组件。
下面是我的一个测试应用程序的示例,请注意它使用 .net-core 3.0,在 3.1 中你可以使用部分 classes。
Index.razor
@page "/"
@inherits IndexViewModel
<div class="row">
<div class="col-md">
@if (users == null)
{
<p><em>Hang on while we are getting data...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th class="text-danger">Id</th>
<th class="text-danger">Username</th>
<th class="text-danger">Email</th>
<th class="text-danger">FirstName</th>
<th class="text-danger">LastName</th>
</tr>
</thead>
<tbody>
@foreach (var user in users)
{
<tr>
<td>@user.Id</td>
<td>@user.Username</td>
<td>@user.Email</td>
<td>@user.FirstName</td>
<td>@user.LastName</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
IndexViewModel.cs
public class IndexViewModel : ComponentBase, IDisposable
{
#region Private Members
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private bool disposedValue = false; // To detect redundant calls
[Inject]
private IToastService ToastService { get; set; }
#endregion
#region Protected Members
protected List<User> users;
[Inject] IUsersService UsersService { get; set; }
protected string ErrorMessage { get; set; }
#endregion
#region Constructor
public IndexViewModel()
{
users = new List<User>();
}
#endregion
#region Public Methods
#endregion
#region Private Methods
protected override async Task OnInitializedAsync()
{
await GetUsers().ConfigureAwait(false);
}
private async Task GetUsers()
{
try
{
await foreach (var user in UsersService.GetAllUsers(cts.Token))
{
users.Add(user);
StateHasChanged();
}
}
catch (OperationCanceledException)
{
ShowErrorMessage($"{ nameof(GetUsers) } was canceled at user's request.", "Canceled");
}
catch (Exception ex)
{
// TODO: Log the exception and filter the exception messages which are displayed to users.
ShowErrorMessage(ex.Message);
}
}
private void ShowErrorMessage(string message, string heading ="")
{
//ErrorMessage = message;
//StateHasChanged();
ToastService.ShowError(message, heading);
}
private void ShowSuccessMessage(string message, string heading = "")
{
ToastService.ShowSuccess(message, heading);
}
protected void Cancel()
{
cts.Cancel();
}
#endregion
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
cts.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
当我使用部分 class 方法并尝试构建 Identity 时遇到此错误。我改成 base class aprroach 解决了。
部分class我正在使用 添加一个组件后说 MyComponent,添加一个 class MyComponent.razor.cs 用于注入服务 使用
[注入] public建筑服务服务{得到;放; }
基本 class 方法
添加一个组件后说 MyComponent,添加一个 class MyComponent.razor.cs 更改 class 名称并使其继承自 componentBase 我的组件库:组件库
并将其放在 MyComponent.razor
的顶部@inherits MyComponentBase
使用 protected 关键字使您的方法可访问
TLDR
确保 razor.cs
文件中的名称空间正确
更长的解释
在我的例子中,当我把 class 放在错误的命名空间时,我得到了这个错误。 page.razor.cs
文件与 page.razor
文件位于同一目录中,它包含部分 class
然而,即使文件位于 path/to/dir
,page.razor.cs
的命名空间为 path.to.another.dir
,这导致了抛出此错误。只需将命名空间更改为 path.to.dir
即可为我修复此错误!
以上几点都非常正确。 FWIW,只是为了添加我在这个问题上发现的一件奇怪的事情;我无法让那个错误消失。一切都被宣布为它应该的样子。一旦你排除了所有潜在的编码问题,我发现退出 VS,重新进入,重建清除它。这几乎就像 VS 不会放过那个错误。
花了两天时间清理、重建……结果是剪切和粘贴错误。我从另一个类似 class 复制了 razor 文件,并错误地将其留在了顶部:
@inject Microsoft.Extensions.Localization.IStringLocalizer<Person> localizer
'Person' 是错误的 class,它没有被任何 include 语句定义。由于某些奇怪的原因,唯一的错误是“OnInitialized() 找不到要覆盖的方法。”
我在升级到 6.0 时发现了这个。我不得不从使用 base 类 切换到使用 partial 类!