
Posted on • Edited on • Originally published atunitcoding.com
Create a Pokedex app with Blazor and C#
This is a repost from my origin article published on my blog:Unit Coding go and check it out! ✨
Creating web applications that consume rest api's are a great starting point to get better at any programming language at the same time that you are building something that is both useful and fun.
Today we will build the famous pokemon "pokedex" using c# as our programming language and Blazor as the web framework and we will be using .net 7 for this project you can use any other version that you want bus some things on the project structure and some declarations will change, so having said this let's beding coding!
Create the application
Create new empty blazor wasm projectdotnet new blazorwasm-empty -o BlazorDex
(You can use the default version of blazor wasm you will only have to deal with the boilerplate code that microsoft provides on any new project).
We will be using the Pokemon API at PokéAPI (pokeapi.co) on the home page there is a "Try it now" section that allows you to try the api to figure out how it works. One simple example is calling the urlhttps://pokeapi.co/api/v2/pokemon/pikachu and you will get a huge json response that contains the data from "Pikachu".
From there we need to convert the json response that we get from the api when we search for a pokemon to C# classes so we can use them on our application. For you can go to a web page like Convert JSON to C# Classes Online - Json2CSharp Toolkit or you can use plugins that parse the json to classes on pasting or if you are using visual studio there is a built in tool to paste any json as C# classes so feel free to use any of this.
Create the pokemon models
From the conversion from json to C# classes we need the "root" class which we will rename to "pokemon" and remove some properties that we will not use, also we need classes like type, stats and sprites. So you should have theese c# classes in a folder called Models in the root of your project.
publicclassPokemon{publicintid{get;set;}=0;publicstringname{get;set;}="";publicintweight{get;set;}=0;publicintheight{get;set;}=0;publicSpritessprites{get;set;}=newSprites();publicList<Stat>stats{get;set;}=newList<Stat>();publicList<Type>types{get;set;}=newList<Type>();}publicclassSprites{publicstringback_default{get;set;}publicobjectback_female{get;set;}publicstringback_shiny{get;set;}publicobjectback_shiny_female{get;set;}publicstringfront_default{get;set;}publicobjectfront_female{get;set;}publicstringfront_shiny{get;set;}publicobjectfront_shiny_female{get;set;}}publicclassStat{publicintbase_stat{get;set;}publicinteffort{get;set;}publicStat2stat{get;set;}}publicclassStat2{publicstringname{get;set;}publicstringurl{get;set;}}publicclassType{publicintslot{get;set;}publicType2type{get;set;}}publicclassType2{publicstringname{get;set;}publicstringurl{get;set;}}
Create the Http client to fetch the pokemon data from the api
Now create a new folder called Util as short for utilites in the root of our project and create the http client called PokeClient with the following code.
usingSystem.Text.Json;usingBlazorDex.Models;namespaceBlazorDex.Properties{publicclassPokeClient{privateHttpClientClient{get;}publicPokeClient(HttpClientclient){this.Client=client;}publicasyncTask<Pokemon>GetPokemon(stringid){varresponse=awaitthis.Client.GetAsync($"<https://pokeapi.co/api/v2/pokemon/{id}/>");varcontent=awaitresponse.Content.ReadAsStringAsync();returnJsonSerializer.Deserialize<Pokemon>(content);}}}
Now go to Program.cs and add the following line above the builder.build.RunAsync() line.
builder.Services.AddScoped<PokeClient>();
Create a new page to display all the pokemons
Now inside the Pages folder create a new page called Index or use the one that is already there and add the code below.
@page"/"@usingModels@usingProperties@injectPokeClientclient@code{Pokemonpokemon=newPokemon();protectedoverrideasyncTaskOnInitializedAsync(){pokemon=awaitclient.GetPokemon("1");Console.WriteLine(pokemon.name);}}
If you run the project and go into the console you should be able to see the pokemon name displayed there.
Add bootstrap
For styling we will be using a mixture of some bootstrap classes and our custom css, but before using bootstrap we must install it. Open the console inside visual studio and run the following commands to initialize libman and install bootstrap.
libman initlibman install twitter-bootstrap@5.2.3
Then you will be prompted to select the folder destination, if you select the default destination you should have something like the following.
Now go into index.html file and insert the cdn link tag to bootstrap and another css link tag to our project, this should have the name of your project, mine is Blazordex.
<linkhref="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"rel="stylesheet"integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"crossorigin="anonymous"><linkhref="css/app.css"rel="stylesheet"/><linkrel="stylesheet"href="BlazorDex.styles.css">
Add initial html markup to Index.razor and create PokemonList property
Add the initial markup on the Index page
Now that we have bootstrap working and our styles tags are in place let's begin adding some initial markup and some code.
<divclass="container"><divclass="pokemon-row">@foreach(varpinpokemonList){<divclass="pokemon-card"><imgsrc="@p.sprites.front_default"alt=""><h4class="pokemon-name">@p.name</h4><divclass="type-row">@foreach(vartypeinp.types){<span>@type.type.name</span>}</div></div>}</div></div>@code{List<Pokemon>pokemonList=newList<Pokemon>();protectedoverrideasyncTaskOnInitializedAsync(){for(inti=1;i<152;i++){pokemonList.Add(awaitclient.GetPokemon(i.ToString()));StateHasChanged();}}}
Now you should be able to see some pokemons getting displayed on the index page, this is not styled yet, we will implement those classes right now.
Add initial css
*{box-sizing:border-box;}.container{margin-top:50px;display:flex;flex-direction:column;}.pokemon-row{display:flex;flex-direction:row;flex-wrap:wrap;gap:50px;justify-content:center;align-items:center;}.pokemon-card{width:200px;height:250px;padding:10px;background-color:#FFF;align-items:center;text-align:center;border-radius:10px;box-shadow:010px10pxrgba(0,0,0,0.15);}img{width:80%;height:60%;}.type-row{display:flex;justify-content:space-around;}.pokemon-name{text-transform:capitalize;text-decoration:none;color:#000;}
Add another utilities class to display the color of the Pokémon type badge
To display the color of the types such as "water, fire, greass, etc" we will create a new utilite class called "PokeColor" and therefore call this on the Index page.
namespacenewBlazorDex.Util{publicstaticclassPokeColor{publicstaticstringGetTypeColor(stringtype){stringcolor=typeswitch{"bug"=>"#26de81","dragon"=>"#ffeaa7","electric"=>"#fed330","fairy"=>"#FF0069","fighting"=>"#30336b","fire"=>"#f0932b","flying"=>"#81ecec","grass"=>"#00b894","ground"=>"#EFB549","ghost"=>"#a55eea","ice"=>"#74b9ff","normal"=>"#95afc0","poison"=>"#6c5ce7","psychic"=>"#a29bfe","rock"=>"#2d3436","water"=>"#0190FF",_=>"#0190FF"};returncolor;}}}
Add styling for span for type badge
Now let's call this utilitie class inside our Index page, on the Span elements that contains the class badge-type. Also below is the code to style this badge.
<spanclass="badge-type"style="background-color: @PokeColor.GetTypeColor(@type.type.name);">@type.type.name</span>
.type-badge { padding: 5px; padding-left: 10px; padding-right: 10px; border-radius: 8px; font-size: 13px; color: #fff; text-transform: uppercase; margin-right: 3px;}
Add a title with Pokémon like font.
For this kind of font I wen to to a page like text craft and generated an image for our application with pokemon like font styling. After having this put this image inside the img directory and add the image tag inside the Index page.
<divclass="container"><imgsrc="/img/Blazor-Dex.png"class="app-title"> //Add this line<divclass="pokemon-row">
.app-title { width: 400px; margin: 0 auto 20px auto;}
Create PokemonCard Page and add initial code to make it work and display a pokemon
Now let's create a new page to display a single pokemon and show relevant data about like stats and wegith and height.
@page"/pokemon"@injectnewBlazorDex.Util.PokeClientclient<h1>PokemonCard</h1><h2>@poke.name</h2><imgsrc="@poke.sprites.front_default"alt="">@code{Pokemonpoke=newPokemon();protectedasyncoverrideTaskOnInitializedAsync(){poke=awaitclient.GetPokemon("1");}}
Add a new function in PokeColor class to Get Stats color
Now add a new function in the class PokeColor to get the color from the stats, as the past function to get the color from the type this will return the color hex code for the color of the stat we are currenty displaying.
publicstaticstringGetStatColor(stringstat){stringcolor=statswitch{"hp"=>"#FE0000","attack"=>"#EE7F30","defense"=>"#F7D02C","special-attack"=>"#F85687","special-defense"=>"#77C755","speed"=>"#678FEE",_=>"#0190FF"};returncolor;}
Add the rest of the code to PokemonCard page
Now add the resto of the markup, here we are doing many things. We are adding calls to GetTypeColor function and GetStatColor function, also we are passing a Parameter for this page called PokemonId to know which pokemon we should be displaying. Aside from calls to another PokeUtil class which will randomly display a type of pokeball to the left of the pokemon name.
@page"/pokemon/{pokemonId}"@usingModels@usingProperties@usingUtil@injectPokeClientclient<divclass="container"><divclass="card">@if(@poke.types.Count>0){<divclass="card-top"><imgsrc="@poke?.sprites?.front_default"alt="pokemon sprite"class="card-img-top"></div>}<divclass="inner-container"><divclass="stats-head"><divclass="icon-container"><imgsrc="/img/@PokeUtil.GetRandomBall()"class="poke-icon"/>"<h1class="pokemon-namecard-title"><b>@poke?.name</b></h1></div><divclass="pokemon-info"><h5>Height:@GetPokemonHeightInMeters(poke.height)m</h5><div>@foreach(vartypeinpoke.types){<spanclass="type-badge"style="background-color: @ShowTypeColor(@type.type.name);">@type.type.name</span>}</div><h5>Weight:@GetPokemonWeightInKilograms(poke.weight)kg</h5></div></div><divclass="stats-head"><divclass="icon-container"><imgsrc="<https://img.icons8.com/color/48/null/insignia-3.png>"class="poke-icon"/><h2>Stats</h2></div>@foreach(varstatinpoke?.stats){<divclass="stat-bar"><h5class="stat">@stat.stat.name: @stat.base_stat</h5><divclass="progress"><divclass="progress-barprogress-bar-striped" role="progressbar"style="width: @stat.base_stat%; background-color: @GetStatColor(@stat.stat.name);"aria-valuenow="100"aria-valuemin="0"aria-valuemax="200"></div></div></div>}</div></div></div></div>@code{[Parameter]publicstringpokemonId{get;set;}="";Pokemonpoke=newPokemon();protectedoverrideasyncTaskOnInitializedAsync(){poke=awaitclient.GetPokemon(pokemonId);}}
Add the styling for PokemonCard
.pokemon-name{text-transform:capitalize;}img{width:200px;}.badge{text-transform:capitalize;}.container{margin:30pxauto;width:28%;}.inner-container{margin:0auto;width:100%;text-align:center;padding:20px;padding-top:0px;}.card-top{display:flex;flex-direction:column;text-align:center;align-items:center;border-radius:15px;}.card{box-shadow:020px30pxrgba(0,0,0,0.3);border-radius:15px;}.pokemon-info{display:flex;justify-content:space-around;align-items:center;margin-bottom:10px;}.type-badge{padding:5px;padding-left:10px;padding-right:10px;border-radius:8px;font-size:13px;color:#fff;text-transform:uppercase;margin-right:3px;}.stat{text-transform:capitalize;}.stat-bar{display:flex;flex-direction:column;text-align:left;margin-bottom:5px;}.stats-head{background-color:#F0F0F0;padding:10px;border-radius:15px;margin-top:5px;}.poke-icon{width:30px;height:30px;margin-right:10px;}.icon-container{display:flex;align-items:center;justify-content:center;}
Create another util class called PokeUtil to manage measurement units and convert them along with a function to get a random pokeball
Units in the pokeapi are not pounds or kilograms for weight types, the same for height so this class is to convert those measurement units to kilograms and meters and the GetRandomBall function will return a random pokeball to display to simulate that we catched this pokemon with that pokeball.
usingSystem.Globalization;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Threading.Tasks;namespaceBlazorDex.Util{publicstaticclassPokeUtil{publicconststringPokeball="icons8-pokeball-96.png";publicconststringGreatBall="icons8-superball-96.png";publicconststringUltraBall="icons8-ultra-ball-96.png";publicconststringMasterBall="icons8-mega-ball-96.png";publicstaticstringGetRandomBall(){varpokeballArray=newstring[]{Pokeball,GreatBall,UltraBall,MasterBall};varrand=newRandom();stringrandomBall=pokeballArray[rand.Next(pokeballArray.Length)];returnrandomBall;}publicstaticdoubleGetPokemonHeightInMeters(intheight){returnConvert.ToDouble(height)/10;}publicstaticdoubleGetPokemonWeightInKilograms(intweight){returnConvert.ToDouble(weight)/10;}}}
Thanks, and consider supporting me! 🙌🏽
This is it, now you have a complete pokedex with C# and blazor that load pokemons dynamically without the need to use any javascript which is awesome.
This is my first article on dev.to so I know there will be some or lots of errors so big apologies 🙇🏽♂️, anyways the code will be available on my kofi page and there ir also a youtube version where you can code along with me.
If you enjoyed this guide please follow me on my journey to create cool and fun projects for C# and the .NET community because I consider we need more projects like that that can engage people with topics that we like and that are catchy for the eye 👁️.
https://www.youtube.com/@unitcoding6783
Also if you really enjoyed the project please consider supporting me on kofi I would be really grateful as that would help me to continue creating more of this cool content.
Also other ways to support me would be to continue my next articles on dev.to and following me on youtube!
Thanks for your attention and I hope you can get the most out of this tutorial, see you soon guys!!! 👋🏽👋🏽👋🏽
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse