Models in ASP.NET Core Web API

Models in ASP.NET Core Web API

In this article, I will discuss Models in ASP.NET Core Web API Application. Please read our previous article discussing Controllers in ASP.NET Core Web API.

Models in ASP.NET Core Web API

In ASP.NET Core Web API, Models are classes that represent the data and business logic of the application. They define the structure, relationships, and constraints of the data that the application manages. Models play an important role in data persistence, data validation, and data transfer between the client and server. The following are the Key Features of Models in ASP.

  • Data Representation: Models are typically Plain Old CLR Objects (POCOs) that define the properties corresponding to the data fields. They can represent entities stored in a database, encapsulating both the data and related business logic.
  • Data Annotations for Validation: Models can be decorated with attributes from the System.ComponentModel.DataAnnotations namespace to enforce validation rules. Common annotations include Required fields [Required], String length [StringLength], Range constraints [Range], and Format Validaions [RegularExpression], which help ensure data integrity and correctness.
  • Defining Relationships: Models can define relationships between different entities using navigation properties. For example, a Product model might have a foreign key to a Category model, establishing a one-to-many relationship.
  • Data Transfer Objects (DTOs): Models can serve as DTOs, which are specialized objects used to transfer data between the client and server. DTOs help in shaping the data exposed by the API, allowing us to hide sensitive information and include only necessary fields.
  • Entity Framework Integration: When using Entity Framework Core (EF Core) for data access, models are mapped to database tables. EF Core uses models to perform CRUD (Create, Read, Update, Delete) operations on the database.
Creating Model:

In ASP.NET Core Web API, Models can be created anywhere in your project, such as:

  • A separate class library project (recommended for larger applications),
  • Any folder or subfolder within the project.

However, as per the recommendation, the models should be created inside a dedicated folder called Models for better maintainability and clarity. So, first, create a folder named Models in the project root directory.

Creating a Model for Product:

Now, let us add a basic model to represent the Product information. Right-click on the Models folder, add a class file named Product.cs, and copy and paste the following code. This is a simple model representing a product. It contains properties like ID, Name, Price, and Category.

using System.ComponentModel.DataAnnotations;
namespace MyFirstWebAPIProject.Models
{
    public class Product
    {
        public int Id { get; set; }

        [Required]
        [StringLength(100, MinimumLength = 3)]
        public string Name { get; set; }

        [Range(0.01, 10000.00)]
        public decimal Price { get; set; }

        [Required]
        public string Category { get; set; }
    }
}

Note: Data Annotations Attributes like [Required] and [StringLength] enforce validation rules. Property Types ensure that property types align with the data we intend to store and transfer.

Using Models in Controller:

Controllers in ASP.NET Core Web API handle HTTP requests and responses. Models are integral to controllers for binding incoming data, processing it, and returning responses. Models are typically used in the request body for POST and PUT operations and in the response body for GET operations.

  • GET Requests: Retrieve data using models, either returning a collection or a single model instance based on the request parameters.
  • POST Requests: Create new instances by accepting model data from request bodies.
  • PUT Requests: Update existing data by matching data from request bodies with existing model instances.
  • DELETE Requests: Remove model instances based on identifiers provided in requests.

Let’s create a ProductsController to manage Product entities. Right-click on the Controllers folder, select Add > Controller, choose API Controller – Empty, name it ProductsController, and then copy and paste the following code. The following Products Controller uses the Product model to handle API requests.

using Microsoft.AspNetCore.Mvc;
using MyFirstWebAPIProject.Models;

namespace MyFirstWebAPIProject.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase
    {
        // In-memory list to store products (for demonstration purposes)
        // In Real-time, we will use database
        private static List<Product> _products = new List<Product>
        {
            new Product { Id = 1, Name = "Laptop", Price = 1000.00m, Category = "Electronics" },
            new Product { Id = 2, Name = "Desktop", Price = 2000.00m, Category = "Electronics" },
            new Product { Id = 3, Name = "Mobile", Price = 300.00m, Category = "Electronics" },
            // Additional products can be added here
        };

        // GET: api/products
        [HttpGet]
        public ActionResult<IEnumerable<Product>> GetProducts()
        {
            return Ok(_products);
        }

        // GET: api/products/{id}
        [HttpGet("{id}")]
        public ActionResult<Product> GetProduct(int id)
        {
            var product = _products.FirstOrDefault(p => p.Id == id);
            if (product == null)
            {
                return NotFound(new { Message = $"Product with ID {id} not found." });
            }
            return Ok(product);
        }

        // POST: api/products
        [HttpPost]
        public ActionResult<Product> PostProduct([FromBody] Product product)
        {
            // Basic ID assignment logic (for demonstration)
            product.Id = _products.Max(p => p.Id) + 1;
            _products.Add(product);
            return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
        }

        // PUT: api/products/{id}
        [HttpPut("{id}")]
        public IActionResult PutProduct(int id, [FromBody] Product updatedProduct)
        {
            if (id != updatedProduct.Id)
            {
                return BadRequest(new { Message = "ID mismatch between route and body." });
            }

            var existingProduct = _products.FirstOrDefault(p => p.Id == id);
            if (existingProduct == null)
            {
                return NotFound(new { Message = $"Product with ID {id} not found." });
            }

            // Update the product properties
            existingProduct.Name = updatedProduct.Name;
            existingProduct.Price = updatedProduct.Price;
            existingProduct.Category = updatedProduct.Category;

            // In a real application, persist changes to the database here

            return NoContent();
        }

        // DELETE: api/products/{id}
        [HttpDelete("{id}")]
        public IActionResult DeleteProduct(int id)
        {
            var product = _products.FirstOrDefault(p => p.Id == id);
            if (product == null)
            {
                return NotFound(new { Message = $"Product with ID {id} not found." });
            }

            _products.Remove(product);

            // In a real application, remove the product from the database here

            return NoContent();
        }
    }
}
Code Explanations:

The above ProductsController demonstrates typical CRUD operations on a static list of Product objects. In a real-time application, these objects would likely be stored and retrieved from a database using Entity Framework Core or any other data-access technology like ADO.NET Core or Dapper Framework.

The [Route(“api/[controller]”)] attribute sets the base route to api/products based on the controller name. Now, let us understand each endpoint.

GET Methods:
  • Get All Products: [HttpGet]: Handles GET requests to api/products. Returns a list of all products.
  • Get Product by ID: [HttpGet(“{id}”)]: Handles GET requests to api/products/{id}. Searches for a product with the specified ID and returns it if found; otherwise, returns a 404 Not Found response.
POST Method:
  • [HttpPost]: Handles POST requests to api/products. It accepts a product object from the request body, assigns a new ID, adds it to the in-memory list, and returns a 201 Created response with the new product’s location.
PUT Method:
  • [HttpPut(“{id}”)]: Handles PUT requests to api/products/{id}. Validates that the ID in the route matches the ID in the request body. Updates the existing product if found; otherwise, returns a 404 Not Found response.
DELETE Method:
  1. [HttpDelete(“{id}”)]: Handles DELETE requests to api/products/{id}. Removes the product with the specified ID if it exists; otherwise, it returns a 404 Not Found response.
Testing the Products Controller APIs:

You can test the APIs in many ways, like using Postman, Fiddler, and Swagger. But .NET 8 provides the .http file, and using that .http file, we can also test the functionality. This .http file name will be the same name as your project name. My Project name is MyFirstWebAPIProject, so Visual Studio creates the MyFirstWebAPIProject.http file. So, open the .http file and copy and paste the following code. Please change the port number with the port number on which your application is running.

@MyFirstWebAPIProject_HostAddress = https://localhost:7113
### Get All Products
GET {{MyFirstWebAPIProject_HostAddress}}/api/products
Accept: application/json
###

### Get Product with ID 1
GET {{MyFirstWebAPIProject_HostAddress}}/api/products/1
Accept: application/json
###

### Create a New Product
POST {{MyFirstWebAPIProject_HostAddress}}/api/products
Content-Type: application/json
{
    "Name": "New Product",
    "Price": 39.99,
    "Category": "Books"
}
###

### Update Product with ID 1
PUT {{MyFirstWebAPIProject_HostAddress}}/api/products/1
Content-Type: application/json
{
    "Id": 1,
    "Name": "Updated Product",
    "Price": 49.99,
    "Category": "Electronics"
}
###

### Delete Product with ID 1
DELETE {{MyFirstWebAPIProject_HostAddress}}/api/products/1
###
Testing:

Before testing, ensure your API runs locally and listens on the correct port. Open the .http file in your IDE, and you should see “Send Request” links above each HTTP request. Click these links to execute the requests, and you’ll see the responses directly in your IDE, as shown in the below image.

Models in ASP.NET Core Web API Application

Notes:
  • Ensure that your API is running and accessible at the specified URL and port.
  • The Content-Type: application/json header in the requests tells the server that you’re sending JSON data. The Accept: application/json header tells the server that you want the response in JSON format.
  • The format of the JSON payloads in POST and PUT requests should match the expected format of your Product model.

Models in ASP.NET Core Web API define the structure of the data handled by the application. They ensure data integrity through validation, facilitate data transfer between client and server, and can be used with DTOs to optimize data exposure.

In the next article, I will discuss Routing in ASP.NET Core Web API Application. In this article, I try to explain Models in ASP.NET Core Web API Application. I hope you enjoy this article, “Models in ASP.NET Core Web API.”

2 thoughts on “Models in ASP.NET Core Web API”

  1. Actually the put method is not working . could you please look into it.
    Errornumber:Compiler Error CS0161

Leave a Reply

Your email address will not be published. Required fields are marked *