Skip to content
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

Exception propagation in Blazor clients #34

Open
vvdb-architecture opened this issue Oct 7, 2022 · 0 comments
Open

Exception propagation in Blazor clients #34

vvdb-architecture opened this issue Oct 7, 2022 · 0 comments
Labels
bug Something isn't working

Comments

@vvdb-architecture
Copy link
Contributor

vvdb-architecture commented Oct 7, 2022

The way exceptions are propagated from back-end to the front end doesn't work with Blazor or any environment that doesn't have awaitable tasks (because they are single-threaded and don't have task completion sources that can be awaited while the task is executing on another thread).
The void ProcessAppException(HttpResponseMessage exception) in AppException contains this:

  var content = exception.Content.ReadAsStringAsync().Result;

In Blazor, this will fail at runtime with:

Cannot wait on monitors on this runtime.
at System.Threading.Monitor.ObjWait(Boolean exitContext, Int32 millisecondsTimeout, Object obj)
at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout, Boolean exitContext)
at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout)
at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.SpinThenBlockingWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.InternalWaitCore(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.InternalWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].get_Result()
at Arc4u.AppException.ProcessAppException(HttpResponseMessage exception)

The first versions of Blazor did not throw an exception, but just blocked.

The easiest solution is to add the following in the openApiToCSharpClient section of the facade.nswag and interface.nswag files:

"generatePrepareRequestAndProcessResponseAsAsyncMethods": true,

This will make the partial methods in the generated client asynchronous.

The method in Arc4u becomes:

public static async Task ProcessAppExceptionAsync(HttpResponseMessage exception, CancellationToken cancellationToken)
        {
            var content = await exception.Content.ReadAsStringAsync(cancellationToken);

            IEnumerable<Message> messages;
            try
            {
                messages = JsonConvert.DeserializeObject<IEnumerable<Message>>(content);
            }
            catch
            {
                // transform the old format to new one. THIS IS NOT THE WAY TO DO IT, BUT IT IS NOT THE SUBJECT OF THIS ISSUE!!!
                content = content.Replace("\"Category\":\"Described\"", "\"Category\":\"Business\"");
                content = content.Replace("\"Category\":\"Undescribed\"", "\"Category\":\"Technical\"");
                messages = JsonConvert.DeserializeObject<IEnumerable<Message>>(content);
            }

            throw new AppException(messages);
        }

Once this is done, the generated code for the partial methods becomes:

            TheFacadeOrInterfaceClient.ProcessExceptionAsync = async (response, cancellationToken) =>
            {
                if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                {
                    await AppException.ProcessAppExceptionAsync(response, cancellationToken);
                }

                // Add any other specific HttpStatusCode specific to your client.
            };

This is somewhat related to #37 , which describes the general exception handling problem,

@rdarko rdarko added the bug Something isn't working label Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants