UssdBuilder 1.0.2
See the version list below for details.
dotnet add package UssdBuilder --version 1.0.2
NuGet\Install-Package UssdBuilder -Version 1.0.2
<PackageReference Include="UssdBuilder" Version="1.0.2" />
paket add UssdBuilder --version 1.0.2
#r "nuget: UssdBuilder, 1.0.2"
// Install UssdBuilder as a Cake Addin #addin nuget:?package=UssdBuilder&version=1.0.2 // Install UssdBuilder as a Cake Tool #tool nuget:?package=UssdBuilder&version=1.0.2
UssdBuilder
USSD may be unstructured, but who says your code has to be? Here is a lightweight and lightning-fast ussd library for advocates of clean and scalable code.
INTRODUCTION
A ussd application is one of hardest api to build. Although the implementation starts fairly simple, it could quickly degenerate into a messy and complicated code of if-else webs.
This library intends to solve the issue above, enabling you build lightning-fast ussd apps quicker, while keeping it clean, readable, and scalable.
SETUP
- Install the Nuget library
- Go to your project's
Startup.cs
orProgram.cs
and add the code below
builder.Services.AddDistributedMemoryCache(); //any implementation of IDistributedCache works, visit https://learn.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-6.0
builder.Services.Configure<DistributedCacheEntryOptions>(opts =>
{
opts.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30); //ussd session timeout
});
builder.Services.AddUssdServer();
USAGE
- Resolve the injected
IUssdServer
instance - Declare your ussd routes
this.server.AddRoute(new UssdRoute
{
Code = "000",
Prev = null, //no previous screen means this is a new ussd session
Regx = (_, _) => true, //use this if you want your request to proceed regardless of user input
Goto = "welcome"
});
//Go to "sayhello" if (ussdCode == "000" && prevScreen == "welcome" && userInput == 1)
this.server.AddRoute(new UssdRoute
{
Code = "000",
Prev = "welcome",
Regx = (_, req) => req.Text == "1",
Goto = "sayhello"
});
//Go to "goodbye" if (ussdCode == "000" && prevScreen == "welcome" && userInput == 2)
this.server.AddRoute(new UssdRoute
{
Code = "000",
Prev = "welcome",
Regx = (_, req) => req.Text == "2",
Goto = "goodbye"
});
// //Go to "goodbye" if (ussdCode == "000" && prevScreen == "welcome", regardless of user input)
// this.server.AddRoute(new UssdRoute
// {
// Code = "000",
// Prev = "welcome",
// Regx = (_, _) => true, //use this if you want your request to proceed regardless of user input
// Goto = "goodbye"
// });
//Go to "welcome" if (ussdCode == "000" && prevScreen == "welcome" && userInput != 1 && userInput != 2)
this.server.AddRoute(new UssdRoute
{
Code = "000",
Prev = "welcome",
Regx = (_, req) => req.Text != "1" && req.Text != "2", //Regx could also be used for input validation like input length check, etc.
Goto = "welcome"
});
- Add your route handlers
this.server.AddHandlers("000", new()
{
{"welcome", async (UssdScreen current, UssdRequest request) => {
// do some async work
return new UssdResponse
{
Status = true,
Message = "CON Welcome.\nEnter \n1. To say hello \n2. To say goodbye \n3. To repeat"
};
}},
{"sayhello", async (UssdScreen current, UssdRequest request) => {
// do some async work
return new UssdResponse
{
Status = true,
Message = $"END Hello world. User input was {request.Text}"
};
}},
{"goodbye", async (UssdScreen current, UssdRequest request) => {
// do some async work
return new UssdResponse
{
Status = true,
Message = $"END Goodbye. User input was {request.Text}"
};
}},
});
- Handle incoming request in your controller action
[HttpPost("Handle")]
public async Task<IActionResult> Handle([FromBody] UssdRequest model)
{
try
{
var result = await server.HandleAsync(model);
return Ok(result);
}
catch (Exception ex)
{
await server.DeleteAsync(model.SessionId);
return Ok($"END An error occurred: {ex.Message}");
}
}
Important note
- Complex input (e.g *0*0*2#) is handled by default using
string.Split(...)
and iteration over splitted inputs. To disable this behaviour, use
builder.Services.AddUssdServer(opt =>
{
opt.EnableInputSplit = false;
});
A single ussd server or endpoint can serve multiple ussd codes, you just have to add routes and handlers for the different codes you want the server to process.
Route.Regx
is not meant to do more than input validation, do your complex work in your handlerFor more details, see sample projects
PRs are welcome.
Having a problem? Verify that you are implementing rightly, check sample projects, and if the problem persists, create an issue.
Want to hire competent engineer(s) for a ussd application? Shoot me an email
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Microsoft.Extensions.Caching.Abstractions (>= 6.0.0)
- Microsoft.Extensions.Options (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
New + Improved
- Reduced package size by prunning unused libraries