You can try it on GitHub Pages here Rick And Morty Wiki
Stack: .NET 7, Blazor WASM App, GraphQL.Client
- Navigation
*Delete github actions script from index.html & 404.html if you have
- Create nginx.conf
events { }
http {
include mime.types;
server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
}
}
}
- Create Dockerfile
*Invoke from parent directory if you have additional libraries (like Application, Domain, etc)
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["src/Presentation/RickAndMortyWiki/RickAndMortyWiki.csproj", "src/Presentation/RickAndMortyWiki/"]
COPY ["src/Core/RickAndMortyWiki.Application/RickAndMortyWiki.Application.csproj", "src/Core/RickAndMortyWiki.Application/"]
COPY ["src/Core/RickAndMortyWiki.Domain/RickAndMortyWiki.Domain.csproj", "src/Core/RickAndMortyWiki.Domain/"]
RUN dotnet restore "src/Presentation/RickAndMortyWiki/RickAndMortyWiki.csproj"
COPY . .
WORKDIR "/src/src/Presentation/RickAndMortyWiki"
RUN dotnet build "RickAndMortyWiki.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "RickAndMortyWiki.csproj" -c Release -o /app/publish
FROM nginx:alpine AS final
WORKDIR /usr/share/nginx/html
COPY --from=publish /app/publish/wwwroot .
COPY nginx.conf /etc/nginx/nginx.conf
- Create docker-compose.yaml
version: '3.4'
services:
blazorapp:
image: blazorandmorty
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:80
The strength of GraphQl is that we ourselves determine the values we need
// Base model for GraphQl response (data : { response: { info: { } results: { } } })
public class Response<T> where T : class
{
public Information Info { get; set; } = null!;
public List<T> Results { get; set; } = new();
}
// Base model for response handling
public class GraphQlArrayResponse<T> where T : class
{
public Response<T> Response { get; set; }
}
// Make the query
public static GraphQLRequest GetPage(int pageNum) =>
new()
{
Query = @$"{{
response: characters(page: {pageNum}) {{
info {{
count
pages
next
prev
}}
results {{
id
name
image
}}
}}
}}"
};
// Handle the data
public async Task<Response<Character>> GetPage(int pageNum)
{
var graphQlClient = new GraphQLHttpClient(Urls.RickAndMortyGraphQl, new NewtonsoftJsonSerializer());
var response =
await graphQlClient.SendQueryAsync<GraphQlArrayResponse<Character>>(CharacterQueries.GetPage(pageNum));
return response.Data.Response;
}
{
response: characters(page: 1) {
info {
count
pages
next
prev
}
results {
id
name
image
}
}
}
{
"data": {
"response": {
"info": {
"count": 826,
"pages": 42,
"next": 2,
"prev": null
},
"results": [
{
"id": "1",
"name": "Rick Sanchez",
"image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg"
},
{
"id": "2",
"name": "Morty Smith",
"image": "https://rickandmortyapi.com/api/character/avatar/2.jpeg"
},
{
"id": "3",
"name": "Summer Smith",
"image": "https://rickandmortyapi.com/api/character/avatar/3.jpeg"
},
{
"id": "4",
"name": "Beth Smith",
"image": "https://rickandmortyapi.com/api/character/avatar/4.jpeg"
},
{
"id": "5",
"name": "Jerry Smith",
"image": "https://rickandmortyapi.com/api/character/avatar/5.jpeg"
},
{
"id": "6",
"name": "Abadango Cluster Princess",
"image": "https://rickandmortyapi.com/api/character/avatar/6.jpeg"
},
{
"id": "7",
"name": "Abradolf Lincler",
"image": "https://rickandmortyapi.com/api/character/avatar/7.jpeg"
},
{
"id": "8",
"name": "Adjudicator Rick",
"image": "https://rickandmortyapi.com/api/character/avatar/8.jpeg"
},
{
"id": "9",
"name": "Agency Director",
"image": "https://rickandmortyapi.com/api/character/avatar/9.jpeg"
},
{
"id": "10",
"name": "Alan Rails",
"image": "https://rickandmortyapi.com/api/character/avatar/10.jpeg"
},
{
"id": "11",
"name": "Albert Einstein",
"image": "https://rickandmortyapi.com/api/character/avatar/11.jpeg"
},
{
"id": "12",
"name": "Alexander",
"image": "https://rickandmortyapi.com/api/character/avatar/12.jpeg"
},
{
"id": "13",
"name": "Alien Googah",
"image": "https://rickandmortyapi.com/api/character/avatar/13.jpeg"
},
{
"id": "14",
"name": "Alien Morty",
"image": "https://rickandmortyapi.com/api/character/avatar/14.jpeg"
},
{
"id": "15",
"name": "Alien Rick",
"image": "https://rickandmortyapi.com/api/character/avatar/15.jpeg"
},
{
"id": "16",
"name": "Amish Cyborg",
"image": "https://rickandmortyapi.com/api/character/avatar/16.jpeg"
},
{
"id": "17",
"name": "Annie",
"image": "https://rickandmortyapi.com/api/character/avatar/17.jpeg"
},
{
"id": "18",
"name": "Antenna Morty",
"image": "https://rickandmortyapi.com/api/character/avatar/18.jpeg"
},
{
"id": "19",
"name": "Antenna Rick",
"image": "https://rickandmortyapi.com/api/character/avatar/19.jpeg"
},
{
"id": "20",
"name": "Ants in my Eyes Johnson",
"image": "https://rickandmortyapi.com/api/character/avatar/20.jpeg"
}
]
}
}
}