Web Api error return
When using .net Web Api to build Endpoint to provide external access, a unified error return format is often required. C# Exception Handling Best Practices.
If according to the previous article , the exception ErrorCodeException with ErrorCode is used, then when an error is returned in WebApi, just return ErrorCode.
code show as below:
[HttpPut] [Authorize] public IActionResult Update(UpdatetNickNameRequest request) { try { long userId = User.GetUserId(); _identityService.SetNickName(userId, request.NickName); return Ok(); } catch (IdentityException ex) { //Deal with it accordingly //... ... return new BadRequestObjectResult(ex.ErrorCode); } catch (OtherException ex) { //Deal with it accordingly //... ... return new BadRequestObjectResult(ex.ErrorCode); } }
C# Exception Handling Best Practices
As everyone said in the comments, you can use ExceptionFilter, or middleware, to catch all kinds of exceptions uniformly.
You can also use
UseExceptionHandler
extension methods to post exceptions to a custom path.
For example, if you use ExceptionFilter for unified processing, the code is as follows:
public class ExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { ErrorCode errorCode = context.Exception is ErrorCodeException ex ? ex.ErrorCode : ErrorCode.Empty; //Other operations, such as logs, etc., or make different treatments according to different ErrorCodes context.Result = new BadRequestObjectResult(errorCode); context.ExceptionHandled = true; } }
C# Exception Handling Best Practices
Will be ExceptionFilter
registered to services
post, you can in the services.AddControllers()
method, the global add Filter, avoid manually add every method.
code show as below:
services.AddControllers(options => { options.Filters.AddService<UserActivityFilter>(); })
C# Exception Handling Best Practices
In short, the point is that we returned ErrorCode. C# Exception Handling Best Practices.
The ErrorCode class contains the Id, Name, and Message properties, which is convenient for the client to process after receiving the error return.
After the custom client receives the return of the Api, it checks the HttpStatusCode. If it is unsuccessful (not 2xx), then it can also directly throw an ErrorCodeException with ErrorCode.
In this way, the processing of the front and back ends becomes consistent and simple. Especially if you also use .net technology in the front-end, such as blazor, xamarin, wpf, winform, etc., the same CodeBase can be used in the front-end and back-end.
Exception capture
In the previous articles, we have been paying attention to the throwing of Exception. Now let’s pay attention to the capture of Exception.
Those basic catch/finally will not be repeated here, and I will talk about the actual phenomena and problems in several projects.
Don’t eat the abnormal
Don’t eat exceptions. There are two levels. One is to ignore them directly. For example, if all Exceptions are caught, they are not handled properly. Isn’t it the result of hastily in the coding process.
The second level is mainly to pay attention to here, that is, do not hide the type of exception when catching, that is, do not catch (Exception ex), which means that the type of exception is hidden and it eats up the opportunity to take different measures for different errors.
Microsoft’s code analysis also directly gives the rule CA1031: Don’t catch general exception types .
Checked Exception
CE is to ensure that all your exceptions are caught. It often provides checks on Exception at the compilation level to ensure that your program will not terminate due to unhandled exceptions.
When writing a reliable program, the programmer needs to know what exceptions the called method throws, whether I need to deal with it, wrap it, or just throw it out. In short, we need to have a way to obtain such information.
Of course, Checked Exception will definitely bring more code volume, and when the project is initially established, it is often necessary to modify one place, while moving the entire chain of code, layer by layer.
Therefore, some people like CE and think that it brings rules and improves the quality of team code; of course, some people think that it brings cumbersomeness.
The benevolent see the benevolent and the wise see the wisdom, so these arguments are not added here. Argument 1 , Argument 2 , Argument 3 , Argument 4
.net vs java
The two languages have to be compared, and each world has to learn from each other.
Students who are familiar with java syntax will definitely know that there is the keyword throws in the java method definition:
public int div(int i,int j) throws Exception {...}
C# Exception Handling Best Practices
The keyword throws ensures that you can know what kind of exception a method throws from the method definition, and you will not miss exceptions directly with the help of compiler checks or intelligent reminders from the IDE.
There is no similar implementation in c#, you can see the discussion on Stackoverflow .
So when you call a method in the .net world, how do you properly know what kind of exception the method throws? After knowing, we can decide whether to handle this exception or continue to throw it.
The current answer is: comment! (Don’t laugh, very serious solution).
/// <exception cref="IdentityService.IdentityService">Write Exception comments like this</exception> public void SetNickName(long userId, string newNickName) { //.... Ensure.NickNameNotExisted(newNickName); //.... }
C# Exception Handling Best Practices
When you look at the source code of .net, you will see a good list of exceptions in the comments of all methods.
There are several problems:
- No one in our team writes comments, what should I do?
- When calling the method, there is no intelligent reminder of any exceptions, so we often ignore
- If you want to see the exception, you have to F12 to see the definition, which is too tedious.
There are many problems that cannot be solved only technically, but we can use some Review tools to check the team’s code and make requests as much as possible.
In addition you will love ctrl + k, ctrl+i
this shortcut, he can help you quickly see annotate documents, to see what is abnormal.
Visual studio extension recommendation
Here, I recommend a visual studio extension, yes, its name is Checked Exceptions , which is a must-have extension for me.
This plug-in will use the form of comments to assist in the realization of the Checked Exception function, and can quickly add corresponding comments.
There is a small tip: if you use this plug-in from the beginning of the project, it will be less tormented. If you use it halfway, it is also a good tool for testing the robustness of the team’s code.
In addition, there may be some bugs in this extension, which leads to constant prompts even if Exception is annotated, so I usually don’t always enable it, but use it as a checking tool when doing Code Review.
This can better solve the shortcomings of Checked Exception mentioned above, and take advantage of its advantages.
Common pattern
Don’t throw repeatedly
This is just a simple reminder, see the following code.
void BadSmellMethod() { try { ..... } catch(Exception ex) { //.... some thing // Wrong approach throw ex; } } void GoodMethod() { try { ..... } catch { //... some thing // Wrong approach throw; } }
C# Exception Handling Best Practices
Simply put, it is repeated throwing, losing the StackTrace between the original method that caused the exception and the current method call.
There are corresponding rules in code analysis. CA2200 .
In asp.net core
When catching an exception, an exception is often thrown all the way, or wrapped and then thrown until the end. If the end is not caught, then the program will be aborted, which no one wants to see.
In asp.net core, this end point is the Controller controller, so we need to call the required Service in the Controller method to handle those exceptions that require special handling, and then use global error handling (ExceptionFilter, middleware, etc.) to take care of others The exception.
In xamarin.forms
If you are a fellow and use xamarin.forms, then you must know the MVVM mode.
The end of the exception is often in the ViewModel in the MVVM mode, such as LoginPageViewModel. The same ViewModel calls various services. You need to handle the exceptions that need to be handled in the current scene here, and then customize the global error handling to take care of other exceptions.
Conclusion
This article briefly introduces the problem of catching exceptions in specific projects. Welcome everyone to communicate and correct.
In the next article, we will focus on Exception in asynchronous programming and global error handling.
thanks for reading C# Exception Handling Best Practices.