Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Web Development with Blazor

You're reading from   Web Development with Blazor A practical guide to building interactive UIs with C# 12 and .NET 8

Arrow left icon
Product type Paperback
Published in Apr 2024
Publisher Packt
ISBN-13 9781835465912
Length 366 pages
Edition 3rd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Jimmy Engström Jimmy Engström
Author Profile Icon Jimmy Engström
Jimmy Engström
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Preface 1. Hello Blazor FREE CHAPTER 2. Creating Your First Blazor App 3. Managing State – Part 1 4. Understanding Basic Blazor Components 5. Creating Advanced Blazor Components 6. Building Forms with Validation 7. Creating an API 8. Authentication and Authorization 9. Sharing Code and Resources 10. JavaScript Interop 11. Managing State – Part 2 12. Debugging the Code 13. Testing 14. Deploying to Production 15. Moving from, or Combining with, an Existing Site 16. Going Deeper into WebAssembly 17. Examining Source Generators 18. Visiting .NET MAUI 19. Where to Go from Here 20. Other Books You May Enjoy
21. Index

Creating the client

To access the API, we need to create a client. There are many ways of doing this, but we will do it in the simplest way possible by writing the code ourselves.

The client will implement the same IBlogApi interface. This way, we have the same code regardless of which implementation we are using, and direct JSON access with BlogApiJsonDirectAccess or BlogApiWebClient, which we are going to create next:

  1. Right-click on the Dependencies node under BlazorWebApp.Client and select Manage NuGet Packages.
  2. Search for Microsoft.AspNetCore.Components.WebAssembly.Authentication and click Install.
  3. Also, search for Microsoft.Extensions.Http and click Install.
  4. In the BlazorWebApp.Client project, in the root of the project, add a new class and name it BlogApiWebClient.cs.
  5. Open the newly created file and add the following namespaces:
    using Data.Models;
    using Data.Models.Interfaces;
    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    using System.Net.Http.Json;
    using System.Text.Json;
    
  6. Add IBlogApi to the class and make it public like this:
    namespace BlazorWebApp.Client;
    public class BlogApiWebClient : IBlogApi
    {
    }
    
  7. Some API calls will be public (do not require authentication), but HttpClient will be configured to require a token.

    The handling of tokens is handled automatically by Blazor, so we only need one client, and, in this case, we call it Api.

    To be able to call the API, we need to inject HttpClient. Add the following code to the class:

        private readonly IHttpClientFactory _factory;
        public BlogApiWebClient(IHttpClientFactory factory)
        {
            _factory = factory;
        }
    
  1. Now, it’s time to implement calls to the API. Let’s begin with the Get calls for blog posts. Add the following code:
    public async Task<BlogPost?> GetBlogPostAsync(string id)
        {
            var httpclient = _factory.CreateClient("Api");
            return await httpclient.GetFromJsonAsync<BlogPost>($"api/BlogPosts/{id}");
        }
        public async Task<int> GetBlogPostCountAsync()
        {
            var httpclient = _factory.CreateClient("Api");
            return await httpclient.GetFromJsonAsync<int>("/api/BlogPostCount");
        }
        public async Task<List<BlogPost>?> GetBlogPostsAsync(int numberofposts, int startindex)
        {
            var httpclient = _factory.CreateClient("Api");
            return await httpclient.GetFromJsonAsync<List<BlogPost>>($"/api/BlogPosts?numberofposts={numberofposts}&startindex={startindex}");
        }
    

    We use the HttpClient we injected and then call GetFromJsonAsync, which will automatically download the JSON and convert it into the class we supply to the generic method.

    Now, it gets a little trickier: we need to handle authentication. Luckily, this is built into HttpClient so we only need to handle AccessTokenNotAvailableException. If a token is missing, it will automatically try and renew it, but if there is a problem (for example, the user is not logged in), we can redirect to the login page.

    We will come back to tokens and how authentication works in Chapter 8, Authentication and Authorization.

  1. Next, we add the API calls that need authentication, such as saving or deleting a blog post.

    Add the following code under the code we just added:

    public async Task<BlogPost?> SaveBlogPostAsync(BlogPost item)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            var response = await httpclient.PutAsJsonAsync<BlogPost>
               ("api/BlogPosts", item);
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<BlogPost>(json);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        return null;
    }
    public async Task DeleteBlogPostAsync(string id)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            await httpclient.DeleteAsync($"api/BlogPosts/{id}");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
    

    If the call throws AccessTokenNotAvailableException, that means HttpClient couldn’t get or renew a token automatically, and the user needs to log in.

    This state should probably never happen because we will ensure that when the user navigates to that page, they will need to be logged in, but it’s better to be safe than sorry.

  1. Now, we need to do the same for Categories. Add the following code to the BlogApiWebClient class:
    public async Task<List<Category>?> GetCategoriesAsync()
    {
        var httpclient = _factory.CreateClient("Api");
        return await httpclient.GetFromJsonAsync<List<Category>>($"api/Categories");
    }
    public async Task<Category?> GetCategoryAsync(string id)
    {
        var httpclient = _factory.CreateClient("Api");
        return await httpclient.GetFromJsonAsync<Category>($"api/Categories/{id}");
    }
    public async Task DeleteCategoryAsync(string id)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            await httpclient.DeleteAsync($"api/Categories/{id}");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
    public async Task<Category?> SaveCategoryAsync(Category item)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            var response = await httpclient.PutAsJsonAsync<Category>("api/Categories", item);
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<Category>(json);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        return null;
    }
    
  2. Next up, we will do the same for Tags. Add the following code just under the code we just added:
    public async Task<Tag?> GetTagAsync(string id)
    {
        var httpclient = _factory.CreateClient("Api");
        return await httpclient.GetFromJsonAsync<Tag>($"api/Tags/{id}");
    }
    public async Task<List<Tag>?> GetTagsAsync()
    {
        var httpclient = _factory.CreateClient("Api");
        return await httpclient.GetFromJsonAsync<List<Tag>>($"api/Tags");
    }
    public async Task DeleteTagAsync(string id)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            await httpclient.DeleteAsync($"api/Tags/{id}");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
    public async Task<Tag?> SaveTagAsync(Tag item)
    {
        try
        {
            var httpclient = _factory.CreateClient("Api");
            var response = await httpclient.PutAsJsonAsync<Tag>("api/Tags", item);
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<Tag>(json);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        return null;
    }
    
  3. Let’s not forget about our comments! Add the following code just under the code we just added:
    public async Task<List<Comment>> GetCommentsAsync(string blogpostid)
        {
            var httpclient = _factory.CreateClient("Api");
            return await httpclient.GetFromJsonAsync<List<Comment>>($"api/Comments/{blogpostid}");
        }
        
        public async Task DeleteCommentAsync(string id)
        {
            try
            {
                var httpclient = _factory.CreateClient("Api");
                await httpclient.DeleteAsync($"api/Comments/{id}");
            }
            catch (AccessTokenNotAvailableException exception)
            {
                exception.Redirect();
            }
        }
        public async Task<Comment?> SaveCommentAsync(Comment item)
        {
            try
            {
                var httpclient = _factory.CreateClient("Api");
                var response = await httpclient.PutAsJsonAsync<Comment>("api/Comments", item);
                var json = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<Comment>(json);
            }
            catch (AccessTokenNotAvailableException exception)
            {
                exception.Redirect();
            }
            return null;
        }
    

Great job! Our API client is now done!

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image