From 191d401178f5f28e72e1473e9ea135dbe53c4a34 Mon Sep 17 00:00:00 2001 From: abdulrahmanshabeekmohamed Date: Sat, 14 Dec 2024 07:27:31 +0530 Subject: [PATCH] Use What, Why, How and Summary Components --- .../Blogs/Wasm/DynamicallyLoadImage.razor | 134 ++-- .../Blogs/Wasm/DynamicallyStreamImage.razor | 190 +++--- .../Pages/Blogs/Wasm/SecuringWithOIDC.razor | 584 +++++++++--------- .../FreeUpResourcesWithCancellation.razor | 154 ++--- .../Pages/Blogs/UnitTestingHttpClient.razor | 198 +++--- .../Pages/Blogs/HealthChecksInASPNET.razor | 360 ++++++----- .../UnitTestingHostedServicesInASPNET.razor | 320 +++++----- 7 files changed, 936 insertions(+), 1004 deletions(-) diff --git a/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyLoadImage.razor b/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyLoadImage.razor index 54894a1dec..1220d654c8 100644 --- a/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyLoadImage.razor +++ b/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyLoadImage.razor @@ -4,96 +4,82 @@ -

What we gonna do?

- -

- In this article, let's learn about how to improve performance by - dynamically loading an image in Blazor WASM apps. -

- -

- Note: If you have not done so already, I recommend you read the article on - Printing barcode to label printer from Blazor WASM. -

- - - -

Why we gonna do?

- -

- Few months ago as of writing this article, I was observing some performance issues in I ❤️ .NET home screen. - The home screen was taking more than 10 seconds to load as I was showing all the posters in home screen. The numbers of posters at that time was some - what close to 80+. I decided to improve performance and reduce the load time to give better user experience to - the users. That's when I decided to load the images dynamically. When I say dynamically, I mean load the image only when it is required via a user - action. This is called Dynamic Loading. I decided to load 5 images by default and kept remaining images inside - show more button. This drastically improved the performance and reduced the load time. In this article, I will teach you how to implement dynamic - loading in Blazor WASM apps. -

+ +

+ In this article, let's learn about how to improve performance by + dynamically loading an image in Blazor WASM apps. +

-

Use Case for Dynamic Loading

+

+ Note: If you have not done so already, I recommend you read the article on + Printing barcode to label printer from Blazor WASM. +

+
+ + +

+ Few months ago as of writing this article, I was observing some performance issues in I ❤️ .NET home screen. + The home screen was taking more than 10 seconds to load as I was showing all the posters in home screen. The numbers of posters at that time was some + what close to 80+. I decided to improve performance and reduce the load time to give better user experience to + the users. That's when I decided to load the images dynamically. When I say dynamically, I mean load the image only when it is required via a user + action. This is called Dynamic Loading. I decided to load 5 images by default and kept remaining images inside + show more button. This drastically improved the performance and reduced the load time. In this article, I will teach you how to implement dynamic + loading in Blazor WASM apps. +

-

- The use case of dynamic loading are, -

+

+ The use case of dynamic loading are, +

-
-
Load Request
-
Load the image only when it is required. This is useful when the image is not required immediately or load only after an interaction like button click.
+
+
Load Request
+
Load the image only when it is required. This is useful when the image is not required immediately or load only after an interaction like button click.
-
Multiple Images
-
Any interaction that changes the displayed image if there is more than once.
-
+
Multiple Images
+
Any interaction that changes the displayed image if there is more than once.
+
+
- + +

Implementing Dynamic Loading

-

How we gonna do?

- -

Implementing Dynamic Loading

+

+ To implement dynamic loading, we need to store image path inside a variable in razor component and assign the image path as + src in <img> tag. If the path is empty we can hide the code that + sources the image. This will prevent the image from loading. The image will only be displayed to the user if the path is not empty. +

-

- To implement dynamic loading, we need to store image path inside a variable in razor component and assign the image path as - src in <img> tag. If the path is empty we can hide the code that - sources the image. This will prevent the image from loading. The image will only be displayed to the user if the path is not empty. -

+ - + +

+ + Click on Show Image button to load the image dynamically. + +

+ + + +
- +

Advantages of Dynamic Loading

- -

- - Click on Show Image button to load the image dynamically. - +

+ The advantages of dynamic loading are as follows,

- - - -
- - -

Advantages of Dynamic Loading

- -

- The advantages of dynamic loading are as follows, -

- -
    -
  • Bandwidth Savings.
  • -
  • Faster Page load.
  • -
  • Improved Performance.
  • -
- +
    +
  • Bandwidth Savings.
  • +
  • Faster Page load.
  • +
  • Improved Performance.
  • +
+
- -

Summary

- -

+

In this article, we learnt how to dynamically loading image and improve performance in Blazor WASM apps by going through the performance issues happened in I ❤️ .NET home screen. We also learnt about the advantages of dynamic loading and its use cases along with a demo of dynamic loading in action. I hope you enjoyed reading this article. Thank you for reading. -

+
\ No newline at end of file diff --git a/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyStreamImage.razor b/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyStreamImage.razor index ad0ce39ab0..afc81657cf 100644 --- a/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyStreamImage.razor +++ b/BlazorDemoComponents/Pages/Blogs/Wasm/DynamicallyStreamImage.razor @@ -4,128 +4,106 @@ -

What we gonna do?

- -

- In this article let's learn how to prevent unauthorised use of images from crawlers in Blazor WASM apps. -

- -

- Note: If you have not done so already, I recommend you read the article on - Improve performance by dynamically loading image in Blazor WASM. -

- - - -

Why we gonna do?

- -

- Every now and then somebody builds a web site with the brilliant idea that they will uses images from other people's web sites as part of their - content. They enjoy the benefits of the traffic (for example, advertising revenue), while the image owner ends up paying for the - bandwidth. This is called image leeching. Image leeching or unauthorised use of images is a common problem on the web. It is a - problem that has been around since the early days of the web. -

- - - -

How we gonna do?

- -

Use Case for Dynamic Streaming

- -

- We can also stream image into blazor wasm app using Javascript Interop. The - image will be stored as BLOB and we can create a temporary URL to display - the image. The benefit of using temporary URL is that it will be difficult to crawl the image and it will make stealing / leeching difficult. Thus we - can prevent unauthorised use of image. -

- - - -

Implementing Dynamic Streaming

- -

- First, we need to remove static image src reference from <img> tag - and add a ElementReference to the <img> tag. Now we need to get the - image Stream using HttpClient and convert it to - DotNetStreamReference and pass the ElementReference and - DotNetStreamReference to Javascript Interop method. - The Javascript Interop method transforms the DotNet Stream to - array buffer and creates BLOB and use that to create a - temporary URL and set it as src of the - <img> tag. -

- - - - - - - - - - -

- - The below image is streamed dynamically with temporary URL. This can be verified by checking the network tab in the - developer tools and the URL of the displayed image. - + +

+ In this article let's learn how to prevent unauthorised use of images from crawlers in Blazor WASM apps.

- - - -
- - -

- If we inspect the image element in the developer tools, we can see that the src of the image is a - temporary BLOB URL as shown below. -

- -
- Temporary URL -
+

+ Note: If you have not done so already, I recommend you read the article on + Improve performance by dynamically loading image in Blazor WASM. +

+ + + +

+ Every now and then somebody builds a web site with the brilliant idea that they will uses images from other people's web sites as part of their + content. They enjoy the benefits of the traffic (for example, advertising revenue), while the image owner ends up paying for the + bandwidth. This is called image leeching. Image leeching or unauthorised use of images is a common problem on the web. It is a + problem that has been around since the early days of the web. +

+
+ +

Use Case for Dynamic Streaming

+

+ We can also stream image into blazor wasm app using Javascript Interop. The + image will be stored as BLOB and we can create a temporary URL to display + the image. The benefit of using temporary URL is that it will be difficult to crawl the image and it will make stealing / leeching difficult. Thus we + can prevent unauthorised use of image. +

-

- When you copy that URL and try to access it via browser you get an Error 404 saying that file cannot be accessed - as shown below. -

+

Implementing Dynamic Streaming

+ +

+ First, we need to remove static image src reference from <img> tag + and add a ElementReference to the <img> tag. Now we need to get the + image Stream using HttpClient and convert it to + DotNetStreamReference and pass the ElementReference and + DotNetStreamReference to Javascript Interop method. + The Javascript Interop method transforms the DotNet Stream to + array buffer and creates BLOB and use that to create a + temporary URL and set it as src of the + <img> tag. +

-
- Image Access Error -
+ + + + + +

+ + The below image is streamed dynamically with temporary URL. This can be verified by checking the network tab in the + developer tools and the URL of the displayed image. + +

+ + + +
+ +

+ If we inspect the image element in the developer tools, we can see that the src of the image is a + temporary BLOB URL as shown below. +

- +
+ Temporary URL +
-

- As a result, it makes it more difficult to download the image outside the application and - prevents unauthorised use of the image. -

+

+ When you copy that URL and try to access it via browser you get an Error 404 saying that file cannot be accessed + as shown below. +

- +
+ Image Access Error +
-

Advantages of Dynamic Streaming

+

+ As a result, it makes it more difficult to download the image outside the application and + prevents unauthorised use of the image. +

-

- The advantages of dynamic streaming are as follows, -

+

Advantages of Dynamic Streaming

-
    -
  • Unauthorised Image Access.
  • -
  • Bandwidth Savings.
  • -
  • Cost Savings.
  • -
- - +

+ The advantages of dynamic streaming are as follows, +

-

Summary

+
    +
  • Unauthorised Image Access.
  • +
  • Bandwidth Savings.
  • +
  • Cost Savings.
  • +
+
-

+

In this article, we learnt about the image leeching problem and how to prevent it by dynamically streaming image in Blazor WASM apps. We also learnt about the advantages of dynamic streaming. Hope you enjoyed reading this article. Thank you for reading from us. -

+
\ No newline at end of file diff --git a/BlazorDemoComponents/Pages/Blogs/Wasm/SecuringWithOIDC.razor b/BlazorDemoComponents/Pages/Blogs/Wasm/SecuringWithOIDC.razor index 5cf1e238dd..24888a0d9b 100644 --- a/BlazorDemoComponents/Pages/Blogs/Wasm/SecuringWithOIDC.razor +++ b/BlazorDemoComponents/Pages/Blogs/Wasm/SecuringWithOIDC.razor @@ -4,309 +4,307 @@ -

What we gonna do?

+ +

+ In this article let's learn how to secure Blazor WASM app with OAuth and + OpenID Connect using Identity Server. +

+
+ + +

+ Blazor WASM app runs on Client thus cannot be trusted and just like any other JavaScript apps, any authorization can be bypassed. + So its very important to focus on securing the API Our Client app is talking to. +

+ +

+ Blazor just like any other SPA Applications runs on the Client side and the most common approach is to use OAuth2 and OpenID Connect. + The reason behind this tokens based engineering design is, +

+ +
    +
  • No CSRF protection required for server endpoints.
  • +
  • Tokens have narrower permissions.
  • +
  • Tokens tend to have short life time (1 Hour).
  • +
  • Tokens can be revoked if it is a reference token.
  • +
+
+ + +

Registering the Client

+ +

+ The first step is to register the Blazor WASM app in the Identity Server. +

+ +

+ In this demo, lets make use of the demo Identity Server provided by Duende. You can access the demo Identity Server at + https://demo.duendesoftware.com. +

+ +

+ The manual registration usually involves creating a Client in the Identity Server and it looks like the + following: +

+ + + +

Configuring the Client

+ +

+ The next step is to install the Microsoft.AspNetCore.Components.WebAssembly.Authentication + Nuget package in the Blazor WASM app. The package provides a set of code that help the app authenticate users and obtain tokens. +

+ +

+ Now we need to include AuthenticationService.js in the index.html file as + shown below. It is this service that handles the OpenID Connect flow. Our app will call the methods defined in this script to perform the authentication + operations. +

+ + -

- In this article let's learn how to secure Blazor WASM app with OAuth and - OpenID Connect using Identity Server. -

+

Authentication Page

+ +

+ The part of the app that does that is the authentication component which defines the routes required for handling different + authentication stages. Now lets add such a page and name it as Authentication.razor. + The RemoteAuthenticatorView component manages the appropriate actions at the each stages of authentication. +

-

Why we gonna do?

+ -

- Blazor WASM app runs on Client thus cannot be trusted and just like any other JavaScript apps, any authorization can be bypassed. - So its very important to focus on securing the API Our Client app is talking to. -

- -

- Blazor just like any other SPA Applications runs on the Client side and the most common approach is to use OAuth2 and OpenID Connect. - The reason behind this tokens based engineering design is, -

- -
    -
  • No CSRF protection required for server endpoints.
  • -
  • Tokens have narrower permissions.
  • -
  • Tokens tend to have short life time (1 Hour).
  • -
  • Tokens can be revoked if it is a reference token.
  • -
- -

How we gonna do?

- -

Registering the Client

- -

- The first step is to register the Blazor WASM app in the Identity Server. -

- -

- In this demo, lets make use of the demo Identity Server provided by Duende. You can access the demo Identity Server at - https://demo.duendesoftware.com. -

- -

- The manual registration usually involves creating a Client in the Identity Server and it looks like the - following: -

- - - -

Configuring the Client

- -

- The next step is to install the Microsoft.AspNetCore.Components.WebAssembly.Authentication - Nuget package in the Blazor WASM app. The package provides a set of code that help the app authenticate users and obtain tokens. -

- -

- Now we need to include AuthenticationService.js in the index.html file as - shown below. It is this service that handles the OpenID Connect flow. Our app will call the methods defined in this script to perform the authentication - operations. -

- - - -

Authentication Page

- -

- The part of the app that does that is the authentication component which defines the routes required for handling different - authentication stages. Now lets add such a page and name it as Authentication.razor. - The RemoteAuthenticatorView component manages the appropriate actions at the each stages of authentication. -

- - - -

Registering OIDC Services

- -

- Now we need to configure and register Authorization in the Program.cs in - the blazor WASM app. We need to call AddOidcAuthentiaction and we need to use the - ClientID from the above registration while configuring the blazor WASM app. - The configuration looks like the following: -

- - - -

- For demo purpose, I'make using the interactive.public.short ClientID from the - demo Duende Identity Server. We are using code flow which means the middleware in server will execute necessary steps to enable PKCE protection. -

- -

Redirect to Login

- -

- Next, we need to add RedirectToLogin Component which will manage redirecting unauthorized users to the login page. - The current URL that the user is attempting to access is maintained by so that they can be returned to that page if authentication is successful. This - happens behind the scenes using Navigation History State. -

- - - -

- Thats it! We have successfully secured the Blazor WASM app with OIDC using Duende Identity Server. - Now if we try to login to the app, we will be redirected to the Identity Server login page and after successful login, we will be redirected back to the app. -

- -

Demo

- - -

- -

    -
  1. Click on the Login button. This will redirected to demo Duende Identity Server login page.
  2. -
  3. - Enter the default credential display on the login screen which is either bob/bob or alice/alie. After successful login, you - will be redirected back to the I Love .NET app. -
  4. -
  5. Then you can see Log out button. Click on the Log out button to log out from the app.
  6. -
  7. - This will redirected to demo Duende Identity Server logout page and logout will happens at the Identity Server level to avoid cross - site scripting and forgery and after successful logout, you will be redirected back to the I Love .NET app. -
  8. -
- +

Registering OIDC Services

+ +

+ Now we need to configure and register Authorization in the Program.cs in + the blazor WASM app. We need to call AddOidcAuthentiaction and we need to use the + ClientID from the above registration while configuring the blazor WASM app. + The configuration looks like the following:

- - - -
- -

- Here is the recap of complete flow. -

- -
    -
  1. -

    Initiate Login

    -
    - Initiate Login -
    -
  2. -
  3. -

    Login Redirect

    -
    - Login Redirect -
    -
  4. -
  5. -

    Enter Credentials

    -
    - Enter Credentials -
    -
  6. -
  7. -

    Completing Login

    -
    - Completing Login -
    -
  8. -
  9. -

    Initiate Log Out

    -
    - Initiate Log Out -
    -
  10. -
  11. -

    Processing Log Out

    -
    - Processing Log Out -
    -
  12. -
  13. -

    End Session

    -
    - End Session -
    -
  14. -
  15. -

    Log Out Callback

    -
    - Log Out Callback -
    -
  16. -
  17. -

    Log Out Complete

    -
    - Log Out Complete -
    -
  18. -
- -

- This looks awesome. We have successfully secured the Blazor WASM app with OIDC using - Identity Server. -

- -

Passing Access Token to API

- -

- Passing Access tokens to API can be easily implemented by using AuthorizationMessageHandler and register it with - along with AddHttpClient in Program.cs. -

- - - -

Displaying parts of UI

- -

- Now let's see how we can shown parts of the UI to user based on authentication status. We can use AuthorizeView - component to show different parts of the UI based on the authentication status. The AuthorizeView component - has two child components Authorized and NotAuthorized which will be - displayed based on the authentication status. I have used the exact same code above to show login button when user is not authenticated and - show logout button when user is authenticated. -

- - -

- Please login using above demo to see different section getting displayed for Bob and Alice + + + +

+ For demo purpose, I'make using the interactive.public.short ClientID from the + demo Duende Identity Server. We are using code flow which means the middleware in server will execute necessary steps to enable PKCE protection. +

+ +

Redirect to Login

+ +

+ Next, we need to add RedirectToLogin Component which will manage redirecting unauthorized users to the login page. + The current URL that the user is attempting to access is maintained by so that they can be returned to that page if authentication is successful. This + happens behind the scenes using Navigation History State.

-
- - - -
- -

User Details

- -

- Now to get details of the user we can rely on context (AuthenticationState) provided by the - AuthorizeView component. We can use context.User.Identity!.Name to get - the name of the user. We can also use context.User.Identity!.IsAuthenticated to check if the user is - authenticated or not. And we can also access the claims of the user using context.User.Claims. -

- -

- This is how I display logged in user name in above demo. We can also change this to email by simply changing - options.UserOptions.NameClaim in Program.cs file. This will now display email instead of name. -

- - - -

Authentication State Provider

- -

- AuthenticationStateProvider is the underlying built in service that provides the current authentication state - to the application. It is this that powers AuthorizeView and CascadingAuthenticationState components. However we should not use this service directly - because anonymous changes in it will not notify UI components. -

- -

- So the safe and better way is to get [CascadingParameter] Task<AuthenticationState> authenticationStateTask { get; set; }. - Now we can use this to get the authentication state and use it in the UI components to conditionally write logic as shown below. -

- - - -

Prevent UnAuthorized Access

- -

- Now lets see how to secure pages from UnAuthorized access. We need to add - [Authorize] attribute to the page or component that we want to secure. This will restrict access to the page or - component to only authenticated users. However to restrict access to child components within a component or page, we need to use - AuthorizeView component. -

- -

- To make sure users are notified with right message we need to use AuthorizeRouteView which we need to replace the - RouteView in the router. This will now show Not Authorized message to the user when they try to access a page - that they are not authorized to access. -

- -

- To customise the default Not Authorized message we can use NotAuthorized render fragment within the - AuthorizeRouteView component. This will now show the custom message to the user when they try to access a page. -

- -

- Now instead of showing custom message we can simply redirect the user to login page when they try to access a page that they are not authorized to access. - This can be done by using RedirectToLogin component within the AuthorizeRouteView - component. This will now redirect the user to login page when they try to access a page that they are not authorized to access. -

- - - -

Customization

- -

- We can also Customize the text showing in UI while authentication process is happening. This can be done in RemoteAuthenticatorView component - by providing the LoggingIn, LogInFailed, LogOut, LogOutFailed, LogOutSucceeded RenderFragments. -

- -

- You can also customise the messages displayed to the user during the authentication process. The messages can be customised by providing the - AuthenticationMessage component in the App.razor file as shown below. -

- - - -

Summary

- -

+ + + +

+ Thats it! We have successfully secured the Blazor WASM app with OIDC using Duende Identity Server. + Now if we try to login to the app, we will be redirected to the Identity Server login page and after successful login, we will be redirected back to the app. +

+ +

Demo

+ + +

+ +

    +
  1. Click on the Login button. This will redirected to demo Duende Identity Server login page.
  2. +
  3. + Enter the default credential display on the login screen which is either bob/bob or alice/alie. After successful login, you + will be redirected back to the I Love .NET app. +
  4. +
  5. Then you can see Log out button. Click on the Log out button to log out from the app.
  6. +
  7. + This will redirected to demo Duende Identity Server logout page and logout will happens at the Identity Server level to avoid cross + site scripting and forgery and after successful logout, you will be redirected back to the I Love .NET app. +
  8. +
+ +

+ + + +
+ +

+ Here is the recap of complete flow. +

+ +
    +
  1. +

    Initiate Login

    +
    + Initiate Login +
    +
  2. +
  3. +

    Login Redirect

    +
    + Login Redirect +
    +
  4. +
  5. +

    Enter Credentials

    +
    + Enter Credentials +
    +
  6. +
  7. +

    Completing Login

    +
    + Completing Login +
    +
  8. +
  9. +

    Initiate Log Out

    +
    + Initiate Log Out +
    +
  10. +
  11. +

    Processing Log Out

    +
    + Processing Log Out +
    +
  12. +
  13. +

    End Session

    +
    + End Session +
    +
  14. +
  15. +

    Log Out Callback

    +
    + Log Out Callback +
    +
  16. +
  17. +

    Log Out Complete

    +
    + Log Out Complete +
    +
  18. +
+ +

+ This looks awesome. We have successfully secured the Blazor WASM app with OIDC using + Identity Server. +

+ +

Passing Access Token to API

+ +

+ Passing Access tokens to API can be easily implemented by using AuthorizationMessageHandler and register it with + along with AddHttpClient in Program.cs. +

+ + + +

Displaying parts of UI

+ +

+ Now let's see how we can shown parts of the UI to user based on authentication status. We can use AuthorizeView + component to show different parts of the UI based on the authentication status. The AuthorizeView component + has two child components Authorized and NotAuthorized which will be + displayed based on the authentication status. I have used the exact same code above to show login button when user is not authenticated and + show logout button when user is authenticated. +

+ + +

+ Please login using above demo to see different section getting displayed for Bob and Alice +

+
+ + + +
+ +

User Details

+ +

+ Now to get details of the user we can rely on context (AuthenticationState) provided by the + AuthorizeView component. We can use context.User.Identity!.Name to get + the name of the user. We can also use context.User.Identity!.IsAuthenticated to check if the user is + authenticated or not. And we can also access the claims of the user using context.User.Claims. +

+ +

+ This is how I display logged in user name in above demo. We can also change this to email by simply changing + options.UserOptions.NameClaim in Program.cs file. This will now display email instead of name. +

+ + + +

Authentication State Provider

+ +

+ AuthenticationStateProvider is the underlying built in service that provides the current authentication state + to the application. It is this that powers AuthorizeView and CascadingAuthenticationState components. However we should not use this service directly + because anonymous changes in it will not notify UI components. +

+ +

+ So the safe and better way is to get [CascadingParameter] Task<AuthenticationState> authenticationStateTask { get; set; }. + Now we can use this to get the authentication state and use it in the UI components to conditionally write logic as shown below. +

+ + + +

Prevent UnAuthorized Access

+ +

+ Now lets see how to secure pages from UnAuthorized access. We need to add + [Authorize] attribute to the page or component that we want to secure. This will restrict access to the page or + component to only authenticated users. However to restrict access to child components within a component or page, we need to use + AuthorizeView component. +

+ +

+ To make sure users are notified with right message we need to use AuthorizeRouteView which we need to replace the + RouteView in the router. This will now show Not Authorized message to the user when they try to access a page + that they are not authorized to access. +

+ +

+ To customise the default Not Authorized message we can use NotAuthorized render fragment within the + AuthorizeRouteView component. This will now show the custom message to the user when they try to access a page. +

+ +

+ Now instead of showing custom message we can simply redirect the user to login page when they try to access a page that they are not authorized to access. + This can be done by using RedirectToLogin component within the AuthorizeRouteView + component. This will now redirect the user to login page when they try to access a page that they are not authorized to access. +

+ + + +

Customization

+ +

+ We can also Customize the text showing in UI while authentication process is happening. This can be done in RemoteAuthenticatorView component + by providing the LoggingIn, LogInFailed, LogOut, LogOutFailed, LogOutSucceeded RenderFragments. +

+ +

+ You can also customise the messages displayed to the user during the authentication process. The messages can be customised by providing the + AuthenticationMessage component in the App.razor file as shown below. +

+ + +
+ + In this article, we learnt about the OpenID Connect and how to secure the Blazor WASM app with OIDC using Identity Server. We started with Authentication.js and learnt about the Authentication page and how it helps in handling the authentication process behind the scenes. We also learnt about the AuthorizeRouteView and how it helps in redirecting the user to login on application load along with customising the messages displayed to the user during the authentication process. -

+
\ No newline at end of file diff --git a/HTTPClientDemoComponents/Pages/Blogs/FreeUpResourcesWithCancellation.razor b/HTTPClientDemoComponents/Pages/Blogs/FreeUpResourcesWithCancellation.razor index d852dd9550..b687544bf1 100644 --- a/HTTPClientDemoComponents/Pages/Blogs/FreeUpResourcesWithCancellation.razor +++ b/HTTPClientDemoComponents/Pages/Blogs/FreeUpResourcesWithCancellation.razor @@ -4,98 +4,98 @@ -

What we gonna do?

- -

- Cancelling requests can be beneficial to performance, both at level of - bandwidth consumption and scalability. Let's learn how and I'll guide - you through this. We will start by learning why we should cancel requests when we no longer need them. -

+ +

+ Cancelling requests can be beneficial to performance, both at level of + bandwidth consumption and scalability. Let's learn how and I'll guide + you through this. We will start by learning why we should cancel requests when we no longer need them. +

+
-

Why we gonna do?

+ +

+ Imagine we're using HttpClient to get a data. Chances are that the user of your application will navigate away + or press a cancel button. In such a case, you want to be able to handle that instead of just letting the + request continue. The reasoning behind this is that behind the scenes, HttpClient works with + async tasks. There's another reason, though. It's not unheard of a timeout + to happen. If that happens, we want to be notified of that so we can gracefully handle such a timeout. In such a case, it is due to the timeout + that the task gets canceled. +

-

- Imagine we're using HttpClient to get a data. Chances are that the user of your application will navigate away - or press a cancel button. In such a case, you want to be able to handle that instead of just letting the - request continue. The reasoning behind this is that behind the scenes, HttpClient works with - async tasks. There's another reason, though. It's not unheard of a timeout - to happen. If that happens, we want to be notified of that so we can gracefully handle such a timeout. In such a case, it is due to the timeout - that the task gets canceled. -

+

+ It's important to know that cancelling a task that's no longer needed will free up the thread that is used to + run the task. That means that thread is potentially returned to the thread pool where it can be used for other work. + Cancellation in short helps to, +

-

- It's important to know that cancelling a task that's no longer needed will free up the thread that is used to - run the task. That means that thread is potentially returned to the thread pool where it can be used for other work. - Cancellation in short helps to, -

+
    +
  • Save threads which can be used to handle other tasks / requests.
  • +
  • Save db calls which can save compute cost.
  • +
  • Save data transferred over network.
  • +
+
-
    -
  • Save threads which can be used to handle other tasks / requests.
  • -
  • Save db calls which can save compute cost.
  • -
  • Save data transferred over network.
  • -
+ +

+ Note: If you have not done so already, I recommend you read the article on + Improving performance and memory use while accessing APIs using HTTPClient in dotnet. +

-

How we gonna do?

+

Cancellation Token Source and Cancellation

-

- Note: If you have not done so already, I recommend you read the article on - Improving performance and memory use while accessing APIs using HTTPClient in dotnet. -

+

+ To support cancelation of async tasks, a + CancellationTokenSource and a CancellationToken are used. A + CancellationTokenSource is an object, which manages and sends cancellation + notifications to the individual cancellation tokens. It exposes such a CancellationToken via its token property. + That CancellationToken is a lightweight value passed to one or more listeners, typically as a method parameter. +

-

Cancellation Token Source and Cancellation

+

+ Listeners should then monitor the value of the IsCancellationRequested property of that token and react accordingly. + From that, it follows that a CancellationToken is what we need to pass to each task returning method we want to + listen to cancellation. So, the idea is that we provide these cancellation tokens to whichever part of our application we want to listen to cancellation + and cancel itself. And we use the CancellationToken source to effectively request them to cancel themselves, which it + does by sending notifications to those tokens. +

-

- To support cancelation of async tasks, a - CancellationTokenSource and a CancellationToken are used. A - CancellationTokenSource is an object, which manages and sends cancellation - notifications to the individual cancellation tokens. It exposes such a CancellationToken via its token property. - That CancellationToken is a lightweight value passed to one or more listeners, typically as a method parameter. -

+

Supporting Cancellation while reading data from API

-

- Listeners should then monitor the value of the IsCancellationRequested property of that token and react accordingly. - From that, it follows that a CancellationToken is what we need to pass to each task returning method we want to - listen to cancellation. So, the idea is that we provide these cancellation tokens to whichever part of our application we want to listen to cancellation - and cancel itself. And we use the CancellationToken source to effectively request them to cancel themselves, which it - does by sending notifications to those tokens. -

+

+ All we need to do now is to initialize a CancellationTokenSource and set CancelAfter() + a timeout. Then, we pass the token to the HTTPClient SendAsync method. + We can then use the token to cancel the request if it takes too long. We can also use the token to cancel the request if the user navigates away. +

-

Supporting Cancellation while reading data from API

+

+ Note: that for demo purpose we are cancelling after 10 seconds and we are awaiting for 5 seconds to simulate the API call failure. In real world + scenario, you can set the timeout to 30 seconds or 1 minute or you can cancel when user presses cancel button. +

-

- All we need to do now is to initialize a CancellationTokenSource and set CancelAfter() - a timeout. Then, we pass the token to the HTTPClient SendAsync method. - We can then use the token to cancel the request if it takes too long. We can also use the token to cancel the request if the user navigates away. -

+ -

- Note: that for demo purpose we are cancelling after 10 seconds and we are awaiting for 5 seconds to simulate the API call failure. In real world - scenario, you can set the timeout to 30 seconds or 1 minute or you can cancel when user presses cancel button. -

+ +

+ Let's try Cancellation while reading data in this Demo, Click on the Read with Cancellation Button to see the demo on the screen. Note that + data might not be rendered on the screen as the API is cancelled before the data is read. You can verify this from the browser network log. +

+ +
- +
+ Supporting Cancellation in API Calls + Cancelled Requests +
+
- +

- Let's try Cancellation while reading data in this Demo, Click on the Read with Cancellation Button to see the demo on the screen. Note that - data might not be rendered on the screen as the API is cancelled before the data is read. You can verify this from the browser network log. + In this article, we learned about how to free up resources with cancellation while accessing APIs using + HTTP Client in .NET. We learned about what is CancellationTokenSource + and why we should cancel requests when we no longer need them and advantages of + cancellation. We also learned about how to support cancellation while reading data from API. + I hope you enjoyed reading this article.

- - - -
- Supporting Cancellation in API Calls - Cancelled Requests -
- -

Summary

- -

- In this article, we learned about how to free up resources with cancellation while accessing APIs using - HTTP Client in .NET. We learned about what is CancellationTokenSource - and why we should cancel requests when we no longer need them and advantages of - cancellation. We also learned about how to support cancellation while reading data from API. - I hope you enjoyed reading this article. -

+
\ No newline at end of file diff --git a/HTTPClientDemoComponents/Pages/Blogs/UnitTestingHttpClient.razor b/HTTPClientDemoComponents/Pages/Blogs/UnitTestingHttpClient.razor index a98e873b6e..ff43d760f6 100644 --- a/HTTPClientDemoComponents/Pages/Blogs/UnitTestingHttpClient.razor +++ b/HTTPClientDemoComponents/Pages/Blogs/UnitTestingHttpClient.razor @@ -3,115 +3,101 @@ -

What we gonna do?

- -

- In this article, let's learn about how to Unit Test HTTPClient in .NET. -

- -

- Note: If you have not done so already, I recommend you read the article on - Extending HTTPClient with Custom Http Message Handlers in dotnet. -

- -

- There are multiple ways to Unit Test HTTP Client in dotnet. Most of the examples you will find on the internet will be using - Moq or NSubstitute. But I prefer to write - Custom Http Message Handlers to Unit Test HTTP Client in dotnet. -

- - - -

Why we gonna do?

- -

- Integrating with a web API is a common task required by many applications. Http Client is a class that - simplifies the consumption of web APIs. It provides a base class for sending HTTP requests - and receiving HTTP responses from a resource identified by a URI. The - HttpClient class is typically used to send and receive requests from a web service by using the - HTTP protocol. -

- -

- Most of the time I see developers including me say we can test HTTP Client or calls in Integration Test but - Unit testing allows developers to verify the behavior and logic of individual units of code - in isolation quickly. By writing tests, you can ensure that your code functions correctly and remains reliable even after making - changes or adding new features. Unit tests are faster and help catch bugs early in the development process and provide confidence in the correctness - of the code. -

- -

- Note: If you have not done so already, I recommend you read the article on - Implementing TDD in C# .Net. -

- - - -

How we gonna do?

- -

- You're working on a part of your application that relies on HttpClient to make API calls. Testing this can - become cumbersome, as you don't want to actually call the API. Because it's not an integration test. Moreover, - constantly calling a service that's cloud hosted can cost you quite a bit of money. You just want to test one specific piece of functionality that - happens to rely on data being returned from an HTTP call. -

- -

- Take error handling, for example. You want to ensure that when the API responds with a dreaded - 401 Unauthorized status code that your application handles it gracefully. You don't want to actually call the - API, though. You just want to ensure that your application handles the response correctly. This is where Custom Http Message - Handlers come in handy. Well, we can write a custom handler to stop communication with the API and return the response required - for our test. For our use case, we don't want to communicate with the API, but we do want to get back a 401 Unauthorized response. -

- -

- The following code shown a simple implementation of a custom message handler that returns a 401 Unauthorized response. Notice that we are using - HttpMessageHandler instead of DelegatingHandler. This is because we don't - want to pass the request to the next handler in the pipeline. We want to return the response we want. So, we are using HttpMessageHandler to - short circuit it. -

- - - - - -

- Now, we can use this custom message handler to unit test our http client. The following code shows a simple implementation of a unit test for - http client. All we need to do is to pass our custom message handler to the http client and make the http call. - The http call will be intercepted by our custom message handler and will - return the response we want which is 200 Success Status Code in our case. This will help you to assert your - code against the response you want. -

- - - - - -

- Here is another similar example for 401 UnAuthorised Status Code. -

- - - - - - - - - -

- The only drawback of this approach is that you need to write a custom message handler for each status code you want to test. I feel like we will also - need to maintain these custom message handlers. But this is the best approach I found to unit test http client in dotnet when there is no option available - to mock the http client. -

- -

Summary

- -

+ +

+ In this article, let's learn about how to Unit Test HTTPClient in .NET. +

+ +

+ Note: If you have not done so already, I recommend you read the article on + Extending HTTPClient with Custom Http Message Handlers in dotnet. +

+ +

+ There are multiple ways to Unit Test HTTP Client in dotnet. Most of the examples you will find on the internet will be using + Moq or NSubstitute. But I prefer to write + Custom Http Message Handlers to Unit Test HTTP Client in dotnet. +

+ + + +

+ Integrating with a web API is a common task required by many applications. Http Client is a class that + simplifies the consumption of web APIs. It provides a base class for sending HTTP requests + and receiving HTTP responses from a resource identified by a URI. The + HttpClient class is typically used to send and receive requests from a web service by using the + HTTP protocol. +

+ +

+ Most of the time I see developers including me say we can test HTTP Client or calls in Integration Test but + Unit testing allows developers to verify the behavior and logic of individual units of code + in isolation quickly. By writing tests, you can ensure that your code functions correctly and remains reliable even after making + changes or adding new features. Unit tests are faster and help catch bugs early in the development process and provide confidence in the correctness + of the code. +

+ +

+ Note: If you have not done so already, I recommend you read the article on + Implementing TDD in C# .Net. +

+
+ + +

+ You're working on a part of your application that relies on HttpClient to make API calls. Testing this can + become cumbersome, as you don't want to actually call the API. Because it's not an integration test. Moreover, + constantly calling a service that's cloud hosted can cost you quite a bit of money. You just want to test one specific piece of functionality that + happens to rely on data being returned from an HTTP call. +

+ +

+ Take error handling, for example. You want to ensure that when the API responds with a dreaded + 401 Unauthorized status code that your application handles it gracefully. You don't want to actually call the + API, though. You just want to ensure that your application handles the response correctly. This is where Custom Http Message + Handlers come in handy. Well, we can write a custom handler to stop communication with the API and return the response required + for our test. For our use case, we don't want to communicate with the API, but we do want to get back a 401 Unauthorized response. +

+ +

+ The following code shown a simple implementation of a custom message handler that returns a 401 Unauthorized response. Notice that we are using + HttpMessageHandler instead of DelegatingHandler. This is because we don't + want to pass the request to the next handler in the pipeline. We want to return the response we want. So, we are using HttpMessageHandler to + short circuit it. +

+ + + +

+ Now, we can use this custom message handler to unit test our http client. The following code shows a simple implementation of a unit test for + http client. All we need to do is to pass our custom message handler to the http client and make the http call. + The http call will be intercepted by our custom message handler and will + return the response we want which is 200 Success Status Code in our case. This will help you to assert your + code against the response you want. +

+ + + +

+ Here is another similar example for 401 UnAuthorised Status Code. +

+ + + + + +

+ The only drawback of this approach is that you need to write a custom message handler for each status code you want to test. I feel like we will also + need to maintain these custom message handlers. But this is the best approach I found to unit test http client in dotnet when there is no option available + to mock the http client. +

+
+ + In this article, we learned about how to Unit Test HTTP Client in dotnet. We also learned about why we should write unit tests and what is a http client. We also learned about how to write custom http message handlers to unit test http client in dotnet. I hope you enjoyed reading this article. With this I'm concluding this HTTP Client series. Please share this with your network and help other dotnet devs. -

+
\ No newline at end of file diff --git a/WebAPIDemoComponents/Pages/Blogs/HealthChecksInASPNET.razor b/WebAPIDemoComponents/Pages/Blogs/HealthChecksInASPNET.razor index e63d7f4ca2..9ed2e7a2ca 100644 --- a/WebAPIDemoComponents/Pages/Blogs/HealthChecksInASPNET.razor +++ b/WebAPIDemoComponents/Pages/Blogs/HealthChecksInASPNET.razor @@ -3,206 +3,190 @@ -

What we gonna do?

+ +

+ In this article, let's learn about how to implement Health Checks + in Web API in ASP.NET Core. +

+ +

+ I'll introduce you to the features that ASP.NET Core offers for health checks, including how to create, register, and customize them. Lets + discusses ASP.NET Core health checks, including how to configure and add health checks, create a UI to work with health checks, and secure + your health check endpoints. +

+
+ + +

+ Health checks are like how we humans check our health. We go to the doctor for a regular checkup to make sure everything is fine. + Similarly, health checks in ASP.NET Core are used to check the health of the application. It is used to check + the status of the application and its dependencies at regular intervals. +

+ +

+ Health checks serve as endpoints that provide snapshot of application's health. They help to monitor the state of the application and its dependencies + such as database, cache, external services etc. +

+ +

+ With health checks you can easily achieve, +

+ +
    +
  • Proactive Monitoring
  • +
  • Automated Recovery
  • +
  • Improved Reliability
  • +
+ +

+ The app is considered healthy if it can respond at the health endpoint URL. +

+ +

+ Health checks in ASP.NET Core are vital for enterprise and commercial development. You need to understand what's happening on your site in order to + find where problems have occurred so that in case of any failures we can be notified and take necessary actions. +

+
+ + +

Configuring Health Check Services

+ +

+ Configuring health checks involves two main steps in Program.cs file: + +

    +
  1. + Registering Health Check Services. This will setup Health Check Middleware. +
  2. +
  3. + Configuring Health Check Endpoints. This will setup Health Check Endpoints. +
  4. +
+

+ + + +

+ Thats the very simple and minimal configuration. Now when you run you web api and navigate to https://localhost:5001/health, you will see the + health check status as shown below. +

+ +
+ Simple Health Check Response +
+ +

Using IHealthCheck Interface

+ +

+ The above setup looks neat and simple. But how do we know which part of the system is failing when we see a unhealthy status? To identify the + failing part, we need to add health checks for each part of the system. We can add health check to any part + of the system using IHealthCheck interface. +

+ +

+ For example, let's add a custom health check logic to check the health of the system as shown below and register the same in the services. +

+ + + +

+ We can now add health check for any part of the system like database, cache, external services, etc. and register them in the services. But does this + seems like a lot of code? If so then you can use battle tested Health Check Library like + AspNetCore.Diagnostics.HealthChecks. +

+ +

+ This Library provides a lot of built-in health checks for various services like + SQL Server, Redis, Azure Blob Storage, Postgres, MongoDB, AWS S3 etc. + You can also create ui and dashboard for health checks using this library. +

+ +

Adding Health Checks

+ +

+ To add health check to postgres database using above library, you need to install the + package AspNetCore.HealthChecks.Npgsql and configure the same in the services as + shown below. +

+ + + +

+ Now when you run you web api and navigate to https://localhost:5001/health, you will see the health check status as shown below. +

+ +
+ Degraded Health Check Response +
+ +

+ Now that said, you can chain as many as health checks you want and configure them in the services as shown below. +

+ + + +

Creating UI and Dashboard

+ +

+ Having a simple string response doesn't help much. We need a UI to visualize the health check status for multiple parts of the system. + To create a UI and dashboard for health checks we need to install + AspNetCore.HealthChecks.UI package and + install AspNetCore.HealthChecks.UI.Client package as well. +

+ +

+ We need to store the data in a storage to show them in UI. However, for demo purpose we can use + in-memory storage. To configure the same, we need to + install AspNetCore.HealthChecks.UI.InMemory.Storage package and configure the + same in the services as shown below. +

-

- In this article, let's learn about how to implement Health Checks - in Web API in ASP.NET Core. -

+ + +
+ Health UI Response +
-

- I'll introduce you to the features that ASP.NET Core offers for health checks, including how to create, register, and customize them. Lets - discusses ASP.NET Core health checks, including how to configure and add health checks, create a UI to work with health checks, and secure - your health check endpoints. -

+

+ So far so good. But what about Dashboard? Its already added. All you need to do is to navigate to https://localhost:5001/healthchecks-ui and you will + see the dashboard as shown below. +

+ +
+ Health Check Dashboard +
+ +

+ If you are looking for options to customize the UI, you can do so by configuring the same with + custom css shown below. +

- + -

Why we gonna do?

+
+ Health Check Dashboard Custom UI +
-

- Health checks are like how we humans check our health. We go to the doctor for a regular checkup to make sure everything is fine. - Similarly, health checks in ASP.NET Core are used to check the health of the application. It is used to check - the status of the application and its dependencies at regular intervals. -

+

Securing Health Check Endpoints

-

- Health checks serve as endpoints that provide snapshot of application's health. They help to monitor the state of the application and its dependencies - such as database, cache, external services etc. -

+

+ By default, the health check endpoints are not secured. Anyone can access the health check endpoints. + To secure the health check endpoints, you can use RequireHost, RequireCORS + and RequireAuthorization middleware as shown below. +

-

- With health checks you can easily achieve, -

+ -
    -
  • Proactive Monitoring
  • -
  • Automated Recovery
  • -
  • Improved Reliability
  • -
+

+ That's it. You have now secured the health check endpoints. +

+
-

- The app is considered healthy if it can respond at the health endpoint URL. -

- -

- Health checks in ASP.NET Core are vital for enterprise and commercial development. You need to understand what's happening on your site in order to - find where problems have occurred so that in case of any failures we can be notified and take necessary actions. -

- - - -

How we gonna do?

- -

Configuring Health Check Services

- -

- Configuring health checks involves two main steps in Program.cs file: - -

    -
  1. - Registering Health Check Services. This will setup Health Check Middleware. -
  2. -
  3. - Configuring Health Check Endpoints. This will setup Health Check Endpoints. -
  4. -
-

- - - -

- Thats the very simple and minimal configuration. Now when you run you web api and navigate to https://localhost:5001/health, you will see the - health check status as shown below. -

- -
- Simple Health Check Response -
- - - -

Using IHealthCheck Interface

- -

- The above setup looks neat and simple. But how do we know which part of the system is failing when we see a unhealthy status? To identify the - failing part, we need to add health checks for each part of the system. We can add health check to any part - of the system using IHealthCheck interface. -

- -

- For example, let's add a custom health check logic to check the health of the system as shown below and register the same in the services. -

- - - -

- We can now add health check for any part of the system like database, cache, external services, etc. and register them in the services. But does this - seems like a lot of code? If so then you can use battle tested Health Check Library like - AspNetCore.Diagnostics.HealthChecks. -

- -

- This Library provides a lot of built-in health checks for various services like - SQL Server, Redis, Azure Blob Storage, Postgres, MongoDB, AWS S3 etc. - You can also create ui and dashboard for health checks using this library. -

- - - -

Adding Health Checks

- -

- To add health check to postgres database using above library, you need to install the - package AspNetCore.HealthChecks.Npgsql and configure the same in the services as - shown below. -

- - - -

- Now when you run you web api and navigate to https://localhost:5001/health, you will see the health check status as shown below. -

- -
- Degraded Health Check Response -
- -

- Now that said, you can chain as many as health checks you want and configure them in the services as shown below. -

- - - - - -

Creating UI and Dashboard

- -

- Having a simple string response doesn't help much. We need a UI to visualize the health check status for multiple parts of the system. - To create a UI and dashboard for health checks we need to install - AspNetCore.HealthChecks.UI package and - install AspNetCore.HealthChecks.UI.Client package as well. -

- -

- We need to store the data in a storage to show them in UI. However, for demo purpose we can use - in-memory storage. To configure the same, we need to - install AspNetCore.HealthChecks.UI.InMemory.Storage package and configure the - same in the services as shown below. -

- - - -
- Health UI Response -
- -

- So far so good. But what about Dashboard? Its already added. All you need to do is to navigate to https://localhost:5001/healthchecks-ui and you will - see the dashboard as shown below. -

- -
- Health Check Dashboard -
- -

- If you are looking for options to customize the UI, you can do so by configuring the same with - custom css shown below. -

- - - -
- Health Check Dashboard Custom UI -
- - - -

Securing Health Check Endpoints

- -

- By default, the health check endpoints are not secured. Anyone can access the health check endpoints. - To secure the health check endpoints, you can use RequireHost, RequireCORS - and RequireAuthorization middleware as shown below. -

- - - -

- That's it. You have now secured the health check endpoints. -

- - - -

Summary

- -

+

In this we learnt about what is health check and why it is important. We also learnt how to configure health checks in ASP.NET Core Web API. We also learnt how to add custom health checks using IHealthCheck and use library to add health checks for various services. We also learnt how to create UI and dashboard for health checks and how to customise the UI and secure the health check endpoints. Now you are ready to implement health checks in your ASP.NET Core Web API. -

+
\ No newline at end of file diff --git a/WebAPIDemoComponents/Pages/Blogs/UnitTestingHostedServicesInASPNET.razor b/WebAPIDemoComponents/Pages/Blogs/UnitTestingHostedServicesInASPNET.razor index ea57a7fe19..49b7c789cc 100644 --- a/WebAPIDemoComponents/Pages/Blogs/UnitTestingHostedServicesInASPNET.razor +++ b/WebAPIDemoComponents/Pages/Blogs/UnitTestingHostedServicesInASPNET.razor @@ -3,165 +3,165 @@ -

What we gonna do?

- -

- In this article, let's learn about how to unit test Hosted Services in WebAPI in ASP.NET Core. -

- -

- In ASP.NET Core, hosted services plays a vital role in simplifying background jobs which needs to run periodically - to perform operations. Most common use cases include: -

- -
    -
  • Processing uploaded excel in background
  • -
  • Sending emails in background
  • -
  • Performing data migration
  • -
  • Syncing data between two data sources
  • -
  • Other long running operations, etc
  • -
- -

- To know more about Hosted Service or Background Service is outside the scope - of this article. I'll write a separate article on Background Services in ASP.NET Core. For now lets understand walkthrough how to use Hosted Service. -

- -

Why we gonna do?

- -

- When writing software, we want to ensure that the code is covered by tests, which verify the required behavior and catch any regressions. - Unit testing is a crucial practice in software development as it helps identify issues early in the development - process. When it comes to service registration, unit testing offers the following benefits: -

- -
    -
  • Validation: Unit tests verify that the necessary services are registered correctly, avoiding runtime errors caused by missing or misconfigured dependencies.
  • -
  • Refactoring: Unit tests provide a safety net when refactoring code by ensuring that service registration remains intact during code changes.
  • -
  • Documentation: Well-written unit tests serve as living documentation, illustrating how services should be registered and ensuring consistency across the application.
  • -
- -

- Note: If you have not done so already, I recommend you read the article on - Implementing TDD in C# .Net. -

- -

How we gonna do?

- -

- We are going to write unit tests for the Data Migration Hosted Service which we used in our previous article on - Perform Background Workloads in Hosted Service using Channels in ASP.NET Web API. - Here is the quick reference of the hosted service used in that article. -

- - - -

- To unit test the DataMigrationService Hosted Service, follow these steps: -

- -
    -
  1. - Create a new test class, let's call it HostedServiceTests, and add a test method - using the [Fact] attribute. -
  2. -
  3. - In the test method, instantiate a DataMigrationChannel which we used in previous article and - ServiceCollection from the - Microsoft.Extensions.DependencyInjection - namespace. This collection will act as the container for our services. -
  4. -
  5. - Use Moq to Mock the IUnitOfWork and add it to the - ServiceCollection and call BuildServiceProvider() to build the - ServiceProvider instance. -
  6. -
  7. - Finally let's use NullLogger<DataMigrationService>.Instance from - Microsoft.Extensions.Logging.Abstractions - namespace instead of Mocking it as we are not going to test the logger. Moreover mocking Logger is a - complex step. -
  8. -
  9. - Next Call the MigrateData method in the DataMigrationChannel object - to add message to the channel. -
  10. -
  11. - Then, instantiate the DataMigrationService class with the above instantiated parameters and call the - StartAsync method with default CancellationToken to start the service. -
  12. -
  13. - Now call ExecuteTask from the DataMigrationService class to - execute the task. This will make the ExecuteAsync of actual background service to run. -
  14. -
  15. - Perform assertions using the IsCompletedSuccessfully result on the - ExecuteTask of DataMigrationService. Check for its success. -
  16. -
  17. Additionally, verify IUnitOfWork using Moq Verify methods.
  18. -
- - - -

- Here is an another examples of background service using TimeProvider which uses timer to Sync data attribute regular interval. - Let's see how to unit test this service. -

- - - -

- To unit test the DataSyncService Hosted Service, follow these steps: -

- -
    -
  1. - Create a new test class, let's call it HostedServiceTests, and add a test method - using the [Fact] attribute. -
  2. -
  3. - In the test method, instantiate a FakeTimeProvider To adjust time and test. This is available from - Microsoft.Extensions.TimeProvider.Testing namespace. -
  4. -
  5. - Finally let's use FakeLogger<DataSyncService> from - Microsoft.Extensions.Diagnostics.Testing - namespace instead of Mocking it as we are going to test the logger. Moreover mocking Logger is a - complex step. -
  6. -
  7. - Then, instantiate the DataSyncService class with the above instantiated parameters and call the - StartAsync method with default CancellationToken to start the service. -
  8. -
  9. - Now call ExecuteTask from the DataSyncService class to - execute the task. This will make the ExecuteAsync of actual background service to run. -
  10. -
  11. - Now adjust the time using by calling Advance from FakeTimeProvider. - This will execute the SyncData callback passed to the periodic timer in the - DataSyncService Background Service. -
  12. -
  13. - Perform assertions using the IsCompletedSuccessfully result on the - ExecuteTask of DataSyncService. Check for its success. -
  14. -
  15. Additionally, make assertions as per your needs.
  16. -
- - - -

- By executing above test we can validate background services in ASP.NET Core apps. The same can be used to validate worker services in dotnet. -

- -

Summary

- -

- Unit testing hosted services in ASP.NET Core is a crucial step to ensure that they are working as expected. By writing unit tests, you can - validate behavior, identify issues early on, and maintain a reliable and robust application. The examples and - techniques covered in this article provide a solid foundation for performing unit tests on hosted services, promoting software quality and - maintainability in ASP.NET Core applications. -

+ +

+ In this article, let's learn about how to unit test Hosted Services in WebAPI in ASP.NET Core. +

+ +

+ In ASP.NET Core, hosted services plays a vital role in simplifying background jobs which needs to run periodically + to perform operations. Most common use cases include: +

+ +
    +
  • Processing uploaded excel in background
  • +
  • Sending emails in background
  • +
  • Performing data migration
  • +
  • Syncing data between two data sources
  • +
  • Other long running operations, etc
  • +
+ +

+ To know more about Hosted Service or Background Service is outside the scope + of this article. I'll write a separate article on Background Services in ASP.NET Core. For now lets understand walkthrough how to use Hosted Service. +

+
+ + +

+ When writing software, we want to ensure that the code is covered by tests, which verify the required behavior and catch any regressions. + Unit testing is a crucial practice in software development as it helps identify issues early in the development + process. When it comes to service registration, unit testing offers the following benefits: +

+ +
    +
  • Validation: Unit tests verify that the necessary services are registered correctly, avoiding runtime errors caused by missing or misconfigured dependencies.
  • +
  • Refactoring: Unit tests provide a safety net when refactoring code by ensuring that service registration remains intact during code changes.
  • +
  • Documentation: Well-written unit tests serve as living documentation, illustrating how services should be registered and ensuring consistency across the application.
  • +
+ +

+ Note: If you have not done so already, I recommend you read the article on + Implementing TDD in C# .Net. +

+
+ + +

+ We are going to write unit tests for the Data Migration Hosted Service which we used in our previous article on + Perform Background Workloads in Hosted Service using Channels in ASP.NET Web API. + Here is the quick reference of the hosted service used in that article. +

+ + + +

+ To unit test the DataMigrationService Hosted Service, follow these steps: +

+ +
    +
  1. + Create a new test class, let's call it HostedServiceTests, and add a test method + using the [Fact] attribute. +
  2. +
  3. + In the test method, instantiate a DataMigrationChannel which we used in previous article and + ServiceCollection from the + Microsoft.Extensions.DependencyInjection + namespace. This collection will act as the container for our services. +
  4. +
  5. + Use Moq to Mock the IUnitOfWork and add it to the + ServiceCollection and call BuildServiceProvider() to build the + ServiceProvider instance. +
  6. +
  7. + Finally let's use NullLogger<DataMigrationService>.Instance from + Microsoft.Extensions.Logging.Abstractions + namespace instead of Mocking it as we are not going to test the logger. Moreover mocking Logger is a + complex step. +
  8. +
  9. + Next Call the MigrateData method in the DataMigrationChannel object + to add message to the channel. +
  10. +
  11. + Then, instantiate the DataMigrationService class with the above instantiated parameters and call the + StartAsync method with default CancellationToken to start the service. +
  12. +
  13. + Now call ExecuteTask from the DataMigrationService class to + execute the task. This will make the ExecuteAsync of actual background service to run. +
  14. +
  15. + Perform assertions using the IsCompletedSuccessfully result on the + ExecuteTask of DataMigrationService. Check for its success. +
  16. +
  17. Additionally, verify IUnitOfWork using Moq Verify methods.
  18. +
+ + + +

+ Here is an another examples of background service using TimeProvider which uses timer to Sync data attribute regular interval. + Let's see how to unit test this service. +

+ + + +

+ To unit test the DataSyncService Hosted Service, follow these steps: +

+ +
    +
  1. + Create a new test class, let's call it HostedServiceTests, and add a test method + using the [Fact] attribute. +
  2. +
  3. + In the test method, instantiate a FakeTimeProvider To adjust time and test. This is available from + Microsoft.Extensions.TimeProvider.Testing namespace. +
  4. +
  5. + Finally let's use FakeLogger<DataSyncService> from + Microsoft.Extensions.Diagnostics.Testing + namespace instead of Mocking it as we are going to test the logger. Moreover mocking Logger is a + complex step. +
  6. +
  7. + Then, instantiate the DataSyncService class with the above instantiated parameters and call the + StartAsync method with default CancellationToken to start the service. +
  8. +
  9. + Now call ExecuteTask from the DataSyncService class to + execute the task. This will make the ExecuteAsync of actual background service to run. +
  10. +
  11. + Now adjust the time using by calling Advance from FakeTimeProvider. + This will execute the SyncData callback passed to the periodic timer in the + DataSyncService Background Service. +
  12. +
  13. + Perform assertions using the IsCompletedSuccessfully result on the + ExecuteTask of DataSyncService. Check for its success. +
  14. +
  15. Additionally, make assertions as per your needs.
  16. +
+ + + +

+ By executing above test we can validate background services in ASP.NET Core apps. The same can be used to validate worker services in dotnet. +

+
+ + +

+ Unit testing hosted services in ASP.NET Core is a crucial step to ensure that they are working as expected. By writing unit tests, you can + validate behavior, identify issues early on, and maintain a reliable and robust application. The examples and + techniques covered in this article provide a solid foundation for performing unit tests on hosted services, promoting software quality and + maintainability in ASP.NET Core applications. +

+
\ No newline at end of file