-
Notifications
You must be signed in to change notification settings - Fork 10k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DotNetObjectRef.Create raises an exception when called from lifecycle events in preview6 #11159
Comments
I also have this problem |
This happens in Server Side Blazor. In client-side all is ok. |
I fix this using this code, but it's realy not cool.
|
same problem for me server-side blazor |
same problem to |
Same problem here |
Thanks for contacting us. |
For those looking to make SamProf's solution a little more portable, here is what I figured out: Define this helper class somewhere: public class Issue11159
{
private IJSRuntime Js { get; set; }
public Issue11159(IJSRuntime jsRuntime)
{
Js = jsRuntime;
}
private static object CreateDotNetObjectRefSyncObj = new object();
public DotNetObjectRef<T> CreateDotNetObjectRef<T>(T value) where T : class
{
lock (CreateDotNetObjectRefSyncObj)
{
JSRuntime.SetCurrentJSRuntime(Js);
return DotNetObjectRef.Create(value);
}
}
public void DisposeDotNetObjectRef<T>(DotNetObjectRef<T> value) where T : class
{
if (value != null)
{
lock (CreateDotNetObjectRefSyncObj)
{
JSRuntime.SetCurrentJSRuntime(Js);
value.Dispose();
}
}
}
} In your Razor component, where you want to make a new DotNetObjectRef, you can do this: @inject IJSRuntime JSRuntime
...
@functions {
protected override void OnAfterRender()
{
Issue11159 fixer = new Issue11159(JSRuntime);
OptionInstance instance = new OptionInstance(); // Whatever you want to create an instance of
DotNetObjectRef<OptionInstance> reference = fixer.CreateDotNetObjectRef(instance);
JSRuntime.InvokeAsync<object>("initSelectTest", reference);
}
} |
Same issue here, thanks for the workaround. |
I have this same issue, but not when I create the a DotNetObjectRef but when the Framework does, so I can't solved used the approach because I have not control over it, the error was produced when ever a javascript function try to call any c# function, even with third party libraries like Blazor.Extensions.SIgnalR. This error was produced when I try to call and async function before to start the Host in the Main method and use the ContinueWith syntax like below: public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var httpFactory = host.Services.GetRequiredService<ModernHttpClientFactory>();
FlurlHttp.Configure(c =>
{
c.HttpClientFactory = httpFactory;
});
var configurationManager = host.Services.GetRequiredService<UserConfigurationManager>();
configurationManager.GetIfNeedsAsync().ContinueWith((task) =>
{
if (task.Exception != null)
{
Console.WriteLine(task.Exception.ToString());
}
host.Run();
});
}
public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
BlazorWebAssemblyHost.CreateDefaultBuilder()
.UseBlazorStartup<Startup>();
} Note that the app is running in client-side, and I need to call this function in order to load some resources before to start the app in the host.Run(), since Client Side apps does not has a lifecycle And due the way the app start: And the limitation with async Main on web assembly runtime we can't use await to sync the execution of the task, if we use ConfigureAwait(false).GetAwaiter().GetResult(); or any flavor of it; the task block the execution when performs the HttpRequest by the HttpClient and the app gets int to a dead lock, the browser stock and the window in the web browser do not respond to any command, even close. If we use: public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var httpFactory = host.Services.GetRequiredService<ModernHttpClientFactory>();
FlurlHttp.Configure(c =>
{
c.HttpClientFactory = httpFactory;
});
var configurationManager = host.Services.GetRequiredService<UserConfigurationManager>();
await configurationManager.GetIfNeedsAsync();
await host.StartAsync();
}
public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
BlazorWebAssemblyHost.CreateDefaultBuilder()
.UseBlazorStartup<Startup>();
} The app also entry in a dead lock, because under the hock the compiler transform the async Main method into : [DebuggerStepThrough]
private static void <Main>(string[] args)
{
Program.Main(args).GetAwaiter().GetResult();
} So we fall in the same issue adobe. So we cannot make a http request before the app start in the Program.Main method, the work around was to make the request in the App.SetParametersAsync method by overriding it like: public override async Task SetParametersAsync(ParameterCollection parameters)
{
await configurationManager.GetIfNeedsAsync();
await base.SetParametersAsync(parameters);
} |
I have the same issue, but only when accessing directly a component with its URL. If I start the app and open the website on the landing page and then open the page with the component, it works. If I directly point to the component as first page requested, I see the exception. This with 3.0 preview 7. |
@AlbertoPa The error is still thrown, it just causes the signalr connection to close so that's why your page doesn't get updated. I've got the same problem, I'm trying to use https://github.com/BlazorExtensions/SignalR for a signalr client but gives the same error when I try to create a new HubConnectionBuilder in the OnAfterRenderAsync. //Issue11159 fixer = new Issue11159(Js);
//var reference = fixer.CreateDotNetObjectRef<HubConnection>(connection);
connection = new HubConnectionBuilder(Js).WithUrl("https://api.dapperdino.co.uk/discordbothub").Build();
connection.On<TicketReaction>("TicketReaction", async (TicketReaction message) =>
{
if (message.TicketId.ToString() == TicketId)
{
var newMessage = await ticketDiscordHelper.GetMessageFromChannel($"ticket{message.TicketId}", ulong.Parse(message.DiscordMessage.MessageId));
reactions.Prepend(newMessage as DSharpPlus.Entities.DiscordMessage);
StateHasChanged();
}
}); Ps I tried the Issue11159 fixer combined with the Hub but this seems to break all other jsinterop functions (or I'm doing something wrong). |
Closing as we're tackling this as part of #12082 |
In preview6, there seems to be a regression in creating DotnetObjectRefs, such that when object refs are created during application lifecycle events, an InvalidOperationException is thrown, complaining that "JSRuntime must be set up correctly and must be an instance of JSRuntimeBase to use DotNetObjectRef.".
This happens even if I make sure prerendering has completed and ComponentContext.IsConnected is true.
If I modify app.razor from the default template to this:
An exception is thrown during the DotNetObjectRef.Create call in OnAfterRenderAsync. However, if I disable that theOnAfterRenderAsync lifecycle event, and instead click on the button, the DotNetObjectRef.Create call succeeds as expected.
I need to register callbacks into dotnet-land at application startup (mediaQueryListener and similar), this issue breaks my use case.
The text was updated successfully, but these errors were encountered: