EditContext OnFieldChanged reporting wrong return type

Viewed 597

I have the 3 methods below in a razor file

    protected override async Task OnInitializedAsync()
    {
        EditContext = new EditContext(_projectModel);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;
    }
    
    
    private async Task EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
    {
        await SetOkDisabledStatus();
    }
    

This method is an async method and I have to await it anywhere it is been called

    private async Task SetOkDisabledStatus()
    {
        if (EditContext.Validate())
        {
            OkayDisabled = null;
            await JsRuntime.InvokeVoidAsync("Animate");
        }
        else
        {
            OkayDisabled = "disabled";
        }
    }
    
    

I am using the EditContext for validation in a Blazor server application.

I have been getting the error message on this line below in the OnInitializedAsync() method and not sure how to proceed with it.

    EditContext.OnFieldChanged += EditContext_OnFieldChanged;

Error Message:

Task MyProject.EditContext_OnFieldChanged(object, FieldChangedEventArgs)' has the wrong return type.

Expected a method with void EditContext_OnFieldChanged(object?, FieldChangedEventArgs e)

Please note that I am using sonarqube to check all my code.

2 Answers

You can assign an async lambda to the event handler, like this:

EditContext.OnFieldChanged += 
  async (sender,args) => await EditContext_OnFieldChanged(sender,args);

But, you should be aware that the EditContext/Form will not await your task. Anything you do in that async task will be out of sync with the editcontext.

You should probably include a cancellation token in your async code as well, so that multiple changes to a field do not fire multiple validation tasks at the same time.

Async validation is hard - make sure you test every possible scenario.

Generated Blazor eventhandlers (like @onclick="...") are flexible about return type and parameters but EditContext.OnFieldChanged is not, it has a fixed delegate type.

Make the following change:

//private async Task EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
  private async void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
  {
     await SetOkDisabledStatus();
     StateHasChanged();  // make sure OkayDisabled takes effect
  }
  

On another note, you can probably make OkayDisabled a boolean and use disabled="@OkayDisabled" where you need it.
Blazor makes the disabled attribute disappear when you assign it with false.


Alternative: keep the validation synchronous. That might prevent some problems as @Mister Magoo points out. And then let only the Animation run async.

private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
{
   SetOkDisabledStatus();  
}

private void SetOkDisabledStatus()
{
    if (EditContext.Validate())
    {
        OkayDisabled = null; 
        _ = JsRuntime.InvokeVoidAsync("Animate");  // no await, on purpose
    }
    else
    {
        OkayDisabled = "disabled";
    }
}

StateHasChanged() should not be needed in this scenario.

Related