Tracking down unhandled exceptions in Blazor Webassembly - c#

Any idea on how to get the line number of an unhanded exception in blazor webassembly?
There was a discussion long ago on some work that still needs to be done by the team to have it working. I think that died down if I'm not mistaken.
Consider the message below. It leaves one completely in the dark with no guidance on where to start looking.
Thanks in advance.

Not to be rude, but it is in the Blazor documentation to always handle exceptions yourself when interacting with components: https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/handle-errors?view=aspnetcore-5.0&pivots=webassembly#global-exception-handling
Simply wrap your all your method bodies (even the lifecycle methods) with a try/catch block. Bonus points to inject the ILogger<MyComponent> for friendly logging.
Example:
#inject ILogger<MyComponent> Logger
<h1>#UserName</h1>
#code {
private string UserName { get; set; } = string.Empty;
protected override async Task OnInitializedAsync()
{
try
{
NavigationManager.LocationChanged += OnLocationChanged;
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
UserName = $"Hi, {authState.User.Claims.FirstOrDefault(x => x.Type == "display_name")?.Value}!";
}
catch (Exception ex)
{
Logger.LogError($"Failed to initialize MyComponent. Error: {ex}");
}
}
}

Related

How to handle exceptions from API calls in Unity and pass them down to the UI?

I'm trying to figure out what to do with some errors in Unity when I call an API and how to propogate it up to the user interface - where and how to handle things. I've built aspnet APIs but there I'd normally use some error handling middleware to keep my controllers clean.
Let say we have some code like this (I'm using controller / repository language cos that's what I know).
A UI button fires an event like OnLoginButtonPressed.
An AuthController class reacts to the event by calling it's login method and then doing some logic when the response comes through, as follows:
public async void Login(LoginModel input)
{
var result = await AuthRepo.instance.Login(input);
app.token = result;
EventService.OnSuccessfulLogin();
}
The Auth.Repo calls the API and tries to return a Token class (just a wrapper around a JWT string)
public async Task<Token> Login(LoginModel input)
{
string json = JsonConvert.SerializeObject(input);
var request = UnityWebRequest.Post(app.baseURL + "authentication/login", json);
request.SetRequestHeader("Content-Type", "application/json");
request.SendWebRequest();
while (!request.isDone)
{
await Task.Yield();
}
if (request.result == UnityWebRequest.Result.Success)
{
Token token = JsonConvert.DeserializeObject<Token>(request.downloadHandler.text);
return token;
}
else
{
throw
}
}
So that's without exception handling. So I want to try to let the user know if there is a connection error, or they have put invalid details etc... I'm guessing I'm supposed add some logic into the AuthRepo such as:
if (request.result == UnityWebRequest.Result.Success)
{
Token token = JsonConvert.DeserializeObject<Token>(request.downloadHandler.text);
return token;
}
else if (request.result== UnityWebRequest.Result.ConnectionError)
{
throw new ConnectionException(request.error);
}
else if (request.result == UnityWebRequest.Result.DataProcessingError)
{
throw new BadRequestException(request.error);
}
else
{
throw new System.Exception(request.error);
}
This seems like a lot of code, and would end up in every method in every repo (unless I pull it out into some helper method?).... anyway, and then in the controller I would do something like:
try {
var result = await AuthRepo.instance.Login(input);
app.token = result;
EventService.OnSuccessfulLogin();
}
catch (ConnectionException ex)
{
EventService.OnConnectionError(ex.Message);
//some UI object would listen for this event and show the connection error message.
}
catch (BadRequestException ex)
{
EventService.LoginFailedError(ex.Message);
}
finally
{
EventService.UnknownError(ex.Message);
}
Is this completely down the wrong path? Seems like the code is just gonna get swamped with exception handling, or is this the correct way?
I've worked through a few YouTube videos that seem to suggest this is right, but they don't really show my use case (talking to APIs) so I'm just trying to be sure.
because UnityWebRequest.Result is an enum, you can start by using a switch statement here. Not only is this cleaner, it performs better too.
Another thing you can do is create an abstract class (e.g. APIException) and make that responsible for creating the correct exception instances, by giving it some static method like APIException FromUWRResult(UnityWebRequest.Result result).
Handling the exceptions can be done in APIException too. Give it an abstract method Handle() and implement accordingly in each of the deriving classes.
Now your code would look like this:
var ex = APIException.FromUWRResult(request.result);
if(ex != null) {
throw ex;
}
...
catch(APIException ex) {
ex.Handle();
}

Exceptions of my Azure Function are logged 3 times in Application Insights

I have created a Blob Trigger Azure Function, and I wanted to be able to create mail alerts when I have an exception, and among the information sent in the mail alert, there should be the name of the file the exception occurred on.
I noticed that exceptions are automatically logged in Azure, but I found no way of customizing the message or the information sent along the exception. So I decided to inject a telemetry service in my Function App, and add the file name as a custom property, as you can see in the code below :
public class Function1
{
private readonly IGremlinService _gremlinService;
private readonly TelemetryClient _telemetryClient;
public Function1(IGremlinService gremlinService, TelemetryConfiguration telemetryConfiguration)
{
this._gremlinService = gremlinService;
this._telemetryClient = new TelemetryClient(telemetryConfiguration);
}
[FunctionName(nameof(Function1))]
public async Task Run([BlobTrigger("files/{directory}/{name}.00.pdf", Connection = "AzureWebJobsStorage")] Stream myBlob, string name, ILogger logger)
{
try
{
//some code not related to the issue
}
catch (Exception e)
{
var properties = new Dictionary<string, string>
{{"Filename", name}};
_telemetryClient.TrackException(e, properties);
if (e is ResponseException)
{
ResponseException re = (ResponseException) e;
var statusCode = (long) re.StatusAttributes["x-ms-status-code"];
_telemetryClient.TrackTrace("Error on file " + name + ". Status code: " + statusCode + " " + re.StackTrace, SeverityLevel.Error, properties);
}
else
{
_telemetryClient.TrackTrace("Error on file " + name, SeverityLevel.Error, properties);
}
throw;
}
}
}
}
But I still cannot customize the message to provide the user with additional information. I know I can send alerts on trace messages instead, and send customized messages this way, and this is currently what I'm doing, but I would find it cleaner to send alert on exceptions.
My second issue is that my exceptions are still logged automatically on top of being logged by the telemetry service, and for some reason I can't understand, they are logged twice, as you can see in the screenshot below from Application Insights :
Is there a way I can turn off the automatic logging of exceptions ? Or is there a way to customize these exceptions messages that I'm not aware of, instead of using the telemetry service ?
I believe, the 3 exceptions are being logged due to following reasons:
The implementation service of IGremlinService throwing exception which is being logged.
You are logging via _telemetryClient.TrackException(e, properties);
Azure infrastructure is handling when throw is invoked.
Now coming to your question
I found no way of customizing the message or the information sent along the exception
I would suggest you to use ILogger for LogException and use BeginScope (read here) to define the scope properties which will be logged as Custom Properties in application insights for all the logs which are invoked during the lifetime of created scope.
Using the ILogger object, your code will be simplified as follows and all traces and exceptions inside scope will have FileName as custom property in application insights.
[FunctionName(nameof(Function1))]
public async Task Run([BlobTrigger("files/{directory}/{name}.00.pdf", Connection = "AzureWebJobsStorage")] Stream myBlob, string name, ILogger logger)
{
using (logger.BeginScope(new Dictionary<string, object>()
{
["FileName"] = name,
}))
{
try
{
//some code not related to the issue
}
catch (Exception e)
{
logger.LogError(e, "Error occurred with {StatusCode}", (long) re.StatusAttributes["x-ms-status-code"]);
throw;
}
}
}
Following summarizes the definition of statement logger.LogException(e, "Error occurred with {StatusCode}", (long) re.StatusAttributes["x-ms-status-code"]);
e represents the actual exception which occurred.
the code part {StatusCode} will be logged the StatusCode as Custom Property in application insights for the logged exception so you don't need to create any dictionary.
FileName will be logged as Custom property as defined by Scope.
You can view a sample implementation at here.

C# Cannot catch exceptions from another project within same solution

Got a strange problem: in a complex camera control program I'm working on, I use an SDK with a C# wrapper that was programmed by someone else. I include the wrapper as a separate project within the same solution. My own code is a WPF project that uses numerous calls into the SDK.
Everything synchronous works fine. However, depending on camera responses, the SDK occasionally sends asynchronous responses, usually in the form of throwing a custom exception with info about an error the camera reports. I implemented this using
try { ... } catch (ThisExceptionType) { ... }
However, NO exception ever gets caught. When an exception situation occurs, VisualStudio breaks, shows me the code where the SDK throws it and reports "ThisExceptionType was unhandled by user code", also showing the details of the exception condition (meaning it was apparently thrown properly). I verified that the exception corresponds with the error condition I created, so I'm sure I'm not looking at the wrong part of my code.
For testing purposes, I also replaced the line in the SDK where it throws ThisExceptionType with a standard exception, such as throw new ArgumentException("Test"); Same result: when changing my catch to catch (ArgumentException), I still cannot catch the condition and get a similar unhandled-by-user-code error.
Here's how the SDK throws the exception:
void CallEntryPoint( ...)
{
eNkMAIDResult result = _md3.EntryPoint(...);
switch (result)
{
// Note: Ignore these return values
case eNkMAIDResult.kNkMAIDResult_NoError:
case eNkMAIDResult.kNkMAIDResult_Pending:
break;
default:
throw new NikonException(...);
}
}
What am I missing here? Sorry if this is a simple issue - I'm pretty experienced in general programming but have not worked much with VisualStudio, and not a whole lot in C#, either.
UPDATE: According to the wrapper's author (this is actually Thomas Dideriksen's Nikon SDK wrapper), "when you're writing WPF or WinForms application, the C# wrapper relies on the inherent windows message queue to fire events on the UI thread."
He also states that the wrapper processes all camera tasks sequentially, so I guess my statement was incorrect about the wrapper throwing asynchronous exceptions - all code examples for the wrapper use the same try { ... } catch (ThisExceptionType) { ... } approach. For good measure, I tried some of your suggestions, for instance by hooking a handler to AppDomain.CurrentDomain.UnhandledException, but that approach failed to catch the exception, as well.
Any other ideas why this may be happening?
This article on MSDN may help. https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx
There are differences in handling exceptions using Tasks in C#. Hopefully that will give a run down on different techniques you can use to handle the exceptions appropriately.
From the MSDN article:
Unhandled exceptions that are thrown by user code that is running
inside a task are propagated back to the calling thread, except in
certain scenarios that are described later in this topic. Exceptions
are propagated when you use one of the static or instance Task.Wait or
Task.Wait methods, and you handle them by enclosing the call
in a try/catch statement. If a task is the parent of attached child
tasks, or if you are waiting on multiple tasks, multiple exceptions
could be thrown.
And there are a couple solutions provided:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
Or you can do this:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
while(! task1.IsCompleted) {}
if (task1.Status == TaskStatus.Faulted) {
foreach (var e in task1.Exception.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw e;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
I hope that helps!

Generic property disadvantages?

i use generic properties on my project,but i dont know,is there any disadvantage use them,please tell me a scenario,they have a disadvantage?my part of code below.
public class GenericResult<T>
{
public T Data { get; set; }
public bool IsSuccess { get; set; }
public string Message { get; set; }
}
public GenericResult<int> AddCategory(TCategory tCategory)
{
GenericResult<int> result = new GenericResult<int>();
//business logic validation,dont make sense,only example :)
if (tCategory.Name.Lenght > 100)
{
result.IsSuccess = false;
result.Message = "Category Name length is too long";
result.Data = 0;
}
//handle .net runtime error//may be database is not aviable.
try
{
result.Data = this.catalogRepository.AddCategory(tCategory);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.Data = 0;
result.IsSuccess = false;
result.Message = ex.Message;
}
return result;
}
public GenericResult<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory)
{
GenericResult<IEnumerable<TCategory>> result = new GenericResult<IEnumerable<TCategory>>();
try
{
IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories();
result.Data = GetCategoryHierarchy(allCategories, parentCategory);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.IsSuccess = false;
result.Data = null;
result.Message = ex.Message;
}
return result;
}
If you don't want to throw an exception but prefer to return a result containing either the error or the value i.e. a MayBe that's fine in some situations. But to be honest in this situation I'd prefer simply throwing/passing through the exception.
I'd prefer returning an immutable struct as MayBe instead of a mutable class like you did. It's very similar to Nullable<T>, except it works on reference types and can store an error. Something like:
public struct MayBe<T>
{
private T value;
private Exception error;
public bool HasValue{get{return error==null;}}
public T Value
{
if(error!=null)
throw error;
else
return value;
}
public static MayBe<T> CreateError(Exception exception)
{
return new MayBe<T>(default(T),exception);
}
public static MayBe<T> CreateValue(T value)
{
return new MayBe<T>(value,null);
}
public static implicit operator MayBe<T>(T value)
{
return CreateValue(value);
}
public override string ToString()
{
if(HasValue)
return "Value: "+Value.ToString();
else
return "Error: "+Error.GetType().Name+" "+Error.Message;
}
}
Your code becomes
public MayBe<int> AddCategory(TCategory tCategory)
{
try
{
return this.catalogRepository.AddCategory(tCategory);
}
catch (Exception ex)
{
return MayBe<int>.CreateError(ex);
}
return result;
}
public MayBe<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory)
{
try
{
IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories();
return allCategories;
}
catch (Exception ex)
{
return MayBe<int>.CreateError(ex);
}
return result;
}
One problem I see with this implementation is that exceptions are not completely immutable. That can cause problems if the same MayBe<T> throws on multiple threads. Perhaps someone can suggest a better implementation.
I'd rather removing IsSuccess and Message and returning only the object. See below...
Take a look at my question Good practices when handling Exceptions in C#. You're returning errors instead of throwing exceptions, and in .NET, that's not suggested.
From MSDN:
Do not return error codes. Exceptions are the primary means of reporting errors in frameworks.
What you are doing is suggested in some articles/books I've read, including The Pragmatic Programmer: From Journeyman to Master and this Joel Spolsky article, but as said by MSDN, in .NET exceptions are better for this purpose.
Edit:
If you still want to do it that way (even if that could bring some problems to developers that are working with your code), I think that, in general, it could be a good way. In fact, I'm going to edit the question I linked on this answer to place a link to your code for an alternative of returning errors instead of throwing Exceptions in .NET
If your application scope is completely inside .NET scope, then this pattern is of no use and just as others have mentioned, you should let exceptions be thrown and you might want to change the exceptions.
However, if your application scope is wide that might include any other client side framework, probably via JSON, web services etc, and if client side framework does not properly support exceptions then this pattern may be useful. For example, in JSON based Javascript call, you will always expect a result, and a message indicating a failure on server side or not. Failure on client side could be either failure on server side or network failure, usually all client framework will detect and only report network failures and improperly coded framework will lead to chaos when you will not get any error report on client side of what exactly failed on server side.
One more place this pattern is very useful is, when you are writing some plugin in the UI or inside someone else's framework where just throwing exceptions can result in undesired results as after having exceptions, third party framework may say "Unexpected error" as they do not and they are not made to understand your exceptions. This pattern is useful while being inside someone else's framework and still letting underlying framework work correctly regardless of your failure. And you probably can communicate correctly within your app framework.
I recently have seen, and its still a bug, WPF stops processing some pending UI related activities if you set a source of an image that is a web address and that does not exist. You will see a network related exception traced, but WPF will incompletely stop processing anything that was in pending tasks and app still works but it does affect other UI elements where it should not.
The use of the automatic property is quite fine and I do not see any issues.
But I strongly discourge the pattern using a class as a result to tell the outside world that something failed. Return null or throw an exception when something badly fails.
hth
Mario

Handle JobExecutionException in Quartz.net

Probably a stupid question... but here goes anyway...
I have set up quartz, and can schedule jobs, and I can confirm that jobs (implementing the IJob interface) are working.
Looking at the documentation on the site, (Lesson 3 of the tutorial):
The only type of exception that you are allowed to throw from the execute method is JobExecutionException.
I would like that when an exception occurs that I haven't explicitly handled, it should throw a JobExecutionException, so that I can log it in the 'parent' application. I have wrapped my code in a try catch, and have thrown the JobExecutionException, but now where to handle it?
I don't call the execute method anywhere, that is handled by Quartz (on a separate thread). So, how do I handle that error when it occurs. I don't really want to swallow the error in the Job
I solved this problem by using a base class to catch all the exceptions:
public abstract class JobBase : IJob
{
protected JobBase()
{
}
public abstract void ExecuteJob(JobExecutionContext context);
public void Execute(JobExecutionContext context)
{
string logSource = context.JobDetail.FullName;
try
{
ExecuteJob(context);
}
catch (Exception e)
{
// Log exception
}
}
}
Your Job class should like this:
public class SomeJob : JobBase
{
public SomeJob()
{
}
public override void ExecuteJob(JobExecutionContext context)
{
// Do the actual job here
}
}
Typically you would set up the execute method of your job as follows:
try
{
// the work you want to do goes here
}
catch (ExceptionTypeYouWantToHandle1 ex1)
{
// handle exception
}
catch (ExceptionTypeYouWantToHandle2 ex2)
{
// handle exception
}
// and so on
catch (Exception ex)
{
// something really unexpected happened, so give up
throw new JobExecutionException("Something awful happened", ex, false); // or set to true if you want to refire
}
At this point the scheduler itself will log the exception to wherever it is logging (based on the configuration).
As already mentioned, the correct way to "detect" JobExecutionException's on a global level is to implement and register an IJobListener and check if the JobExecutionException parameter in the JobWasExecuted() method is != null.
However, the problem I had (and judging from the additional comment of the OP, he faced this too) was that Quartz did not handle the JobExecutionException (as it should) which resulted in an unhandled exception killing the application.
So far, I was using the precompiled DLL from the Quartz.NET 2.0.1 release (.NET3.5) package. To get to the bottom of the problem, i referenced the Quartz project/sourcecode and to my astonishment it was suddenly working?!
As a point of interest, this is the Quartz library code that executes the IJob and handles the JobExecutionException:
try {
if (log.IsDebugEnabled) {
log.Debug("Calling Execute on job " + jobDetail.Key);
}
job.Execute(jec);
endTime = SystemTime.UtcNow();
} catch (JobExecutionException jee) {
endTime = SystemTime.UtcNow();
jobExEx = jee;
log.Info(string.Format(CultureInfo.InvariantCulture, "Job {0} threw a JobExecutionException: ", jobDetail.Key), jobExEx);
} catch (Exception e) {
// other stuff here...
}
The next thing was to reference my freshly compiled DLL direcly and this was working as well. Sadly i can't tell you why this works and i currently don't have any time to get into it any further, but maybe this helps someone. Maybe some else can confirm this and even contribute an explanation. It may have something to do with different target platforms (x86/64bit)?

Categories