code-behind - Blazor Server - 'Code Behind' pattern: OnInitializedAsync(): no suitable method found to override
问题描述
I have a Blazor (Server) application which runs perfectly fine, and which adheres to all rules set by Microsoft.CodeAnalysis.FxCopAnalyzers
and StyleCop.Analyzers
.
A heavily cut-down razor page is as follows:
@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);
}
}
Note#1: I used @inherits OwningComponentBase<MyService>
based on Daniel Roth's suggestion
Note#2: I am using the Chris Sainty's Modal component component
However, when I try to move all the code from the @code {...}
section to a"Code Behind" partial class ("MyPage.razor.cs"), then I run into the following errors....
'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'.
Suggestions?
解决方案
Your MyPage.razor.cs
should inherit from ComponentBase
class and your Mypage.razor
should inherit from MyPage.razor.cs
.
In your "code-behind" class you should use [Inject]
attribute for every service you are injecting and make them at least protected
properties to be able to use them in your razor components.
Below is an example from one of my testing apps, please note this uses .net-core 3.0, in 3.1 you can use partial 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
}
推荐阅读
- javascript - Shopify Liquid:将变量输出到 .js 文件
- python - 如何像数据框中的 vlookup 一样替换行值
- vue.js - Vuex:getter总是返回初始值
- python - 重新标记 Seaborn 轴上的蜱虫?
- authentication - 长时间(约 1 小时)后未调用 SetSelected 解锁,未刷新凭据磁贴(Windows 8.1)
- c++ - 为什么我的模运算符不能正常工作?
- c# - 使用 json.net 动态反序列化对多种类型的 json 响应
- python - 如何用python杀死一个批处理文件?
- javascript - 没有为 node_modules 配置加载器 | 网络包 + 通天塔
- python - 增加 Resnet 的输出?