Posts

Showing posts from December, 2025

Debugging

Image
  Debugging Blazor Server Right-click on MyBlogServerSide and click Set As Startup project. Press F5 to start the project. Using the web browser, navigate to https://localhost:5001/ throwexception (the port number may vary). Press F12 to show the web browser developer tools. In the developer tools, click Console. Click the Throw exception button on our page. Press F5 to continue and switch back to the web browser. We should now be able to see the exception message in the developer tools. Now let's try a breakpoint: In Visual Studio, open  MyBlog.Shared/Pages/Index.razor. Anywhere in the LoadPosts method, set a breakpoint by clicking the leftmost border (making a red dot appear). We can also add a breakpoint by pressing F9. Go back to the web browser and navigate to https://localhost:5001/ (the port number may vary). Visual Studio should now trigger the breakpoint, and by hovering over the variables, we should be able to observe their current values. Debugging Blaz...

Managing State (Part 4)

Image
  Using An In-Memory State Container Service In the context of in-memory state containers, we utilize dependency injection to maintain the service instance in memory for a specified duration (scoped, singleton, transient). To show how in-memory state works, we will have to implement it a bit differently depending on hosting. Implementing Real-Time Updates On Blazor Server In the MyBlog.Shared project, select the Interfaces folder and press Shift + F2 . Name the file IBlogNotificationService.cs. In the MyBlogServerSide project, select the Services folder and press Shift+ F2 . Name the file BlazorServerBlogNotificationService.cs . It might seem unnecessary to give the class a name that includes BlazorServer , but it makes sure we can easily tell the classes apart. In Startup.cs at the end of ConfigureServices, add the dependency injection- Services.AddSingleton<IBlogNotificationService, BlazorServerBlogNottificationService> (); We add this dependency injection as a S...

Managing State (Part 3)

Image
  Implementing WebAssembly We will use Blazored.SessionStorage for Blazor WebAssembly: Right-click on the Dependencies node under the MyBlogWebAssembly.Client project and select Manage Nuget Package. Search for Blazored.SessionStorage and click Install. Right-click on the MyBlogWebAssembly.Client project and select Add|New Folder. Name the folder Services. Select the new folder and press Shift+ F2 . Name the file MyBlogBrowserStorage.cs. Open the new file and replace the content with code. In the Program.cs file, add the following namespaces- using Blazored.SessionStorage; using MyBlog.Shared.Interfaces; using MyBlogWebAssembly.Client.Services; Add code just above await builder.Build().RunAsync();  Then we add our configuration for IBrowserStorage, but in this case, we return MyBlogBrowserStorage when we ask the dependency injection for IBrowserStorage. Implementing the shared We also need to implement some code that calls the services we just created: In the MyB...

Managing State (Part 2)

Image
  Implementing Browser Storage The web browser offers various methods for storing data, each with different handling based on the type utilized. Local storage is limited to the specific browser window being used by the individual. Even if the user refreshes the page or exits the web browser entirely, the data will remain intact. The information is also accessible across different tabs. Session storage is limited to the specific browser tab. If you refresh the tab, the data remains, but closing the tab will result in loss of the data. SessionsStorage can be considered safer because it minimizes the potential issues that could arise from multiple tabs altering the same stored values. To be able to access the browser storage, we need to use JavaScript. In .NET 5, Microsoft rolled out Protected browser storage , leveraging data protection features in ASP.NET Core, although it is not accessible in WebAssembly. Nevertheless, we can utilize an open source library named Blazored.LocalSt...

Managing State (Part 1)

Image
  Storing Data On Server Side There are numerous methods available for storing data on the server. It's important to keep in mind that Blazor WebAssembly will always require an API. In contrast, Blazor Server can access server-side resources directly without needing an API. If you're developing a Blazor Server application and don't want to switch to Blazor WebAssembly, you should choose direct access. We can initially utilize direct server access and transition to an API later if we choose to. In terms of data storage options, we have the ability to store data in Blob storage, key-value storage, a relational database, or table storage. The options are virtually limitless. As long as .NET can interact with the technology, we can implement it. Storing Data In URL Data, in this case, could refer to the ID of the blog post or the specific page number when pagination is being utilized. To read a parameter from the URL, we can use the following syntax- @page "/post...

JavaScript Interop (Part 2)

Image
  JavaScript To .NET There are three ways of doing a callback from JavaScript to .NET code: • Static .NET method call • Instance method call • Component instance method call Static .NET Method Call To invoke a .NET function using JavaScript, we should declare the function as static and apply the JSInvokable attribute to the method. Instance Method Call This method is a little bit tricky. We need to pass an instance of the .NET object to be able to call it. First, we need a class that will handle the method call. This class accepts a string (a name) as an argument in its constructor, along with a method named SayHello that produces a string comprising “Hello,” followed by the name provided during the instance creation. We should start by creating an instance of that class, providing it with a name, and generating a DotNetObjectReference<T> to enable JavaScript to interact with the instance. However, we first need the JavaScript code that can invoke the .NET method. There a...

JavaScript Interop (Part 1)

Image
  Why Do We Need JavaScript? Blazor requires JavaScript to function. Certain events are only activated in JavaScript, and to utilize these events, we must implement an interop. A couple of libraries that depend on JavaScript to function are named Blazm.Components and Blazm.Bluetooth . The first component is a grid that leverages JavaScript interop to initiate C# code (JavaScript to .NET) when the window is resized, eliminating columns if all cannot fit within the window. When this occurs, the C# code invokes JavaScript to obtain the dimensions of the columns based on the client width, a detail known only to the web browser, and removes columns as necessary based on that information. The second component, Blazm.Bluetooth , allows for interaction with Bluetooth devices using Web Bluetooth, a web standard accessible via JavaScript. It uses two-way communication. Bluetooth events can trigger C# code that can iterate over devices and send data to them. They are both open-source. .NET T...

Sharing Code and Resources (Part 5)

Image
  Making The Blog Look Like A Blog In the MyBlog.Shared project, open the Pages/index.razor file. We no longer need fake blog posts, so let's remove the button from the top of the page, as well as the <br /> tag. Remove the AddSomePosts method. Now, when we have an admin, we can create our posts. Inside the Virtualize component, change the content (RenderFragment). Also remove the <ul> tag. Add a using statement for Markdig at the top of the file- @using Markdig; Add an OnInitializedAsync method that will handle the instantiation of the Markdig pipeline. Now, run the project using Ctrl + F5 and take a look at our new front page. Sharing Problems In the MyBlog.Shared project, open Pages/Admin/BlogPostEdit.razor . Always perform null checks. Add a null check around the category loop. Add a null check around the tag loop. Note- It's good to keep in mind to always check for nulls, but sometimes these things sneak past us. When sharing code, it is always goo...

Sharing Code and Resources (Part 4)

Image
  Adding CSS To MyBlogServerSide Open Pages/_Host.cshtml .   Remove these rows- <link rel = “stylesheet” href = “css/bootstrap/bootstrap.min.css” /> <link href = “css/site.css” rel = “stylesheet” /> Add a reference to the new stylesheet (containing both Bootstrap and the BootSwatch Darkly theme)- <link rel = “stylesheet” href = “_content/MyBlog.Shared/MyBlogStyle.min.css” /> Open App.Razor and, in the router component, add the following as an additional property- AdditionalAssemblies="new[] { typeof(MyBlog.Shared.Pages. Index).Assembly}" In _Imports.Razor , add the following namespaces- @using MyBlog.Shared @using MyBlog.Shared.Shared Set MyBlogServerSide as the start-up project and run the project by pressing Ctrl + F5 . Adding CSS To MyBlogWebAssembly.Client In the MyBlogWebAssembly.Client project, open wwwroot/index.html : Remove the following lines- <link href = “css/bootstrap/bootstrap.min.css” rel = “stylesh...

Sharing Code and Resources (Part 3)

Image
  Adding Static Files Blazor has the capability to utilize static files like images, CSS, and JavaScript. By placing our files in the wwwroot folder, they will be automatically available online and reachable from the main directory of our website. One advantage of Blazor is that we can also accomplish this with a library, making it incredibly simple to share static files through a library. Blazor ultimately relies on HTML, which can be styled with CSS. As noted earlier, the default Blazor templates utilize Bootstrap, and we will also stick with that. You can find a fantastic website featuring user-friendly Bootstrap themes that are available for download at https://bootswatch.com/ . CSS versus LESS versus SASS CSS represents Cascading Style Sheets, which allows you to apply styles to the appearance of your website. LESS denotes Leaner Style Sheets and builds upon CSS. SASS, or Syntactically Awesome Style Sheets, functions similarly to LESS. SASS requires less coding and is simpler...

Sharing Code and Resources (Part 2)

Image
  Cleaning Up The Shared Files Let's make sure the moved files have matching namespaces: In the MyBlog.Shared project, change the namespace to MyBlog.Shared . Components on the following files- Components/BootstrapFieldCssClassProvider.cs Components/ CustomCssClassProvider.cs Remove @using MyBlogServerSide.Components from the following files- Pages/Admin/BlogPostEdit.razor Pages/Admin/BlogPostList.razor Pages/Admin/CategoryList.razor Pages/Admin/TagList.razor In the MyBlog.Shared project, add the following namespaces to the _Imports.razor file - @using MyBlog.Shared @using MyBlog.Shared.Components We have cleaned up a couple of new projects. Adding The API Perform the following steps: In the MyBlogWebAssembly.Client project, open Program.cs and add the following- builder.Services.AddScoped <IMyBlogApi>; MyBlogApiClientSide >(); Add the following namespaces at the top of the file- using MyBlog.Data; using MyBlog.Data.Interfaces; Delete the Pages/Index.razor file (sin...