Over the weekend I started playing around with ASP.NET Core 3 and Blazor (Server-side). My idea is to create a simple books app, similar to Goodreads.
The one and only purpose of this app is going to be to make myself aware of Blazor and how it works – so the code will be spaghetti as hell, as I am only striving to make things appear on the screen :).
I got inspired by Scott Hanselman and Leslie Richardson’s ASP.NET Core 101 presentation in which they’ve created this app, called Contoso Crafts.
If you haven’t watched it I suggest you do, as it is very informative and fun way to familiarize yourself with ASP.NET Core world.
Just to get my feet wet and to save time creating a real database I started with a simple json file I found on Github. This was my database.
I wanted to see how easy it is to get the data from the file, deserialize it and show it up on the screen. Well, it was easy as cake!
The code and the technique below is pretty much the same as the one in the presentation.
1. Created a Book Model (inside Models folder)
namespace Bookio.SPA.Models
{
public class Book
{
public string Title { get; set; }
public string Isbn { get; set; }
public int PageCount { get; set; }
public PublishedDate PublishedDate { get; set; }
public string ThumbnailUrl { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public string Status { get; set; }
public List<string> Authors { get; set; }
public List<object> Categories { get; set; }
}
public class PublishedDate
{
public DateTime Date { get; set; }
}
}
2. Created a BookService service (inside Services folder)
namespace Bookio.SPA.Services
{
public class BookService
{
private IWebHostEnvironment _webHostEnvironment;
private string JsonBooksFilePath
{
get { return Path.Combine(_webHostEnvironment.ContentRootPath, "Data", "books.json"); }
}
public BookService(IWebHostEnvironment webHostEnvironment)
{
_webHostEnvironment = webHostEnvironment;
}
public IEnumerable<Book> GetAllBooks()
{
using (var jsonFileReader = File.OpenText(JsonBooksFilePath))
{
return JsonSerializer.Deserialize<Book[]>(jsonFileReader.ReadToEnd(), new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
}
}
}
2. Added the service to Startup.cs
services.AddTransient<BookService>();
3. Created a Books.razor file
@page "/books"
@using Bookio.SPA.Services
@using Bookio.SPA.Models
@inject BookService BookService
<h3>Books</h3>
@foreach (var book in booksList)
{
<p>@book.Title</p>
}
@code {
List<Book> booksList;
protected override void OnInitialized()
{
booksList = BookService.GetAllBooks().ToList();
}
}
Here I declared the route with @page directive (so, localhost:port/books would serve this razor page). The @using directives are serving similar purpose to the using statement we all know. @inject directive injects the service we’ve created so that we could use it.
OnInitialized() is a lifecycle method that gets called as soon as the component receives its initial parameters from its parent in the render tree. There we ask our service to give us all books and store it in a booksList object.
Then we just iterate through the object and print the titles for each book.
@foreach (var book in booksList)
{
<p>@book.Title</p>
}
It really is that simple.
The @ as well as the @code { } part is just a razor syntax that helps us combine HTML and C#.
All that was fun and all, but I wanted to see Blazor in action so I exchanged the json file for a real database with Books, Authors and Categories. I’ve added ratings and a simple search feature. I am planning to add comments, shopping cart and what not in the future as I continue exploring.
For now, however, this is what it looks like.
To be continued…
Thanks and happy coding!
I have built the crafts and modified it to my liking. I am researching how to add a search box like you describe. Do you have any more detail on that?
Greg, Take a look at the Contoso University Razor Pages with Entity Framework Core in ASP.NET Core tutorial. They have a search box.
I also worked through Leslie Richardson and Scott Hanselman’s Contoso Crafts very helpful exercise and came across your example while trying to implement Chris Sainty’s elegant Blazored.Modal as an alternative to the JS dependent modal in Contoso Crafts.
You helped me join a few dots.
Thanks for that.