How to resolve exception: The current thread is not associated with the Dispatcher - asp.net-core

I am getting this exception in a Blazor Server-Side app when a UI component is called from an async method. More specifically, the app is getting data from the database, and when it is done, it calls a Toast component at which time the exception is thrown:
This is the code that throws the exception:
ToastModel model = new ToastModel() { Content = message.MessageToShow, Timeout = message.Timeout};
this.ToastObj.Show(model);
This is the exception:
[2021-01-19T11:35:49.358Z] Error: System.InvalidOperationException: The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
at Microsoft.AspNetCore.Components.Dispatcher.AssertAccess()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
at Syncfusion.Blazor.Notifications.SfToast.Show(ToastModel toastModel)
at CDS.Pages.Accounts.AccountsView.HandleAsync(StatusBarMessage message) in C:\Dev\cds-order-entry.visualstudio.com\CDSBlazor\CDS\CDS\Pages\Accounts\AccountsView.razor.cs:line 43
at CDS.Core.EventAggregator.EventAggregator.PublishAsync(Object message) in C:\Dev\cds-order-entry.visualstudio.com\CDSBlazor\CDS\CDS\Core\EventAggregator\EventAggregator.cs:line 78
at CDS.Pages.Accounts.Search.SearchView.ShowMessage(String message) in C:\Dev\cds-order-entry.visualstudio.com\CDSBlazor\CDS\CDS\Pages\Accounts\Search\SearchView.razor.cs:line 1916
at CDS.Pages.Accounts.Search.SearchView.DoSearch() in C:\Dev\cds-order-entry.visualstudio.com\CDSBlazor\CDS\CDS\Pages\Accounts\Search\SearchView.razor.cs:line 1397
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Syncfusion.Blazor.Internal.SfBaseUtils.InvokeEvent[T](Object eventFn, T eventArgs)
at Syncfusion.Blazor.Buttons.SfButton.OnClickHandler(MouseEventArgs args)
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
Note that this exception only occurred when the app was published to IIS. When running in VS, the exception is not thrown.
(Note: This will be self-answered. It took me much time to debug this, and I want to make it easier for the next guy.)

The fix is actually very easy: Just wrap it in InvokeAysnc like this:
InvokeAsync(() =>
{
this.ToastObj.Show(model);
});
This method is ONLY available on the ComponentBase call, meaning it must be called from the codebehind of the page.
The exception message actually says exactly what the issue is: Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
The moral of the story is that if you are in an async method, wrap any rendering or component state change in InvokeAsync to ensure it is executed on the UI thread, not a background thread.

Related

NServiceBus 6: want some errors to ignore eror queue

As per Customizing Error Handling "Throwing the exception in the catch block will forward the message to the error queue. If that's not desired, remove the throw from the catch block to indicate that the message has been successfully processed." That's not true for me even if I simply swallow any kind of exception in a behavior:
public override async Task Invoke(IInvokeHandlerContext context, Func<Task> next)
{
try
{
await next().ConfigureAwait(false);
}
catch (Exception ex)
{
}
}
I put a breakpoint there and made sure execution hit the catch block. Nevertheless after intimidate and delayed retries messages inevitably ends up in error queue. And I have no more Behaviours in the pipeline besides this one.
Only if I run context.DoNotContinueDispatchingCurrentMessageToHandlers(); inside the catch block it prevents sending error to the error queue, but it also prevents any further immediate and delayed retries.
Any idea on why it works in contravention of Particular NserviceBus documentation is very appreciated
NserviceBus ver. used: 6.4.3
UPDATE:
I want only certain type of exceptions not being sent to an error queue in NServiceBus 6, however to make test case more clear and narrow down the root cause of an issue I use just type Exception. After throwing exception, execution certainly hits the empty catch block. Here is more code to that:
public class EndpointConfig : IConfigureThisEndpoint
{
public void Customize(EndpointConfiguration endpointConfiguration)
{
endpointConfiguration.DefineEndpointName("testEndpoint");
endpointConfiguration.UseSerialization<XmlSerializer>();
endpointConfiguration.DisableFeature<AutoSubscribe>();
configure
.Conventions()
.DefiningCommandsAs(t => t.IsMatched("Command"))
.DefiningEventsAs(t => t.IsMatched("Event"))
.DefiningMessagesAs(t => t.IsMatched("Message"));
var transport = endpointConfiguration.UseTransport<MsmqTransport>();
var routing = transport.Routing();
var rountingConfigurator = container.GetInstance<IRountingConfiguration>();
rountingConfigurator.ApplyRountingConfig(routing);
var instanceMappingFile = routing.InstanceMappingFile();
instanceMappingFile.FilePath("routing.xml");
transport.Transactions(TransportTransactionMode.TransactionScope);
endpointConfiguration.Pipeline.Register(
new CustomFaultMechanismBehavior(),
"Behavior to add custom handling logic for certain type of exceptions");
endpointConfiguration.UseContainer<StructureMapBuilder>(c => c.ExistingContainer(container));
var recoverability = endpointConfiguration.Recoverability();
recoverability.Immediate(immediate =>
{
immediate.NumberOfRetries(2);
});
endpointConfiguration.LimitMessageProcessingConcurrencyTo(16);
recoverability.Delayed(delayed =>
{
delayed.NumberOfRetries(2);
});
endpointConfiguration.SendFailedMessagesTo("errorQueue");
...
}
}
public class CustomFaultMechanismBehavior : Behavior<IInvokeHandlerContext>
{
public override async Task Invoke(IInvokeHandlerContext context, Func<Task> next)
{
try
{
await next().ConfigureAwait(false);
}
catch (Exception ex)
{
}
}
}
UPDATE 2
I think I know what's going on: message is handled by first handler that throws an exception which is caught by the Behavior catch block, but then NServiceBus runtime tries to instantiate second handler class which is also supposed to handle the message (it handles class the message is derived from). That's where another exception is thrown in a constructor of one of dependent class. StructureMap tries to instantiate the handler and all its dependent services declared in the constructor and in the process runs into the exception. And this exception is not caught by CustomFaultMechanismBehavior.
So my I rephrase my question now: Is there any way to suppress errors (ignore error queue) occurring inside constructor or simply during StructureMap classes initialization? Seems like the described way does not cover this kind of situations
Your behavior is activated on Handler invocation. This means you are catching exceptions happening inside the Handle method so any other exception, e.g. in the Constructor of the handler would not be caught.
To change the way you 'capture' the exceptions, you can change the way the behavior is activated, e.g. change it from Behavior<IInvokeHandlerContext> to Behavior<ITransportReceiveContext> which is activated when the transport receives a message. You can investigate on different stages and behaviors to see which one suits your purpose best.

asp.net mvc exception in controller not beign handled at custom ErroHandler

I have a global ErrorHanlder (Derive from HandleErrorAttribute) that works fine and catches all errors that occur. But I have a situation in which, home controller can throw exception. I inspected and saw that error thrown from controller is not handled in my custom ErrorHandler and asp.net gives this:
Exception of type 'Exception' was thrown.
An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Would you help me please ?
Code:
public HomeController()
{
_ServiceAsync = new ServiceAsyncProvider();
}
class ServiceAsyncProvider
{
public ServiceAsyncProvider()
{
throw new Exception();
}
}
While your code snippet is a little unclear on this point, it looks like your _ServiceAsync is being initialized in your controller's constructor. Exceptions thrown during controller construction are not handled by the HandleError filter.
See this related question for more information: Handling Exceptions that happen in a asp.net MVC Controller Constructor
You are throwing an exception in the constructor. These exceptions are not handled by the filter.

NServiceBus Send() vs SendLocal() and exceptions

We are implementing a saga that calls out to other services with NServiceBus. I'm not quite clear about how NServiceBus deals with exceptions inside a saga.
Inside the saga we have a handler, and that handler calls an external service that should only be called once the original message handler completes succesfully. Is it okay to do:
public void Handle(IFooMessage message)
{
var message = Bus.CreateInstance<ExternalService.IBarMessage>();
Bus.Send(message);
// something bad happens here, exception is thrown
}
or will the message be sent to ExternalService multiple times? Someone here has suggested changing it to:
// handler in the saga
public void Handle(IFooMessage message)
{
// Do something
var message = Bus.CreateInstance<ISendBarMessage>();
Bus.SendLocal(message);
// something bad happens, exception is thrown
}
// a service-level handler
public void Handle(ISendBarMessage message)
{
var message = Bus.CreateInstance<ExternalService.IBarMessage>();
Bus.Send(message);
}
I've done an experiment and from what I can tell the first method seems fine, but I can't find any documentation other than http://docs.particular.net/nservicebus/errors/ which says:
When an exception bubbles through to the NServiceBus infrastructure, it rolls back the transaction on a transactional endpoint, causing the message to be returned to the queue, and any messages that user code tried to send or publish to be undone as well.
Any help to clarify this point would be much appreciated.
As long as you're doing messaging from your saga and not doing any web service calls, then you're safe - no need to do SendLocal.

NServiceBus HandleMessage async causes crash

I'm looking at NServiceBus v3.3.0.0, in our MessageHandler it calls an external WCF service.
If the WCF service is called synchronously and that service throws an exception, NServiceBus handles it perfectly and retries the process as per configuration.
But, if the WCF service is called asynchronously and an exception is thrown then the subscriber process crashes.
So, for example, this handles the exception fine if service.Update throws
public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
{
public void Handle(LeagueMessage message)
{
var service = new LeagueService.LeagueContractClient();
var league = service.Update(leagueDto);
}
}
but if the call to service.UpdateAsync throws an exception then the process crashes
public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
{
public async void Handle(LeagueMessage message)
{
var service = new LeagueService.LeagueContractClient();
var league = await service.UpdateAsync(leagueDto);
}
}
The WCF service is just added as a Service Reference to the class library, it generates the Async method wrappers.
Edit after Adam and Udi comments.
It looks like the issue is unrelated to NServiceBus it's more to do with how console applications handle async methods throwing exceptions. Please see thread
Catch unhandled exceptions from async
Stephen Cleary has written this
http://nuget.org/packages/Nito.AsyncEx
which helps you roll your own SynchronisationContext which handles catching the exception. So the WCF call above is wrapped such...
var league = AsyncContext.Run(() => service.UpdateAsync(leagueDto));
when the exception gets thrown it is caught within that context and the console app no longer closes.
When you call it async, the exception happens on a different thread than the one that is processing the message. For that reason, there's no way for NServiceBus to know which message was the one to cause that exception, so it can't roll anything back.
When using NServiceBus, your overall architecture is already asynchronous - there really isn't any need to perform these WCF calls asynchronously.

Is there a way to get error feedback on asynchronous WCF calls?

I have a WCF service which works 100% in the synchronous (blocking) mode and I now need to rework a call so that it uses the async pattern.
The service uses authentication and performs a chunked file transfer from client to server so I have reworked it to use the 'Begin' async prefix to kick off the call.
Now I'm testing for errors by deliberately mangling the user credentials which causes the call to timeout on each part of the file chunk it tries to transfer, which takes ages. The problem is that I don't get any error feedback and can't see how to get any if the async call fails. This leads to some very large files failing to upload at all, but the client being unaware of it as no exceptions are thrown.
I have the Debug->Exceptions->All CLR exceptions ticked to see if there are any exceptions being swallowed but still nothing.
So in summary, how do you get error feedback from async calls in WCF?
Thanks in advance,
Ryan
The server caches the exception for you and if you call the end operation completion method for your async call it will throw any exceptions that occured.
private void go_Click(object sender, EventArgs e)
{
client.BeginDoMyStuff(myValue, new AsyncCallback(OnEndDoMyStuff), null);
}
public void OnEndDoMyStuff(IAsyncResult asyncResult)
{
this.Invoke(new MethodInvoker(delegate() {
// This will throw if we have had an error
client.EndDoMyStuff(asyncResult);
}));
}