Gift Card System using .NetCore, RedisJSON and ReactJs

Rajeev Soni
10 min readJun 19, 2022

Introduction

In this article, we will be creating a gift card system using RedisJSON, .NET Core and ReactJS.

We will use RedisJSON as our persistence store for keeping our data related to gift cards. RedisJSON is a high performance NoSQL document based storage provided by Redis.

We will be creating REST Api using .NET Core which will provide CRUD operations around gift cards and will integrate it with a UI created in React which will be calling those REST endpoints.

Prerequisites

  1. We will be using Redis OM .NET library for handling documents in redis. For the we will use .NET Core 6.
  2. Any IDE for writing .NET Code. Visual Studio, VS Code or Rider will work.
  3. npm will be required to run the React app and for that we need to install Node.js

Design of Gift Card System

We will be designing a basic Gift Card system on the line of Amazon Gift card system where an Admin should be able to create Gift cards of some value and a consumer should be able to redeem the gift cards. We will be creating an Admin dashboard and Consumer dashboard for that purpose.

Here the most important thing is storage entities. we need to design some entities for storing our data related to gift cards. For keeping things simple we will create one entity i.e. GiftCard which will store our data related to gift cards. Below is the entity which will serve our purpose.

string Idstring Codedouble ValueDateTime CreatedOn DateTime ExpireOnbool IsConsumed

Here is the reference for the entity in our code repo.

Its a basic entity which will store info like gift card code ,its value, created and expiry time and a flag to represent whether its consumed or not.

After designing entity, we will be creating REST API for performing CRUD operations on Gift Cards data. We will be creating 3 REST endpoints for creating gift cards, listing gift cards and redeeming gift cards.

Once the Endpoints are ready we will integrate those in UI.

In the next sections we will go through all the steps in details for setting up our gift card App. Lets dive in :)

Setting up Redis Cluster

Signup for Redis cloud using this link. They are providing 200$ free credits to start via coupon code TIGER200.

Once you signup and login. When you sign in, you will be asked to choose cloud provider from Azure, google cloud, aws. Choose any one which you prefer and after that a free subscription will be created for you.

Once the subscription is created, a database will also be created for you which has modules RedisJSON, Redis Search , Redis Bloom, Redis Graph and Redis TimeSeries. For our app we need Redis JSON and Redis Search only. So we will delete the existing one and create a new database.

In order to delete, click on databases on left side of options under Subscriptions. You will get to see the default database which is created for you. After that click on the database name and you will land on database configuration page. Scroll down the page and you will get to see the delete option under Danger Zone at the bottom.

After that we need to create a new database. For that click on Subscription options again. Now under your subscription there is no database and you will be getting an option New Database button to create database. Click on that and you will be getting options to set name for your database and you will be getting the type to set for your database. Here choose Redis instead of Redis Stack and select RedisJSON and RedisSearch. after that click Activate and your database will be ready to use in few minutes.

Once your database is ready, keep the public endpoint and password value handy at one place from general and security sections respective as we will be using it later for creating our connection string.

Setting up .NET Core REST API

Open the visual studio and create .NET Core Web API project. You can choose .NET 6 as the target framework and keep rest of the configurations as it is. Once you click on create project , visual studio will bootstrap a project for you.

First we need to add our entity for Gift Card which will be used to model document in Redis database.

This is the entity we will be using:

[Document]
public partial class GiftCard
{
[RedisIdField]
public string Id { get; set; }
[Indexed(Sortable = true)]
public string Code { get; set; }
[Searchable(Sortable = true)]
public double Value { get; set; }
[Indexed(Sortable = true)]
public DateTime CreatedOn { get; set; }
[Indexed(Sortable = true)]
public DateTime ExpireOn { get; set; }
[Searchable(Sortable = true)]
public bool IsConsumed { get; set; }
}

After this, we need to add REST endpoints for our Gift Card System and for that we will first create a Controller for gift cards.

[ApiController][Route(“[controller]”)]public class GiftCardsController : ControllerBase
{
}

After this we will create below REST endpoints

GET
/giftcards
Query Parameter: bool IsConsumed
---------------------------------------------------
POST
/giftcards
Body: {double GiftCardValue}
---------------------------------------------------
PUT
/giftcards/redeem
Body: {string GiftCardCode}
---------------------------------------------------
POST
/InitializeStorage

Redis OM .NET library installation

Before adding Rest endpoints we need to add Redis OM .NET nuget which we will be using to connect to Redis database and performing operations on it.

To install Redis OM .NET all you need to do is add the Redis.OM NuGet package to your project. This can be done by running dotnet add package Redis.OM

Setting up Redis Connection provider dependency

Redis OM .NET uses RedisConnectionProvider class to handle connections to Redis and provides functions by which you can interact with Redis. To use it, we need to inject an instance of the RedisConnectionProvider into your app by using .NET Core dependency injection. For this, you need to put below code in Program.cs file.

builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration["REDIS_CONNECTION_STRING"]));

We also need to add REDIS_CONNECTION_STRING in our appsettings.json file. In order to get our connection string we can use the below schema:

“redis://username:password@hostname:port/4"

Username, password and public endpoint(host)can be found in under the configuration tab of database. Replace those values in the above schema and you will get your connection string you need to put under appsettings.json file.

After this the provider will now be available in your controllers/services to use.

REST Endpoints

The first 3 endpoints are for performing CRUD operations in GiftCards and the last one is for a specific purpose i.e. to create Index for our GiftCard entity on Redis Database that we have created on Redis Cloud in previous step.

  1. Initialize Storage

With the entity in place, the next step is to create the index in Redis database for the Gift Card model we have created. This operation needs to be done only one time so we are creating an POST endpoint for this and run this only once.

Below code will create create a RedisConnectionProvider using Redis connection string and then create index of type GiftCard in Redis. In case of success it will return 201 (created) else there will be some exception.

[HttpPost("/InitializeStorage")]
public async Task<IActionResult> InitializeStorage()
{
var provider = new RedisConnectionProvider(_configuration["REDIS_CONNECTION_STRING"]);
var isSuccess = await provider.Connection.CreateIndexAsync(typeof(GiftCard));
return Created("Storage", null);
}

2. Create gift card endpoint

We need to provide an endpoint which will take user input for gift card value and create a gift card of the corresponding value in our system with all the appropriate details.

We will be creating a POST endpoint which will take createGiftcardRequest in which we need to pass giftCardValue and this will be passed in Body of the POST request.

Below code will create a gift card with a giftcard code generated using GUID, the value passed in giftCardValue, with created and Expiry time and isConsumed flag set to false as this is a newly created gift card.

[HttpPost]
public async Task<IActionResult> CreateGiftCard([FromBody] CreateGiftCardRequest createGiftCardRequest)
{
var giftCard = new GiftCard();
giftCard.Value = createGiftCardRequest.GiftCardValue;
giftCard.Code = Guid.NewGuid().ToString();
giftCard.CreatedOn = DateTime.UtcNow;
giftCard.ExpireOn = giftCard.CreatedOn.AddYears(1);
giftCard.IsConsumed = false;
var giftCardCollection = _provider.RedisCollection<GiftCard>();
await giftCardCollection.InsertAsync(giftCard);
return Created(“GiftCard”, giftCard.Id);
}

3. Get all Gift cards endpoint

We need to provide an endpoint which will list all the gift cards created in the system.

We will be creating a GET endpoint which will take GiftCardQuery in which we can pass IsConsumed flag. This will be passed as query parameter in GET our request.

We have created isConsumed flag a nullable means i can skip to pass any value for it means pass it as null and in such case all the gift cards in the system will be returned. But if we choose to pass IsConsumed flag value as false /true, we will filter out Gift Cards based on the IsConsumed flag.

Similarly, if we need we can add more flags to filter out Gift cards on the basis of our requirements.

Below code will fetch gift cards on the basis of the query parameter we will be sending. If we avoid sending any query parameter we will be returning all the gift cards else we will filter out gift cards on the basis of our query parameter and send them in Ok response.

[HttpGet]
public async Task<IActionResult> Get([FromQuery] GiftCardQuery giftCardQuery)
{
var giftCardCollection = _provider.RedisCollection<GiftCard>();
if (giftCardQuery.IsConsumed.HasValue)
{
giftCardCollection = giftCardCollection.Where(x => x.IsConsumed == giftCardQuery.IsConsumed.Value);
}
IList<GiftCard> giftCards = await giftCardCollection.ToListAsync();
return Ok(giftCards);
}

4. Redeem gift card endpoint

Next, We need to provide an endpoint which consumer can use to redeem a gift card by passing the code value.

We will be creating a PUT endpoint which will take RedeemGiftCardRequest in which we need to pass giftCardCode. This data will be passed in PUT request’s Body.

If user’s doesn’t pass any value for giftcardCode, in that case request is not valid and we will return 400 in response.(Bad request)

If giftCardCode is passed in request, then we will try to fetch the gift card with that code and check if a gift card with that code even exists or not and also we need to validate that the code is not consumed till now and also its not expired. if any of the condition fails we will mark the request a bad request and will return 400 in response.

Below code will validate our RedeemGiftCardRequest if its a valid request or not by checking existence of gift card corresponding to the code passed in the request and checking its vaidity.

[HttpPut]
[Route(“redeem”)]
public async Task<IActionResult> Redeem([FromBody] RedeemGiftCardRequest redeemGiftCardRequest)
{
if(string.IsNullOrEmpty(redeemGiftCardRequest.GiftCardCode))
{
return BadRequest();
}
var giftCardCollection = _provider.RedisCollection<GiftCard>();
var all = await giftCardCollection.ToListAsync();
var validGiftCard = await giftCardCollection.FirstOrDefaultAsync(x => x.Code == redeemGiftCardRequest.GiftCardCode);
if(validGiftCard == null || validGiftCard.IsConsumed || validGiftCard.ExpireOn < DateTime.UtcNow)
{
return BadRequest();
}
validGiftCard.IsConsumed = true;
_provider.Connection.Set(validGiftCard);
return Accepted();
}

Setting up React UI and integration with API

Once we are done with REST endpoints, we will next work on integrating those endpoints with our UI.

Setting up REST endpoints in React App

I have a sample UI created here which you can clone and integrate with your endpoints to test it out locally.

After you clone the repo locally, get into the giftcardapp folder and run npm start command and it will start the react app on this url http://localhost:3000

Here it will not work immediately, as we need to make some configurations changes to integrate it with our API to run it locally.

In the react app, we have 2 js files i.e. AdminDashboard.js and ConsumerDashboard.js and we need to provide API endpoints in both of the files.

In AdminDashboard.js, we need to provide the POST endpoint for creating GiftCard in handleSubmit function and we need to provide GET endpoint for listing all the giftcards on UI in fetchData function.

Similarly, on ConsumerDashboard.js we need to provide PUT endpoint for redeeming gift card in handleSubmit function.

Adding connection string for Redis database

In order to interact with the Redis database, we have created on Redis Cloud, we need to specify connection string for the Redis database in our API project. For that we need to add the connection string value for the key REDIS_CONNECTION_STRING in appSettings.json file of our .NET Core API project.

Enabling CORS for our react app

After that you need to add the URL of your react app on .NET Core API project to enable CORS. To know more about CORS you can visit this link. We need to add the url of our UI app i.e. http://localhost:3000 in program.cs file in our API project as mentioned below to allow UI to make calls to our endpoints, other wise we will get CORS error.

app.UseCors( options => options
.WithOrigins(“http://localhost:3001")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());

Once all the above configurations are setup, we can run the API project and UI app locally and you can add and see Gift cards on Admin dashboard.

Similarly on Consumer Dashboard, you can Redeem any gift card by providing the gift card code.

Conclusion

Hope you get to learn how we can use RedisJSON with .NET Core in this blog.

If you have any doubts or you are facing any issue with setting up the project locally you can reach out to me on my email here: rajivsn007@gmail.com

If you have any feedback for me around the gift card system, you can share on my GitHub repo itself. Till then keep learning and coding :)

This post is in collaboration with Redis.

References

You can find complete project here on GitHub

Some other useful links related Redis are mentioned below.

Getting Started With Redis

Redis Developer Hub

RedisInsight Desktop GUI

--

--