Back to: ASP.NET Core Web API Tutorials
Implementing Room Type Module of Hotel Booking Application
In this article, I will discuss implementing the Room Type Module of a Hotel Booking Application. Please read our previous article discussing How to Implement the User Module of a Hotel Booking Application.
How to Implement Room Type Module of Hotel Booking Application
Let us implement the Room Type Module. Let us create the Stored Procedures, Model classes, DTOS, a Repository class, and RoomType Controller for adding, updating, and deleting Room Type, Fetching the Room Details by Room Type ID, Fetching all Room Details, etc.
Create Stored Procedures for Room Types and Rooms
We will start by creating the necessary stored procedures in SQL Server to Manage the Room Type Data in the database. Please execute the following Script on the HotelDB database that we are working with so far.
-- Create Room Type CREATE PROCEDURE spCreateRoomType @TypeName NVARCHAR(50), @AccessibilityFeatures NVARCHAR(255), @Description NVARCHAR(255), @CreatedBy NVARCHAR(100), @NewRoomTypeID INT OUTPUT, @StatusCode INT OUTPUT, @Message NVARCHAR(255) OUTPUT AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION IF NOT EXISTS (SELECT 1 FROM RoomTypes WHERE TypeName = @TypeName) BEGIN INSERT INTO RoomTypes (TypeName, AccessibilityFeatures, Description, CreatedBy, CreatedDate) VALUES (@TypeName, @AccessibilityFeatures, @Description, @CreatedBy, GETDATE()) SET @NewRoomTypeID = SCOPE_IDENTITY() SET @StatusCode = 0 -- Success SET @Message = 'Room type created successfully.' END ELSE BEGIN SET @StatusCode = 1 -- Failure due to duplicate name SET @Message = 'Room type name already exists.' END COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION SET @StatusCode = ERROR_NUMBER() -- SQL Server error number SET @Message = ERROR_MESSAGE() END CATCH END GO -- Update Room Type CREATE PROCEDURE spUpdateRoomType @RoomTypeID INT, @TypeName NVARCHAR(50), @AccessibilityFeatures NVARCHAR(255), @Description NVARCHAR(255), @ModifiedBy NVARCHAR(100), @StatusCode INT OUTPUT, @Message NVARCHAR(255) OUTPUT AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION -- Check if the updated type name already exists in another record IF NOT EXISTS (SELECT 1 FROM RoomTypes WHERE TypeName = @TypeName AND RoomTypeID <> @RoomTypeID) BEGIN IF EXISTS (SELECT 1 FROM RoomTypes WHERE RoomTypeID = @RoomTypeID) BEGIN UPDATE RoomTypes SET TypeName = @TypeName, AccessibilityFeatures = @AccessibilityFeatures, Description = @Description, ModifiedBy = @ModifiedBy, ModifiedDate = GETDATE() WHERE RoomTypeID = @RoomTypeID SET @StatusCode = 0 -- Success SET @Message = 'Room type updated successfully.' END ELSE BEGIN SET @StatusCode = 2 -- Failure due to not found SET @Message = 'Room type not found.' END END ELSE BEGIN SET @StatusCode = 1 -- Failure due to duplicate name SET @Message = 'Another room type with the same name already exists.' END COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION SET @StatusCode = ERROR_NUMBER() -- SQL Server error number SET @Message = ERROR_MESSAGE() END CATCH END GO -- Delete Room Type By Id CREATE PROCEDURE spDeleteRoomType @RoomTypeID INT, @StatusCode INT OUTPUT, @Message NVARCHAR(255) OUTPUT AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION -- Check for existing rooms linked to this room type IF NOT EXISTS (SELECT 1 FROM Rooms WHERE RoomTypeID = @RoomTypeID) BEGIN IF EXISTS (SELECT 1 FROM RoomTypes WHERE RoomTypeID = @RoomTypeID) BEGIN DELETE FROM RoomTypes WHERE RoomTypeID = @RoomTypeID SET @StatusCode = 0 -- Success SET @Message = 'Room type deleted successfully.' END ELSE BEGIN SET @StatusCode = 2 -- Failure due to not found SET @Message = 'Room type not found.' END END ELSE BEGIN SET @StatusCode = 1 -- Failure due to dependency SET @Message = 'Cannot delete room type as it is being referenced by one or more rooms.' END COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION SET @StatusCode = ERROR_NUMBER() -- SQL Server error number SET @Message = ERROR_MESSAGE() END CATCH END GO -- Get Room Type By Id CREATE PROCEDURE spGetRoomTypeById @RoomTypeID INT AS BEGIN SET NOCOUNT ON; SELECT RoomTypeID, TypeName, AccessibilityFeatures, Description, IsActive FROM RoomTypes WHERE RoomTypeID = @RoomTypeID END GO -- Get All Room Type CREATE PROCEDURE spGetAllRoomTypes @IsActive BIT = NULL -- Optional parameter to filter by IsActive status AS BEGIN SET NOCOUNT ON; -- Select users based on active status IF @IsActive IS NULL BEGIN SELECT RoomTypeID, TypeName, AccessibilityFeatures, Description, IsActive FROM RoomTypes END ELSE BEGIN SELECT RoomTypeID, TypeName, AccessibilityFeatures, Description, IsActive FROM RoomTypes WHERE IsActive = @IsActive; END END GO -- Activate/Deactivate RoomType CREATE PROCEDURE spToggleRoomTypeActive @RoomTypeID INT, @IsActive BIT, @StatusCode INT OUTPUT, @Message NVARCHAR(255) OUTPUT AS BEGIN SET NOCOUNT ON; BEGIN TRY -- Check user existence IF NOT EXISTS (SELECT 1 FROM RoomTypes WHERE RoomTypeID = @RoomTypeID) BEGIN SET @StatusCode = 1 -- Failure due to not found SET @Message = 'Room type not found.' END -- Update IsActive status BEGIN TRANSACTION UPDATE RoomTypes SET IsActive = @IsActive WHERE RoomTypeID = @RoomTypeID; SET @StatusCode = 0 -- Success SET @Message = 'Room type activated/deactivated successfully.' COMMIT TRANSACTION END TRY -- Handle exceptions BEGIN CATCH ROLLBACK TRANSACTION SET @StatusCode = ERROR_NUMBER() -- SQL Server error number SET @Message = ERROR_MESSAGE() END CATCH END; GO
Explanation of Each Stored Procedure:
- spCreateRoomType: Creates a new room type in the RoomTypes table. To avoid duplicates, it checks if a room type with the same name already exists. If successful, it inserts the new room type with the provided details and returns the new room type ID, a success status code, and a success message. If the room type name already exists, it returns an error message and status code indicating failure.
- spUpdateRoomType: Updates the details of an existing room type identified by its ID. It ensures that the new type name does not exist for another record and that the specified room type exists before updating. Success or failure is communicated through a status code and message, indicating whether the update was successful, a duplicate was found, or the room type was not found.
- spDeleteRoomType: Deletes a room type from the RoomTypes table based on the provided room type ID. It first checks if any rooms are still linked to this room type to prevent deleting a type that is in use. It deletes the room type and returns a success message if no dependencies are found. If dependencies exist or the room type is not found, appropriate failure messages and status codes are returned.
- spGetRoomTypeById: Retrieves details of a specific room type by its ID. This procedure fetches the type name, accessibility features, description, and active status of a room type, allowing for detailed viewing of a single room type’s information.
- spGetAllRoomTypes: Fetches all room types from the RoomTypes table, optionally filtered by their active status. This procedure supports viewing all room types or filtering them based on whether they are currently active or inactive.
- spToggleRoomTypeActive: This procedure toggles the active status of a specific room type. It can activate or deactivate a room type, which is useful for managing whether it should be available for new bookings. Success or failure is communicated through a status code and message.
Creating Room Type DTOs:
Next, we need to create the DTOs required for performing operations on Room Types. Controllers and Repositories will use these DTOs to manage Operations and Data Transformation effectively. Please create a folder called RoomTypeDTOs inside the DTOs folder, where we will add all the DTOs related to managing Room Types.
RoomTypeDTO
Create a class file named RoomTypeDTO.cs within the RoomTypeDTOs folder, and then copy and paste the following code. This DTO will only include the properties required to return the Room Type information.
namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class RoomTypeDTO { public int RoomTypeID { get; set; } public string TypeName { get; set; } public string AccessibilityFeatures { get; set; } public string Description { get; set; } public bool IsActive { get; set; } } }
CreateRoomTypeDTO
Create a class file named CreateRoomTypeDTO.cs within the RoomTypeDTOs folder, and then copy and paste the following code. This class will only include the properties required to create a new Room Type.
using System.ComponentModel.DataAnnotations; namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class CreateRoomTypeDTO { [Required] public string TypeName { get; set; } public string AccessibilityFeatures { get; set; } [Required] public string Description { get; set; } } }
CreateRoomTypeResponseDTO
Create a class file named CreateRoomTypeResponseDTO.cs within the RoomTypeDTOs folder, and then copy and paste the following code. Once the room type is created, this class will only include the properties we send.
namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class CreateRoomTypeResponseDTO { public int RoomTypeId { get; set; } public string Message { get; set; } public bool IsCreated { get; set; } } }
DeleteRoomTypeResponseDTO
Create a class file named DeleteRoomTypeResponseDTO.cs within the RoomTypeDTOs folder, and then copy and paste the following code. This class will only include the properties that we are sending once the Room Type is deleted.
namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class DeleteRoomTypeResponseDTO { public string Message { get; set; } public bool IsDeleted { get; set; } } }
UpdateRoomTypeDTO
Create a class file named UpdateRoomTypeDTO.cs within the RoomTypeDTOs folder and copy and paste the following code. This DTO will only include the properties required to update an existing room type.
using System.ComponentModel.DataAnnotations; namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class UpdateRoomTypeDTO { [Required] public int RoomTypeID { get; set; } [Required] public string TypeName { get; set; } public string AccessibilityFeatures { get; set; } [Required] public string Description { get; set; } } }
UpdateRoomTypeResponseDTO
Create a class file named UpdateRoomTypeResponseDTO.cs within the RoomTypeDTOs folder, and then copy and paste the following code. Once the room type is updated, this DTO class will only include the properties we send.
namespace HotelBookingAPI.DTOs.RoomTypeDTOs { public class UpdateRoomTypeResponseDTO { public int RoomTypeId { get; set; } public string Message { get; set; } public bool IsUpdated { get; set; } } }
Creating Room Type Repository:
Next, we need to create the RoomTypeRepository class, where we will implement the business and data access logic. This class will consume the Room Type Related Stored Procedures and DTOs for the operations that we have created so far. So, create a class file named RoomTypeRepository.cs within the Repository folder and copy and paste the following code.
using HotelBookingAPI.Connection; using HotelBookingAPI.DTOs.RoomTypeDTOs; using HotelBookingAPI.Models; using Microsoft.Data.SqlClient; using System.Data; namespace HotelBookingAPI.Repository { public class RoomTypeRepository { private readonly SqlConnectionFactory _connectionFactory; public RoomTypeRepository(SqlConnectionFactory connectionFactory) { _connectionFactory = connectionFactory; } public async Task<List<RoomTypeDTO>> RetrieveAllRoomTypesAsync(bool? IsActive) { using var connection = _connectionFactory.CreateConnection(); var command = new SqlCommand("spGetAllRoomTypes", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.AddWithValue("@IsActive", (object)IsActive ?? DBNull.Value); await connection.OpenAsync(); using var reader = await command.ExecuteReaderAsync(); var roomTypes = new List<RoomTypeDTO>(); while (reader.Read()) { roomTypes.Add(new RoomTypeDTO { RoomTypeID = reader.GetInt32("RoomTypeID"), TypeName = reader.GetString("TypeName"), AccessibilityFeatures = reader.GetString("AccessibilityFeatures"), Description = reader.GetString("Description"), IsActive = reader.GetBoolean("IsActive") }); } return roomTypes; } public async Task<RoomTypeDTO> RetrieveRoomTypeByIdAsync(int RoomTypeID) { using var connection = _connectionFactory.CreateConnection(); var command = new SqlCommand("spGetRoomTypeById", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.AddWithValue("@RoomTypeID", RoomTypeID); await connection.OpenAsync(); using var reader = await command.ExecuteReaderAsync(); if (!reader.Read()) { return null; } var roomType = new RoomTypeDTO { RoomTypeID = RoomTypeID, TypeName = reader.GetString("TypeName"), AccessibilityFeatures = reader.GetString("AccessibilityFeatures"), Description = reader.GetString("Description"), IsActive = reader.GetBoolean("IsActive") }; return roomType; } public async Task<CreateRoomTypeResponseDTO> CreateRoomType(CreateRoomTypeDTO request) { CreateRoomTypeResponseDTO createRoomTypeResponseDTO = new CreateRoomTypeResponseDTO(); using var connection = _connectionFactory.CreateConnection(); var command = new SqlCommand("spCreateRoomType", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.Add(new SqlParameter("@TypeName", request.TypeName)); command.Parameters.Add(new SqlParameter("@AccessibilityFeatures", request.AccessibilityFeatures)); command.Parameters.Add(new SqlParameter("@Description", request.Description)); command.Parameters.Add(new SqlParameter("@CreatedBy", "System")); var outputId = new SqlParameter("@NewRoomTypeID", SqlDbType.Int) { Direction = ParameterDirection.Output }; var statusCode = new SqlParameter("@StatusCode", SqlDbType.Int) { Direction = ParameterDirection.Output }; var message = new SqlParameter("@Message", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; command.Parameters.Add(outputId); command.Parameters.Add(statusCode); command.Parameters.Add(message); try { await connection.OpenAsync(); await command.ExecuteNonQueryAsync(); if ((int)statusCode.Value == 0) { createRoomTypeResponseDTO.Message = message.Value.ToString(); createRoomTypeResponseDTO.IsCreated = true; createRoomTypeResponseDTO.RoomTypeId = (int)outputId.Value; return createRoomTypeResponseDTO; } createRoomTypeResponseDTO.Message = message.Value.ToString(); createRoomTypeResponseDTO.IsCreated = false; return createRoomTypeResponseDTO; } catch (SqlException ex) { createRoomTypeResponseDTO.Message = ex.Message; createRoomTypeResponseDTO.IsCreated = false; return createRoomTypeResponseDTO; } } public async Task<UpdateRoomTypeResponseDTO> UpdateRoomType(UpdateRoomTypeDTO request) { UpdateRoomTypeResponseDTO updateRoomTypeResponseDTO = new UpdateRoomTypeResponseDTO() { RoomTypeId = request.RoomTypeID }; using var connection = _connectionFactory.CreateConnection(); var command = new SqlCommand("spUpdateRoomType", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.Add(new SqlParameter("@RoomTypeID", request.RoomTypeID)); command.Parameters.Add(new SqlParameter("@TypeName", request.TypeName)); command.Parameters.Add(new SqlParameter("@AccessibilityFeatures", request.AccessibilityFeatures)); command.Parameters.Add(new SqlParameter("@Description", request.Description)); command.Parameters.Add(new SqlParameter("@ModifiedBy", "System")); var statusCode = new SqlParameter("@StatusCode", SqlDbType.Int) { Direction = ParameterDirection.Output }; var message = new SqlParameter("@Message", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; command.Parameters.Add(statusCode); command.Parameters.Add(message); try { await connection.OpenAsync(); await command.ExecuteNonQueryAsync(); updateRoomTypeResponseDTO.Message = message.Value.ToString(); updateRoomTypeResponseDTO.IsUpdated = (int)statusCode.Value == 0; return updateRoomTypeResponseDTO; } catch (SqlException ex) { updateRoomTypeResponseDTO.Message = ex.Message; updateRoomTypeResponseDTO.IsUpdated = false; return updateRoomTypeResponseDTO; } } public async Task<DeleteRoomTypeResponseDTO> DeleteRoomType(int RoomTypeID) { DeleteRoomTypeResponseDTO deleteRoomTypeResponseDTO = new DeleteRoomTypeResponseDTO(); using var connection = _connectionFactory.CreateConnection(); //If you want to Delete the Record Permanentlt, then use spDeleteRoomType Stored Procedure var command = new SqlCommand("spToggleRoomTypeActive", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.Add(new SqlParameter("@RoomTypeID",RoomTypeID)); command.Parameters.AddWithValue("@IsActive", false); var statusCode = new SqlParameter("@StatusCode", SqlDbType.Int) { Direction = ParameterDirection.Output }; var message = new SqlParameter("@Message", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; command.Parameters.Add(statusCode); command.Parameters.Add(message); try { await connection.OpenAsync(); await command.ExecuteNonQueryAsync(); deleteRoomTypeResponseDTO.Message = "Room Type Deleted Successfully"; deleteRoomTypeResponseDTO.IsDeleted = (int)statusCode.Value == 0; return deleteRoomTypeResponseDTO; } catch (SqlException ex) { deleteRoomTypeResponseDTO.Message = ex.Message; deleteRoomTypeResponseDTO.IsDeleted = false; return deleteRoomTypeResponseDTO; } } public async Task<(bool Success, string Message)> ToggleRoomTypeActiveAsync(int RoomTypeID, bool IsActive) { using var connection = _connectionFactory.CreateConnection(); using var command = new SqlCommand("spToggleRoomTypeActive", connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.Add(new SqlParameter("@RoomTypeID", RoomTypeID)); command.Parameters.AddWithValue("@IsActive", IsActive); var statusCode = new SqlParameter("@StatusCode", SqlDbType.Int) { Direction = ParameterDirection.Output }; var message = new SqlParameter("@Message", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; command.Parameters.Add(statusCode); command.Parameters.Add(message); await connection.OpenAsync(); await command.ExecuteNonQueryAsync(); var ResponseMessage = message.Value.ToString(); var success = (int)statusCode.Value == 0; return (success, ResponseMessage); } } }
Explanation of Each Method:
Constructor (RoomTypeRepository)
- Input Parameters: SqlConnectionFactory connectionFactory
- Objective: Initialize the repository with a SqlConnectionFactory to facilitate database connections.
- Outcome: The repository is configured to use the provided SqlConnectionFactory for database operations.
RetrieveAllRoomTypesAsync
- Input Parameters: bool? IsActive (optional parameter to filter active/inactive room types)
- Stored Procedure: spGetAllRoomTypes
- Objective: Retrieves all room types from the database, optionally filtered by their active status.
- Outcome: Returns a list of RoomTypeDTO objects representing each room type fetched from the database.
RetrieveRoomTypeByIdAsync
- Input Parameters: int RoomTypeID (ID of the room type to retrieve)
- Stored Procedure: spGetRoomTypeById
- Objective: Fetches a single room type by its ID.
- Outcome: Returns a RoomTypeDTO object containing the room type details if found or null if not found.
CreateRoomType
- Input Parameters: CreateRoomTypeDTO request (contains the details of the new room type to be created)
- Stored Procedure: spCreateRoomType
- Objective: Create a new room type based on the provided details in the database.
- Outcome: Returns a CreateRoomTypeResponseDTO indicating the success or failure of the creation, the message from the database, and the ID of the newly created room type.
UpdateRoomType
- Input Parameters: UpdateRoomTypeDTO request (contains the updated details for an existing room type)
- Stored Procedure: spUpdateRoomType
- Objective: Updates an existing room type with new details provided in the request.
- Outcome: Returns an UpdateRoomTypeResponseDTO indicating whether the update was successful, along with a message detailing the operation’s outcome.
DeleteRoomType
- Input Parameters: int RoomTypeID (ID of the room type to “delete” by setting IsActive to false)
- Stored Procedure: spToggleRoomTypeActive (used to “soft delete” by deactivating the room type)
- Objective: Soft deletes a room type by setting its IsActive status to false.
- Outcome: Returns a DeleteRoomTypeResponseDTO indicating whether the delete operation was successful, along with a message.
ToggleRoomTypeActiveAsync
- Input Parameters: int RoomTypeID, bool IsActive (ID of the room type and the new active status)
- Stored Procedure: spToggleRoomTypeActive
- Objective: Toggles the active status of a room type, enabling or disabling it.
- Outcome: This function returns a tuple (bool Success, string Message) indicating the operation’s success and providing a relevant message.
Register the Repository:
Next, we need to register the RoomTypeRepository into the dependency injection container so that the framework can inject the object wherever we need this repository instance, mostly in the Controller class. So, please add the following code to the Program.cs class file:
builder.Services.AddScoped<RoomTypeRepository>();
Creating Room Type Controller:
Let us create the Room Type Controller and use the methods defined in the above RoomTypeRepository class. So, create a new Empty API Controller named RoomTypeController within the Controllers folder and copy and paste the following code.
using HotelBookingAPI.DTOs.RoomTypeDTOs; using HotelBookingAPI.Models; using HotelBookingAPI.Repository; using Microsoft.AspNetCore.Mvc; using System.Net; namespace HotelBookingAPI.Controllers { [Route("api/[controller]")] [ApiController] public class RoomTypeController : ControllerBase { private readonly RoomTypeRepository _roomTypeRepository; private readonly ILogger<RoomTypeController> _logger; public RoomTypeController(RoomTypeRepository roomTypeRepository, ILogger<RoomTypeController> logger) { _roomTypeRepository = roomTypeRepository; _logger = logger; } [HttpGet("AllRoomTypes")] public async Task<APIResponse<List<RoomTypeDTO>>> GetAllRoomTypes(bool? IsActive = null) { _logger.LogInformation($"Request Received for GetAllRoomTypes, IsActive: {IsActive}"); try { var users = await _roomTypeRepository.RetrieveAllRoomTypesAsync(IsActive); return new APIResponse<List<RoomTypeDTO>>(users, "Retrieved all Room Types Successfully."); } catch (Exception ex) { _logger.LogError(ex, "Error Retriving all Room Types"); return new APIResponse<List<RoomTypeDTO>>(HttpStatusCode.InternalServerError, "Internal server error: " + ex.Message); } } [HttpGet("GetRoomType/{RoomTypeID}")] public async Task<APIResponse<RoomTypeDTO>> GetRoomTypeById(int RoomTypeID) { _logger.LogInformation($"Request Received for GetRoomTypeById, RoomTypeID: {RoomTypeID}"); try { var roomType = await _roomTypeRepository.RetrieveRoomTypeByIdAsync(RoomTypeID); if (roomType == null) { return new APIResponse<RoomTypeDTO>(HttpStatusCode.NotFound, "RoomTypeID not found."); } return new APIResponse<RoomTypeDTO>(roomType, "RoomType fetched successfully."); } catch (Exception ex) { _logger.LogError(ex, "Error getting Room Type by ID {RoomTypeID}", RoomTypeID); return new APIResponse<RoomTypeDTO>(HttpStatusCode.BadRequest, "Error fetching Room Type .", ex.Message); } } [HttpPost("AddRoomType")] public async Task<APIResponse<CreateRoomTypeResponseDTO>> CreateRoomType([FromBody] CreateRoomTypeDTO request) { _logger.LogInformation("Request Received for CreateRoomType: {@CreateRoomTypeDTO}", request); if (!ModelState.IsValid) { _logger.LogInformation("Invalid Data in the Request Body"); return new APIResponse<CreateRoomTypeResponseDTO>(HttpStatusCode.BadRequest, "Invalid Data in the Requrest Body"); } try { var response = await _roomTypeRepository.CreateRoomType(request); _logger.LogInformation("CreateRoomType Response From Repository: {@CreateRoomTypeResponseDTO}", response); if (response.IsCreated) { return new APIResponse<CreateRoomTypeResponseDTO>(response, response.Message); } return new APIResponse<CreateRoomTypeResponseDTO>(HttpStatusCode.BadRequest, response.Message); } catch (Exception ex) { _logger.LogError(ex, "Error adding new Room Type with Name {TypeName}", request.TypeName); return new APIResponse<CreateRoomTypeResponseDTO>(HttpStatusCode.InternalServerError, "Room Type Creation Failed.", ex.Message); } } [HttpPut("Update/{RoomTypeId}")] public async Task<APIResponse<UpdateRoomTypeResponseDTO>> UpdateRoomType(int RoomTypeId, [FromBody] UpdateRoomTypeDTO request) { _logger.LogInformation("Request Received for UpdateRoomType {@UpdateRoomTypeDTO}", request); if (!ModelState.IsValid) { _logger.LogInformation("UpdateRoomType Invalid Request Body"); return new APIResponse<UpdateRoomTypeResponseDTO>(HttpStatusCode.BadRequest, "Invalid Request Body"); } if (RoomTypeId != request.RoomTypeID) { _logger.LogInformation("UpdateRoomType Mismatched Room Type ID"); return new APIResponse<UpdateRoomTypeResponseDTO>(HttpStatusCode.BadRequest, "Mismatched Room Type ID."); } try { var response = await _roomTypeRepository.UpdateRoomType(request); if (response.IsUpdated) { return new APIResponse<UpdateRoomTypeResponseDTO>(response, response.Message); } return new APIResponse<UpdateRoomTypeResponseDTO>(HttpStatusCode.BadRequest, response.Message); } catch (Exception ex) { _logger.LogError(ex, "Error Updating Room Type {RoomTypeId}", RoomTypeId); return new APIResponse<UpdateRoomTypeResponseDTO>(HttpStatusCode.InternalServerError, "Update Room Type Failed.", ex.Message); } } [HttpDelete("Delete/{RoomTypeId}")] public async Task<APIResponse<DeleteRoomTypeResponseDTO>> DeleteRoomType(int RoomTypeId) { _logger.LogInformation($"Request Received for DeleteRoomType, RoomTypeId: {RoomTypeId}"); try { var roomType = await _roomTypeRepository.RetrieveRoomTypeByIdAsync(RoomTypeId); if (roomType == null) { return new APIResponse<DeleteRoomTypeResponseDTO>(HttpStatusCode.NotFound, "RoomType not found."); } var response = await _roomTypeRepository.DeleteRoomType(RoomTypeId); if (response.IsDeleted) { return new APIResponse<DeleteRoomTypeResponseDTO>(response, response.Message); } return new APIResponse<DeleteRoomTypeResponseDTO>(HttpStatusCode.BadRequest, response.Message); } catch (Exception ex) { _logger.LogError(ex, "Error deleting RoomType {RoomTypeId}", RoomTypeId); return new APIResponse<DeleteRoomTypeResponseDTO>(HttpStatusCode.InternalServerError, "Internal server error: " + ex.Message); } } [HttpPost("ActiveInActive")] public async Task<IActionResult> ToggleActive(int RoomTypeId, bool IsActive) { try { var result = await _roomTypeRepository.ToggleRoomTypeActiveAsync(RoomTypeId, IsActive); if (result.Success) return Ok(new { Message = "RoomType activation status updated successfully." }); else return BadRequest(new { Message = result.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error toggling active status for RoomTypeId {RoomTypeId}", RoomTypeId); return StatusCode(500, "An error occurred while processing your request."); } } } }
Explanation of the Controller’s Functions:
GetAllRoomTypes
Retrieves all room types, optionally filtered by their active status.
- Input Parameters: bool? IsActive (optional) to filter room types based on their active status.
- Outcome: Returns a list of RoomTypeDTO objects wrapped in an APIResponse with a success message or an error message in case of failure.
GetRoomTypeById
Fetches a specific room type by its ID.
- Input Parameters: int RoomTypeID to specify which room type to retrieve.
- Outcome: Returns a single RoomTypeDTO object wrapped in an APIResponse, or an error/not found message if no room type is found.
CreateRoomType
Creates a new room type using the details provided in the request.
- Input Parameters: CreateRoomTypeDTO request containing the new room type’s details.
- Outcome: Returns a CreateRoomTypeResponseDTO wrapped in an APIResponse indicating whether the room type was successfully created, along with a relevant message.
UpdateRoomType
Updates details of an existing room type.
- Input Parameters: int RoomTypeId as the URL parameter to identify the room type and UpdateRoomTypeDTO request containing the updated details.
- Outcome: Returns UpdateRoomTypeResponseDTO wrapped in an APIResponse indicating whether the room type was successfully updated, along with a relevant message.
DeleteRoomType
Deletes (or deactivates) a room type identified by ID.
- Input Parameters: int RoomTypeId to specify which room type to delete.
- Outcome: Returns a DeleteRoomTypeResponseDTO wrapped in an APIResponse, indicating whether the room type was successfully deleted, along with a relevant message.
ToggleActive
Toggles the active status of a room type.
- Input Parameters: int RoomTypeId to specify the room type, and bool IsActive to set the desired active status.
- Outcome: Returns a JSON response indicating success with a success message or a BadRequest with an error message if the operation fails.
Testing User Functionalities:
Run the application and test each functionality; it should work as expected.
In this article, I explain the Room Type Module of the Hotel Booking Application. I hope you enjoy this implementation of the Room Type Module of a Hotel Booking Application article. Please take a few minutes to give your valuable feedback about this article. Your feedback means a lot to me and motivates me to give better examples and explanations.
What Next? Implementing the Room Module of the Hotel Booking Application.