Hello! How are you today? I'm going to share my exploration of Redis, Elastic Beanstalk, and Razor Pages in ASP.NET 6. So, let's check it out.
Required Tools
You will be required these tools. Please download and install it.
Project Preparation
You will need to prepare the project of Razor Pages. You can follow the steps below.
- Generate the
.gitignore
. This will be useful when you are using a changes tracker like git.
dotnet new gitignore
- Generate the Razor Project
dotnet new razor -o RedisSample
- Generate the solution to link the root repository to the project directory.
dotnet new sln
- Add the project to the solution.
dotnet sln add RedisSample
- Install
Redis.OM
to the project.
dotnet add .\RedisSample\ package Redis.OM --version 0.2.1
- Try to build, so we know the process is already done.
dotnet build
Time to Code!
- If you want skip the step by step of coding steps, you may use this repository.
bervProject / redis-sample
Redis sample app
Redis Sample
Sample App using Redis as main databases.
Tools
Install Dependencies
dotnet restore
How to Run
- Normal Run
dotnet run --project RedisSample
- With File Watcher
dotnet watch --project RedisSample
Build
dotnet build
Publish
dotnet publish -o PublishedRedisSample
LICENSE
MIT
- Update the
Program.cs
like this.
using Redis.OM;
using RedisSample.HostedService;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration["REDIS_CONNECTION_STRING"]));
builder.Services.AddHostedService<CreateIndexService>();
// Add services to the container.
builder.Services.AddRazorPages();
// the rest of the codes
// ...
app.Run();
- Create the model file:
Models/Note.cs
. This model will be used to define the redis data model.
using Redis.OM.Modeling;
namespace RedisSample.Models;
[Document(StorageType = StorageType.Json, Prefixes = new[] { "Note" })]
public class Note
{
[RedisIdField]
public Ulid Id { get; set; }
[Indexed]
public string Title { get; set; }
[Indexed]
public string Message { get; set; }
}
- Create file
HostedServices/CreateIndexService.cs
. This class will be used to create the index of the model.
using Redis.OM;
using RedisSample.Models;
namespace RedisSample.HostedService;
public class CreateIndexService : IHostedService
{
private readonly RedisConnectionProvider _redisConnectionProvider;
public CreateIndexService(RedisConnectionProvider redisConnectionProvider)
{
_redisConnectionProvider = redisConnectionProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_redisConnectionProvider.Connection.CreateIndex(typeof(Note));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Now, let's go the Pages directory. We will update
Index.cshtml
andIndex.cshtml.cs
also create new fileAddNote.cshtml
,AddNote.cshtml.cs
,EditNote.cshtml
,EditNote.cshtml.cs
. Here we go. You may check the files in here.Index.cshtml
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div>
<a class="btn btn-primary" asp-area="" asp-page="/AddNote" role="button">Add Note</a>
<p>Total Notes: @Model.NoteList.Count</p>
<div class="container">
<div class="row gy-3">
@foreach (var note in Model.NoteList)
{
<div class="col-6">
<div class="card">
<div class="card-body">
<p class="h1">@note.Title</p>
<p>@note.Message</p>
<div class="row">
<div class="col-2">
<a class="btn btn-secondary" asp-area="" asp-page="/EditNote" asp-route-id="@note.Id"
role="button">Edit</a>
</div>
<div class="col-2">
<form method="post">
<button class="btn btn-danger" type="submit" asp-page-handler="DeleteNote"
asp-route-id="@note.Id">Delete</button>
</form>
</div>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
Index.cshtml.cs
sing Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Redis.OM;
using Redis.OM.Searching;
using RedisSample.Models;
namespace RedisSample.Pages;
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
private readonly IRedisCollection<Note> _notes;
public List<Note> NoteList { get; set; } = new List<Note>();
public IndexModel(ILogger<IndexModel> logger, RedisConnectionProvider redisConnection)
{
_logger = logger;
_notes = redisConnection.RedisCollection<Note>();
}
public async Task OnGetAsync()
{
var notes = await _notes.ToListAsync();
NoteList.AddRange(notes);
}
public async Task<IActionResult> OnPostDeleteNoteAsync(string id)
{
var note = await _notes.FindByIdAsync(id);
_logger.LogDebug($"...... data: {note}");
if (note == null)
{
return NotFound();
}
await _notes.DeleteAsync(note);
await _notes.SaveAsync();
return RedirectToPage();
}
}
AddNote.cshtml
@page
@model AddNoteModel
@{
ViewData["Title"] = "Add Note";
}
<h1>Add Note</h1>
<div class="card">
<div class="card-body">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Note!.Title" class="control-label">Title</label>
<input asp-for="Note!.Title" class="form-control" placeholder="Enter the title of notes">
<span asp-validation-for="Note!.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Note!.Message">Message</label>
<textarea class="form-control" asp-for="Note!.Message" placeholder="Enter the message of notes here"> </textarea>
<span asp-validation-for="Note!.Message" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
AddNote.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Redis.OM;
using Redis.OM.Searching;
using RedisSample.Models;
namespace RedisSample.Pages;
public class AddNoteModel : PageModel
{
private readonly ILogger<AddNoteModel> _logger;
private readonly IRedisCollection<Note> _notes;
[BindProperty]
public Note? Note { get; set; }
public AddNoteModel(ILogger<AddNoteModel> logger, RedisConnectionProvider redisConnection)
{
_logger = logger;
_notes = redisConnection.RedisCollection<Note>();
}
public void OnGet()
{
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
if (Note != null)
{
await _notes.InsertAsync(Note);
}
await _notes.SaveAsync();
return Redirect("/");
}
}
EditNote.cshtml
page "{id}"
@model EditNoteModel
@{
ViewData["Title"] = "Edit Note";
}
<h1>Edit Note</h1>
<div class="card">
<div class="card-body">
<form method="post">
<input type="hidden" asp-for="Note!.Id" />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Note!.Title" class="control-label">Title</label>
<input asp-for="Note!.Title" class="form-control" placeholder="Enter the title of notes">
<span asp-validation-for="Note!.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Note!.Message">Message</label>
<textarea class="form-control" asp-for="Note!.Message" placeholder="Enter the message of notes here"> </textarea>
<span asp-validation-for="Note!.Message" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
EditNote.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Redis.OM;
using Redis.OM.Searching;
using RedisSample.Models;
namespace RedisSample.Pages;
public class EditNoteModel : PageModel
{
private readonly ILogger<AddNoteModel> _logger;
private readonly IRedisCollection<Note> _notes;
[BindProperty]
public Note? Note { get; set; }
public EditNoteModel(ILogger<AddNoteModel> logger, RedisConnectionProvider redisConnection)
{
_logger = logger;
_notes = redisConnection.RedisCollection<Note>();
}
public async Task<IActionResult> OnGetAsync(string id)
{
Note = await _notes.FindByIdAsync(id);
if (Note == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
if (Note != null)
{
await _notes.UpdateAsync(Note);
}
await _notes.SaveAsync();
return Redirect("/");
}
}
Test our code locally
Finally done! Now, let's start to try our code. But, we will need to host the Redis Stack first. We will run the Redis Stack using docker. You can check this link for more details. Basically you can run using this command.
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:6.2.2-v4
Ok, let's try our code. You can run the project using this command dotnet run --project RedisSample
or dotnet watch --project RedisSample
.
Now, let's explore your website! You can check this video for the demo.
You might need to check the RedisInsight for more details about the stored data.
Preparing Redis Stack
I think it will not be enough if we just implement it locally. So we will need to host it somewhere else. We will deploy it to Elastic Beanstalk, but I will host the Redis Stack using Redis Enterprise since they have options to host in AWS! For more details on how I set up the Redis Enterprise, you may check this video.
Preparing Elastic Beanstalk
Now, since the Redis Stack is ready. We will move to set up Elastic Beanstalk. Please check this video.
Testing Your App
Finally, we test our code that is hosted in Elastic Beanstalk. Here's my video.
Why I didn't use ElastiCache? So, when I'm exploring the ElastiCache, seems the ElastiCache doesn't have the RediSearch module, so I can't create the index. Like this error logs.
Thank you
Thank you for reading and watching. If you have any comments and suggestions, please feel free to comment in the comment section and tell me about your suggestion.
Top comments (0)