Skip to content

More granular JSExceptions for JSInterop #53620

@KristofferStrube

Description

@KristofferStrube

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

The invocation can fail for multiple reasons when using JSInterop to call JavaScript functions from Blazor. Currently, the erroring case is handled on the JS side, where a boolean indicating whether the invocation was successful together with the error message, and the stack (stack trace) is returned to the C# side as we can see here and the formatting function here. On the C# side a JSException is constructed containing the message and nothing else. But what we are missing is the type of error. An error can basically be one of these types with the APIs available in the browser:

  • EvalError
  • RangeError
  • ReferenceError
  • SyntaxError
  • TypeError
  • URIError

Apart from these, we also have some standard exceptions called the DOMExceptions. There are many different kinds of DOMExceptions as well that are defined in the WebIDL standard specifications. They differ only by having different names and then of cause by being used in different scenarios.

Many JS methods can throw different error types depending on how the invocation failed. As developers, we would like to know why an invocation failed, but we only have the JSException with a raw string message in it. People have employed different methods to parse the string to recover the original reason that the invocation failed. But nowhere in the message is the actual name of the error, as we don't capture that when formatting the error. Instead, people try to find consistent parts of the error message and check if the error contains this subpart to identify the type. An example could be to check if the phrase "is aborted" is in the message to identify it as an AbortError DOMException.

Describe the solution you'd like

I would like it if Blazor would send back the name attribute that is defined on all error types so that developers can check for this property to identify the reason why an invocation failed without doing any guesswork.

Additionally, it would be awesome if there were exception types for all standard JS error names so that developers could catch specific reasons for failure like this:

try
{
    var result = await JSRuntime.InvokeAsync<string>("navigator.clipboard.readText");
}
catch (NotAllowedJSException exception)
{
    Logger.LogWarning(exception, "The user has not given permission to read the clipboard.");
}
catch (NotFoundJSException exception)
{
    Logger.LogWarning(exception, "There wasn't text in the clipboard.");
}
catch (JSException exception)
{
    Logger.LogError(exception, $"An JS error with name '{exception.Name}' happened.");
}
catch (Exception exception)
{
    Logger.LogError(exception, $"Some other unexpected error happened '{exception.GetType().Name}': \"{exception.Message}\"");
}

Additional context

I previously made the following article that also repeats some of my above points but with more details:
https://kristoffer-strube.dk/post/typed-exceptions-for-jsinterop-in-blazor/

In the article I also started on this library which is a workaround to get typed exception types: https://github.com/KristofferStrube/Blazor.WebIDL

Metadata

Metadata

Assignees

Labels

area-blazorIncludes: Blazor, Razor Components

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions