DEV Community

Njeri Muriithi
Njeri Muriithi

Posted on

Lets Build: With ASP.Net Web API - IWallet

Introduction

In today’s world managing personal finances is essential.
Most of us have experienced the consequences of poor financial management, whether overspending, neglecting savings, or struggling to keep track of daily expenditures.
As someone who has personally struggled with this issue for far too long.
I decided to take develop IWallet a C# Web API project dedicated to helping me gain control over my finances and foster healthier spending habits.

As a part of the ongoing C# Web API series, this article will guide you through creating essential components such as models, interfaces, Entity Framework integration, building controllers, and testing the API.

Contents

1.Chapter 1

2.Chapter 2

3.Chapter 3

4.Chapter 4

5.Chapter 5
- API Validation

6.Chapter 6

7.Chapter 7

8.Chapter 8

Prerequisite

  • Microsoft visual studio 2022
  • SQL
  • Net SDK 6.0
  • PostMan

Getting Started

Create an ASP.Net Web API Project in Microsoft visual studio 2022 follow the following steps:

Create a new project on Microsoft Visual studio 2022 →Search and Select ASP.NET Core Web API →Click Next →Add your Project Name –Click Next→Configure the .Net FrameWork → Click create

A New Project is created with the following a test project of weather forecast.Clear the Weather forecast Example .

Add Model
The Model Class acts as representation of the data structure.

  1. Add a new class DailyExpense with the following properties:
using WalletAPI.Entities;
using static WalletAPI.Enums.TransactionEnums;

namespace WalletAPI.Models
{
    public class DailyExpense :BaseEntity
    {

        public string TransactionName { get; set; } = default!;

        public string VendorName { get; set; } = default!;

        public int TransactionCost { get; set; } = default!;

        public int TransactionCostCharges { get; set; } = default!;

        public ModeOfPayments ModeOfPayment { get; set; } = default!;
        public DateTime DateOfTransaction { get; set; } = DateTime.Now;

        public Categories Category { get; set; } = default!;     

        public int TotalAmount
        {
            get
            {
                return TransactionCostCharges + TransactionCost;
            }
            set { }
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

TransactionName --> Represents the Name of Transaction Made Example:Shopping,Rent
VendorName-->Represents the Name of the Vendor where the Transaction is being made Example:Name of Shop, etc.
TransactionCost -->Amount spent.
TransactionCostCharges --> Costs Involved during the Transaction
ModeOfPayment -->How did you pay via Cash,Bank,MobilePayment etc
DateOfTransaction --> Date payment was made.
Category --> Category of the Transaction.
TotalAmount --> The total amount spent on the Transaction (TransactionCostCharges +TransactionCost)


The DailyExpense class inherits the Id from the BaseEntity class.

 using WalletAPI.Entities;
 public class DailyExpense :BaseEntity
Enter fullscreen mode Exit fullscreen mode
Lets Create the BaseEntity class:
  1. Create a new Folder Entities.
  2. Add The Base Entity class.
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;

namespace WalletAPI.Entities
{
    public class BaseEntity
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Column(TypeName = "int")]
        [Display(Name = "Id")]
        [Required]

        public int Id { get; set; }
    }
}

Enter fullscreen mode Exit fullscreen mode

Enums

In the model class created above DailyExpense the properties:
public Categories Category { get; set; } = default!;
public ModeOfPayments ModeOfPayment { get; set; } = default!;
are represented as Enums.
That is why we have using static WalletAPI.Enums.TransactionEnums in the model class.
`Enums

also known as Enumeration is a way of Grouping Related Constants and they are declared using the enum keyword.`

Let's create a new class that incorporates the use of enums:
  1. Create a new folder Enums.
  2. Add class TransactionEnums.
namespace WalletAPI.Enums
{
    public class TransactionEnums
    {
        public enum Categories
        {
            None = 0,
            Transport = 1,
            Food,
            Other
        }
        public enum ModeOfPayments
        {
            None = 0,
            Mpesa = 1,
            Bank,
            Cash
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Entity Framework

In this project we will use Entity Framework core to map the Entities Created in the Model Folder DailyExpense.cs to the SQL Server database.

`Microsoft Entity Framework (EF) -->

is an object-relational mapper that enables .NET developers to work with relational data using domain-specific objects.It uses Code First Approach which means developers can define the application data model using C# and EF Core will automatically generate a database schema.`

https://learn.microsoft.com/en-us/aspnet/entity-framework

  1. Install the Microsoft.EntityFrameworkCore library from the Nugget Package manager or from dotnet cli.
  2. Create a new folder DatabaseContext.
  3. Add a new Class DailyExpenseContext.cs
using Microsoft.EntityFrameworkCore;
using WalletAPI.Models;

namespace WalletAPI.DatabaseContext
{
    public class DailyExpenseContext : DbContext
    {
        public DailyExpenseContext(DbContextOptions options) : base(options)
        {
        }

        public DbSet<DailyExpense> DailyExpesnses { get; set; }
    }
}
Enter fullscreen mode Exit fullscreen mode

The DailyExpenseContext inherits from DbContext base class which is a class in the Microsoft.EntityFrameworkCore library.

        public DailyExpenseContext(DbContextOptions options) : base(options)
        {
        }

Enter fullscreen mode Exit fullscreen mode

The constructor takes an instance of DbContextOptions as its parameter which is used to configure the database connection.

public DbSet<DailyExpense> DailyExpenses { get; set; }
Enter fullscreen mode Exit fullscreen mode

The Entity Framework library includes DbSetclass to represent the model Entity created DailyExpense.
Therefore the name of the corresponding database table will be DailyExpenses.

Configuration of the database

  1. Create a new database in Msql.
  2. Configure the database created using connection strings configuration in the appsettings.json.
  3. Add Connection string :

Appsetting.json showing connection string
DefaultConnection: that defines the value of the connection string.

Configuration of the DatabaseContext in Program.cs

Register the DailyExpenseContext as DbContext to make it available for Dependancy injection.

builder.Services.AddDbContext<DailyExpenseContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
Enter fullscreen mode Exit fullscreen mode

The builder.Configuration.GetConnectionString("DefaultConnection") retrieves the connection string value from the configuration file (appsettings.json) using the key "DefaultConnection".
The retrieved connection string is then passed to the UseSqlServer method to configure the DbContext to use SQL Server with that connection string.

Migrations

Migration in EntityFrameworkCore is the process of updating the database schema to match the latest changes made to the model class.
Install the following NuGet Packages to use Migration.

  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.EntityFrameworkCore.Design The Migration involves the following steps.
  1. Open the Package manager console.
  2. Add Migration command
    AddMigrationCommand on Package Manager Console
    FirstMigration is the migration Name and its upto to specify the name that you want.
    The Migration Command will add three files to your project Under the Migrations Folder.

  3. Update the Database.

Update-Database Command on Package Manager Console

Other Migration Commands.

  • Rollback a migration -->Update-Database -TargetMigration:"{migration_name}"
  • To remove a migration -->Remove-Migration
  • To view the migration history--> Get-Migrations

Data Transfer Object(DTOs)

A DTO is an object that defines how the data will be sent over the network.Learn More on DTOs Here--https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5

  1. Create New Folder DTO's
  2. Add a New Class DailyExpenseDto

using System.ComponentModel.DataAnnotations.Schema;
using static WalletAPI.Enums.TransactionEnums;

namespace WalletAPI.DTO_S
{
    public class DailyExpenseDto
    {
        public string TransactionName { get; set; } = default!;

        public string VendorName { get; set; } = default!;

        public int TransactionCost { get; set; } = default!;

        public int TransactionCostCharges { get; set; } = default!;

        public ModeOfPayments ModeOfPayment { get; set; } = default!;


        public Categories Category { get; set; } = default!;            


        public DateTime DateOfTransaction { get; set; } = DateTime.Now;


    }
}
Enter fullscreen mode Exit fullscreen mode

AutoMapping

AutoMapper -->

AutoMapper is an object-object mapper. Object-object mapping works by transforming an input object of one type into an output object of a different type. Learn More -->https://docs.automapper.org/en/stable/Getting-started.html

  1. Install the AutoMapper NuGet package using the NuGet package manager or from the dotnet CLI
  2. Create a New Folder AutomapperProfile
  3. Add A new Class AutoMapperProfiles
using AutoMapper;
using WalletAPI.DTO_S;
using WalletAPI.Models;

namespace WalletAPI.AutomapperProfile
{
    public class AutoMapperProfiles :Profile
    {
        public AutoMapperProfiles()
        {
            CreateMap<DailyExpense, DailyExpenseDto>().ReverseMap();
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

The code above Maps between the DailyExpenseModel and DailyExpenseDto.
The AutoMapperProfiles inherits from the Profile class provided by the Automapper.
Inside the AutomapperProfiles constructor the CreateMap() Method specifies the source type (DailyExpense), while the second argument specifies the destination type (DailyExpenseDto)
The ReverseMap() method is also called on the mapping, which creates a reverse mapping from DailyExpenseDto to DailyExpense.

API Validation

Validation

is the verification and assurance that an API operates accurately and meets the desired behavior. In this project, we will utilize Fluent Validation as a means to enhance the security of the API.
For more detailed information and insights on this topic, I recommend referring to the accompanying article that I have written.

Lets Create the Validator.

  1. Install FluentValidation Nuget Package.
  2. Create a new folder Validations.
  3. Add the class DailyExpenseValidator.

using static WalletAPI.Enums.TransactionEnums;
using FluentValidation;
using WalletAPI.DTO_S;

namespace WalletAPI.Validations
{
    public class DailyExpenseValidator :AbstractValidator<DailyExpenseDto>
    {
        public DailyExpenseValidator()
        {
            RuleFor(exp => exp.TransactionName).NotEmpty().MinimumLength(2).MaximumLength(50);
            RuleFor(exp => exp.TransactionCost).NotEmpty().GreaterThan(0);
            RuleFor(exp => exp.VendorName).NotEmpty().MinimumLength(2).MaximumLength(30);
            RuleFor(exp => exp.Category).IsInEnum().NotEqual(Categories.None).NotEmpty();
            RuleFor(exp => exp.ModeOfPayment).IsInEnum().NotEqual(ModeOfPayments.None).NotEmpty();

        }
    }
}


Enter fullscreen mode Exit fullscreen mode

IWallet Interface

An Interface

defines a contract for the behavior of a class. It defines set of methods, properties, or Events that a class that subscribes to it must implement.
The Interface class is Identified by the I keyword.
Learn more on Interfaces-->(https://learn.microsoft.com/e
n-us/dotnet/csharp/language-reference/keywords/interface)

  1. Create a New Folder Services
  2. Add A new Interface Class IWallet
using WalletAPI.Models;

namespace WalletAPI.Services
{
    public interface IWallet
    {
        Task<IEnumerable<DailyExpense>> GetTransactions();
        Task<DailyExpense> GetExpenseByName(string 
         TransactionName);
           Task<DailyExpense> AddTransaction(DailyExpense 
        dailyExpense);
        Task<DailyExpense> UpdateTransaction(DailyExpense 
       dailyExpense);
        Task DeleteTransaction(string TransactionName);

    }
}

Enter fullscreen mode Exit fullscreen mode

This Iwallet interface declares several methods related to managing daily expense transactions.

Implement IWallet Interface.

  1. Create a new class DailyExpenseService
using FluentValidation;
using Microsoft.EntityFrameworkCore;
using WalletAPI.DatabaseContext;
using WalletAPI.DTO_S;
using WalletAPI.Models;
using WalletAPI.Validations;

namespace WalletAPI.Services
{
    public class DailyExpenseService:IWallet
    {
        private DailyExpenseContext DailyContext;
        public IFileService FileService { get; }

        public DailyExpenseService(DailyExpenseContext dailyContext,
                                   IFileService fileService
)
        {
            DailyContext = dailyContext;
            FileService = fileService;

        }

        public async Task<DailyExpense> AddTransaction(DailyExpense dailyExpense)
        {
            var _transaction = await DailyContext.DailyExpesnses.AddAsync(dailyExpense);
            await DailyContext.SaveChangesAsync();
            return _transaction.Entity;
        }

        public async Task DeleteTransaction(string TransactionName)
        {
            var deletedTransaction = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(T => T.TransactionName == TransactionName);
            if (deletedTransaction != null)
            {
                DailyContext.DailyExpesnses.Remove(deletedTransaction);
                await DailyContext.SaveChangesAsync();
            }
        }

        public async Task<DailyExpense> GetExpenseByName(string TransactionName)
        {
            var ExpenseEntity = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(N => N.TransactionName == TransactionName);
            return ExpenseEntity;
        }

        public async Task<DailyExpense> GetTransaction(int Id)
        {
            return await DailyContext.DailyExpesnses.FirstOrDefaultAsync(T => T.Id == Id);
        }

        public async Task<IEnumerable<DailyExpense>> GetTransactions()
        {
            var items = DailyContext.DailyExpesnses.ToList();
            return items;
        }

        public async Task<DailyExpense> UpdateTransaction(DailyExpense dailyExpense)
        {
            var updatedExpense = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(T => T.TransactionName == dailyExpense.TransactionName);
            if (updatedExpense != null)
            {
              updatedExpense.TransactionName = dailyExpense.TransactionName;
                updatedExpense.TransactionCost = dailyExpense.TransactionCost;
                updatedExpense.VendorName = dailyExpense.VendorName;
                updatedExpense.TransactionCostCharges = dailyExpense.TransactionCostCharges;
                updatedExpense.Category = dailyExpense.Category;
               updatedExpense.ModeOfPayment = dailyExpense.ModeOfPayment;
                await DailyContext.SaveChangesAsync();
                return updatedExpense;
            }

            return null;
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

This Class provides the implementation of the methods declared in the Iwallet interface

AddTransaction
      public async Task<DailyExpense> AddTransaction(DailyExpense dailyExpense)
        {
            var _transaction = await DailyContext.DailyExpesnses.AddAsync(dailyExpense);
            await DailyContext.SaveChangesAsync();
            return _transaction.Entity;
        }
Enter fullscreen mode Exit fullscreen mode

This method adds a DailyExpense object to the DailyContext (database context) and saves the changes asynchronously. It returns the added DailyExpense object.

DeleteTransaction

  public async void DeleteTransaction(string TransactionName)
        {
            var deletedTransaction = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(T => T.TransactionName == TransactionName);
            if (deletedTransaction != null)
            {
                DailyContext.DailyExpesnses.Remove(deletedTransaction);
                await DailyContext.SaveChangesAsync();
            }
        }
Enter fullscreen mode Exit fullscreen mode

This method deletes a transaction from the DailyContext based on the provided TransactionName.
It removes the transaction from the context and saves the changes asynchronously.

GetExpenseByName
    public async Task<DailyExpense> GetExpenseByName(string TransactionName)
        {
            var ExpenseEntity = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(N => N.TransactionName == TransactionName);
            return ExpenseEntity;
        }

Enter fullscreen mode Exit fullscreen mode

This method retrieves a DailyExpense object from the DailyContext based on the provided TransactionName.

GetTransactions
 public async Task<IEnumerable<DailyExpense>> GetTransactions()
        {
            var items = DailyContext.DailyExpesnses.ToList();
            return items;
        }
Enter fullscreen mode Exit fullscreen mode

This method returns a collection of DailyExpense objects representing all the transactions.

UpdateTransaction
public async Task<DailyExpense> UpdateTransaction(DailyExpense dailyExpense)
        {
            var updatedExpense = await DailyContext.DailyExpesnses.FirstOrDefaultAsync(T => T.TransactionName == dailyExpense.TransactionName);
            if (updatedExpense != null)
            {             
                updatedExpense.TransactionName = dailyExpense.TransactionName;
                updatedExpense.TransactionCost = dailyExpense.TransactionCost;
                updatedExpense.VendorName = dailyExpense.VendorName;
                updatedExpense.TransactionCostCharges = dailyExpense.TransactionCostCharges;
                updatedExpense.Category = dailyExpense.Category;

                updatedExpense.ModeOfPayment = dailyExpense.ModeOfPayment;

                await DailyContext.SaveChangesAsync();
                return updatedExpense;
            }

            return null;
        }
    }
Enter fullscreen mode Exit fullscreen mode

This method updates an existing DailyExpense object in the DailyContext based on the provided TransactionName.
It modifies the properties of the existing object with the values from the passed DailyExpense object and saves the changes asynchronously. The updated DailyExpense object is returned.

Configuration Of Services

Register the interface,validator ,automapper and DbContext created in the program.cs class through Dependancy injection.

Dependancy injection -->

A software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies

Program.cs Containers showing How Services are Configured
By registering these services in the dependency injection container(Program.cs), they can be easily injected into the corresponding controller or other classes throughout the application

The Controller

A controller in ASP.NET is responsible for handling incoming HTTP requests, performing necessary operations, and returning the appropriate HTTP responses.

To add the controller in Microsoft Visual Studio 2022, follow these steps:

  1. Right-click on the project in the Solution Explorer window.
  2. Select "Add" -> "Controller" from the context menu. This will open the "Add Scaffold" dialog.
  3. In the "Add Scaffold" dialog, select "API Controller with actions, using Entity Framework" option.
  4. Click the "Add" button to proceed.
  5. In the "Add Controller" dialog, select the appropriate Model class (e.g., DailyExpense) and the appropriate Data context class (e.g., DailyContext).
  6. Click the "Add" button to generate the controller
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static WalletAPI.DTO_S.ReceiptPhotoUpdateDto;
using WalletAPI.DTO_S;
using WalletAPI.Models;
using WalletAPI.Services;
using WalletAPI.Validations;
using FluentValidation;

namespace WalletAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class DailyTransactionsController : ControllerBase
    {
        private readonly IWallet _wallet;
        private readonly IMapper mapper;
        private DailyExpenseValidator DailyExpvalidator { get; }

        public DailyTransactionsController(IWallet _wallet,
                                           IMapper mapper,
                                           DailyExpenseValidator _dailyExpvalidator)
        {
            this._wallet = _wallet;
            this.mapper = mapper;
            DailyExpvalidator = _dailyExpvalidator;
        }

        [HttpGet]

        public async Task<ActionResult<IEnumerable<DailyExpenseDto>>> GetTransactions()
        {
            var expenses = await _wallet.GetTransactions();

            var expenseDtos = mapper.Map<IEnumerable<DailyExpenseDto>>(expenses);
            return Ok(expenseDtos);


        }

        [HttpGet("Transaction By Name/{TransactionName}")]
        public async Task<ActionResult<DailyExpense>> GetTransactionByName(string TransactionName)
        {
            var ExpenseName = await _wallet.GetExpenseByName(TransactionName);
            if (ExpenseName == null) { return NotFound(); }
            return Ok(ExpenseName);
        }

        [HttpPost]
        public async Task<ActionResult<DailyExpenseDto>> AddNewTransaction(DailyExpenseDto dailyExpenseDto)
        {
            await DailyExpvalidator.ValidateAndThrowAsync(dailyExpenseDto);
            if (dailyExpenseDto == null) return BadRequest();
            var expenseDtos = mapper.Map<DailyExpense>(dailyExpenseDto);
            expenseDtos.TotalAmount = expenseDtos.TransactionCostCharges + expenseDtos.TransactionCost;


            var CreatedTransaction = await _wallet.AddTransaction(expenseDtos);

            return Ok(CreatedTransaction);
        }


        [HttpPut("{TransactionName}")]
        public async Task<ActionResult<DailyExpenseDto>> UpdateExistingTransaction(string TransactionName, DailyExpenseDto dailyExpenseDto)
        {

            await DailyExpvalidator.ValidateAndThrowAsync(dailyExpenseDto);
            if (TransactionName != dailyExpenseDto.TransactionName)
            {
                return BadRequest("Transaction Name does not match");
            }

            var expense = mapper.Map<DailyExpense>(dailyExpenseDto);

            var transactionToUpdate = await _wallet.GetExpenseByName(TransactionName);
            if (transactionToUpdate == null)
            {
                return NotFound("Transaction not found");
            }


            transactionToUpdate.TransactionName = expense.TransactionName;
            transactionToUpdate.VendorName = expense.VendorName;
            transactionToUpdate.TransactionCost = expense.TransactionCost;
            transactionToUpdate.TransactionCostCharges = expense.TransactionCostCharges;
            transactionToUpdate.ModeOfPayment = expense.ModeOfPayment;
            transactionToUpdate.Category = expense.Category;
            transactionToUpdate.DateOfTransaction = expense.DateOfTransaction;
            transactionToUpdate.isNecessaryTransaction = expense.isNecessaryTransaction;



            await _wallet.UpdateTransaction(transactionToUpdate);

            var updatedExpenseDto = mapper.Map<DailyExpenseDto>(expense);

            return Ok(updatedExpenseDto);
        }



        [HttpDelete("{TransactionName}")]
  public async Task<ActionResult<DailyExpenseDto>> DeleteExistingTransaction(string TransactionName)
        {
            string DeleteSucess = "Item Deleted Successfully";

            var transactionToDelete = await _wallet.GetExpenseByName(TransactionName);
            if (transactionToDelete == null) 
            { 
            return NotFound();
            }
             await _wallet.DeleteTransaction(TransactionName);
            return Content(DeleteSucess);
        }


    }
}
Enter fullscreen mode Exit fullscreen mode
Let's break down the code:

The constructor of the DailyTransactionsController class receives several dependencies through dependency injection. These dependencies are:

  • IWallet _wallet: An interface representing the wallet service.
  • IMapper mapper: An interface for object-object mapping.
  • DailyExpenseValidator _dailyExpvalidator: An instance of the DailyExpenseValidator class used for validation.
HTTPGet
[HttpGet]

        public async Task<ActionResult<IEnumerable<DailyExpenseDto>>> GetTransactions()
        {
            var expenses = await _wallet.GetTransactions();

            var expenseDtos = mapper.Map<IEnumerable<DailyExpenseDto>>(expenses);
            return Ok(expenseDtos);


        }
Enter fullscreen mode Exit fullscreen mode

This Method retrieves all the transactions by calling the _wallet.GetTransactions() method asynchronously.
The retrieved transactions are then mapped to DailyExpenseDto object using the mapper.Map method.Then the list of DailyExpenseDto object is returned as the response.

GetTransaction By Name.
     [HttpGet("Transaction By Name/{TransactionName}")]
        public async Task<ActionResult<DailyExpense>> GetTransactionByName(string TransactionName)
        {
            var ExpenseName = await _wallet.GetExpenseByName(TransactionName);
            if (ExpenseName == null) { return NotFound(); }
            return Ok(ExpenseName);
        }
Enter fullscreen mode Exit fullscreen mode

It retrieves a specific transaction by its name, using the _wallet.GetExpenseByName method.
If the transaction is found, it is returned as the response, otherwise a NotFound response is returned.

HTTPPut

        [HttpPut("{TransactionName}")]
        public async Task<ActionResult<DailyExpenseDto>> UpdateExistingTransaction(string TransactionName, DailyExpenseDto dailyExpenseDto)
        {

            await DailyExpvalidator.ValidateAndThrowAsync(dailyExpenseDto);
            if (TransactionName != dailyExpenseDto.TransactionName)
            {
                return BadRequest("Transaction Name does not match");
            }

            var expense = mapper.Map<DailyExpense>(dailyExpenseDto);

            var transactionToUpdate = await _wallet.GetExpenseByName(TransactionName);
            if (transactionToUpdate == null)
            {
                return NotFound("Transaction not found");
            }


            transactionToUpdate.TransactionName = expense.TransactionName;
            transactionToUpdate.VendorName = expense.VendorName;
            transactionToUpdate.TransactionCost = expense.TransactionCost;
            transactionToUpdate.TransactionCostCharges = expense.TransactionCostCharges;
            transactionToUpdate.ModeOfPayment = expense.ModeOfPayment;
            transactionToUpdate.Category = expense.Category;
            transactionToUpdate.DateOfTransaction = expense.DateOfTransaction;
            transactionToUpdate.isNecessaryTransaction = expense.isNecessaryTransaction;
            await _wallet.UpdateTransaction(transactionToUpdate);

            var updatedExpenseDto = mapper.Map<DailyExpenseDto>(expense);

            return Ok(updatedExpenseDto);
        }
Enter fullscreen mode Exit fullscreen mode

It updates an existing transaction with the specified name. First, the dailyExpenseDto object is validated using the DailyExpvalidator.
If the validation fails, an error response is returned. If the validation passes, the dailyExpenseDto object is mapped to a DailyExpense object.
The existing transaction is retrieved using the _wallet.GetExpenseByNamemethod. If the transaction is not found, a NotFound response is returned. Otherwise, the properties of the existing transaction are updated with the new values from the expense object. Finally, the updated transaction is returned as the response.

HTTPPost
    [HttpPost]
        public async Task<ActionResult<DailyExpenseDto>> AddNewTransaction(DailyExpenseDto dailyExpenseDto)
        {
            await DailyExpvalidator.ValidateAndThrowAsync(dailyExpenseDto);
            if (dailyExpenseDto == null) return BadRequest();
            var expenseDtos = mapper.Map<DailyExpense>(dailyExpenseDto);
            expenseDtos.TotalAmount = expenseDtos.TransactionCostCharges + expenseDtos.TransactionCost;
            var CreatedTransaction = await _wallet.AddTransaction(expenseDtos);
            return Ok(CreatedTransaction);
        }
Enter fullscreen mode Exit fullscreen mode

It accepts a DailyExpenseDto object in the request body. First, the dailyExpenseDto object is validated using the DailyExpvalidator and FluentValidation library.
If the validation fails, an error response is returned.
If the validation passes, the dailyExpenseDto object is mapped to a DailyExpenseobject using the mapper.Map method.
The total amount of the expense is calculated by summing TransactionCostCharges and TransactionCost.
Then, the expense is added to the wallet using the _wallet.AddTransaction method. The created transaction is returned

HTTPDelete
  [HttpDelete("{TransactionName}")]

          public async Task<ActionResult<DailyExpenseDto>> DeleteExistingTransaction(string TransactionName)
        {
            string DeleteSucess = "Item Deleted Successfully";

            var transactionToDelete = await _wallet.GetExpenseByName(TransactionName);
            if (transactionToDelete == null) 
            { 
            return NotFound();
            }
             await _wallet.DeleteTransaction(TransactionName);
            return Content(DeleteSucess);
        }
Enter fullscreen mode Exit fullscreen mode

This Methods deletes an existing transaction with the specified name. First, the transaction to delete is retrieved using the _wallet.GetExpenseByName method.
If the transaction is not found, a NotFound response is returned. If the transaction is Found the message Item Deleted Successfully is displayed.

Testing With PostMan

Note:
The 200 OK status code indicates that the request was successful, and the API was able to process it without any issues.

Learn More on Status Codes Here -->(https://learn.microsoft.com/en-us/rest/api/searchservice/http-status-codes)

Add New Transaction

We will create two transactions lunch and BreakFast.

Add new transaction with postman

Get all Transactions

HTTP Get Test with Postman
Sql image showing all the Transactions added

HTTP Put

Lets change content of one of the transaction added.

The Image shows HTTP Put Test with Post Man Change of one of the Transaction
Database Changes:
SQL Image showing Changes of the transaction we have made in the database

Delete the Transaction By Name

Lets delete the transaction that we named lunch.

Transaction deleted success
Database:
Database results transaction was deleted

Conclusion

While this article has focused on the initial stages of IWAllet's development, it serves as a catalyst for further exploration in the C# Web API series. Future articles will dive deeper into additional functionalities, such as authentication, data visualization, advanced analytics, and integration with external services.

Your feedback on how I can make this article even better/more helpful is most appreciated!

Thank you for reading❤️️

Top comments (0)