@SteveSandersonMS hijacking the original post... see the comment below for a more concise statement about what we need to fix.
A clear and concise description of what the bug is.
I need to process client event on server but after some timeout.
Scenario:
Problem happens when user types something in input and click some navigation link.
In this case following happens:
Since the DotNetObjectRef object and the target component are disposed operation can't be completed, but there is a way for me to ignore it, because i do not need it any more in this scenario.
@page "/counter2"
@inherits SomeNameSpace.Counter2Base
<input @ref="@input" />
<span>@Text</span>
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
namespace SomeNameSpace
{
public partial class Counter2Base : ComponentBase, IDisposable
{
public ElementRef input;
public string Text;
[Inject] IJSRuntime JsRuntime { get; set; }
[Inject] IComponentContext ComponentContext { get; set; }
object objReg;
object ObjReg {
get {
if (objReg == null)
objReg = DotNetObjectRef.Create(this);
return objReg;
}
}
protected override void OnAfterRender()
{
SubscribeEvents();
}
public async void SubscribeEvents()
{
await JsRuntime.InvokeAsync<object>(
"exampleJsFunctions.SubscribeEvents", input, ObjReg);
}
[JSInvokable]
public void LostFocus(string text)
{
Text = text;
StateHasChanged();
}
public void Dispose()
{
var disposableObjReg = objReg as IDisposable;
if(disposableObjReg != null)
disposableObjReg.Dispose();
}
}
}
window.exampleJsFunctions = {
SubscribeEvents: function (element, dotnetHelper) {
element.addEventListener('blur', function (e) {
window.setTimeout(function () {
dotnetHelper.invokeMethodAsync('LostFocus', e.target.value);
}, 1000);
});
},
};
What is the best strategy to workaround this?
I can remove the objReg disposing code (the object created by DotNetObjectRef). But who will be releasing it in this case?
I can create a static collection of that objReg objects, mark them with some "ReadyToDispose" flag instead of disposing, and dispose them after some safe timeout on server.
May be something also? Please suggest.
Thank you!
If I understand correctly, the problem here is the fact that the unhandled exception causes the app to die. That is, you understand why making a call on a DotNetObjectRef that has already been disposed will lead to an exception, but you want to be able to catch and handle that exception (e.g., in your JS code) without it killing the app on the server.
If so, you're absolutely right. This is a bug we need to address. I'll update the issue title to match.
Update: I've confirmed that this kind of exception does not kill the server process. It would have been very strange if it did. It's simply an exception during the invocation of a SignalR hub method (ComponentHub.BeginInvokeDotNetFromJS), so it doesn't kill the process, but does terminate the SignalR connection.
We still need to convert this flow into something that behaves the same as if the JS-invoked method itself threw, so the called on the JS side gets back a rejected promise and can handle it if they want.
@SteveSandersonMS ,
Yes, I would be happy to handle the exception in my JS to ignore it in this case, and allow the user to proceed interating with the application without reloading page.
Thank you!
This is already fixed in Preview 7.
Preview 7 - the issue is still there.
The same scenario as above.
Get the same error:
Error: System.ArgumentException: There is no tracked object with id '1'. Perhaps the DotNetObjectRef instance was already disposed. (Parameter 'dotNetObjectId')
at Microsoft.JSInterop.DotNetObjectRefManager.FindDotNetObject(Int64 dotNetObjectId)
at Microsoft.JSInterop.DotNetDispatcher.BeginInvoke(String callId, String assemblyName, String methodIdentifier, Int64 dotNetObjectId, String argsJson)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.<>c__DisplayClass45_0.<BeginInvokeDotNetFromJS>b__0()
at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<Invoke>b__8_0(Object state)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.BeginInvokeDotNetFromJS(String callId, String assemblyName, String methodIdentifier, Int64 dotNetObjectId, String argsJson)
User's session is destroyed. Browser's page stops operating until reloaded.
@ZergZe Could you provide a github project showcasing the repro?
@javiercn
Project has been created by cli:
$ dotnet new blazorserverside
$ dotnet --version
3.0.100-preview7-012821
Application stops operating. I have no chan褋e to handle and ignore the exceptions.
@ZergZe Thanks for the repro, I think there was a confusion and this didn't make it into preview7. But it is indeed fixed.
@javiercn Thank you very much for the clarification.
I will wait for the future update.
I still reproduce the issue in 3.0.0. @javiercn could you please tell us in which release to expect the fix?
Hi @jivanova .
It looks like you are posting on a closed issue!
We're very likely to lose track of your bug/feedback/question unless you: