Rest Api Designing Best Practices

There are some common practices one should take care of while designing REST APIs.

There is also a video version of this post.

rest_api_design_practices

1. Use descriptive names for resources

  • ❌ /api/getAllBooks
  • ❌ /api/retrieveBooks
  • ❌ /api/manageBooks
  • ❌ /api/process
  • ✅ /api/books

2. Use nouns not verbs

  • ❌ /api/mangage-books
  • ✅ /api/books

3. Use plural nouns

❌ Singular Nouns✅ Plural Nouns
/api/book/api/books
/api/movie/api/movies
/api/person/api/people
/api/customer/api/customers

4. Use hyphens (-) in url for better readabilty

  • ❌ /api/useraccounts
  • ✅ /api/user-accounts

5. Never use crud method names in url

HttpMethod❌❌❌✅✅✅
GET/api/books/GetAllBooks/api/books
GET/api/books/GetBookById/{id}/api/books/{id}
POST/api/books/CreateBook/api/books
PUT/api/books/UpdateBook/{id}/api/books/{id}
DELETE/api/books/DeleteBook/{id}/api/books/{id}

6. Use http method properly

HttpMethodEndpointDescription
GET/api/booksIndicates a get resources
GET/api/books/{id}Indicates a get resource with id
POST/api/booksIndicates creating a resource
PUT/api/books/{id}Indicates updating a resource
DELETE/api/books/{id}Indicates deleting a resource

7. Use Http StatusCodes Correctly

These are the most commonly used status codes.

[Read More]

Covering Indexes In Sql Server

Table structure and total records

Let’s look at our table structure as shown in the left panel of the picture

book_structure

Note: There is a non-clustered index on the Title column of the Book table, which has a total of 1 million records.

select
  Id,
  Title,
  Author,
  Price
from Book where title='The Divine Comedy'

query_execution_plan

As you have noticed in the execution plan, there is a key lookup. Since index is only available for the Title column, Title is retrieved from the non-clustered index. However, other columns like Id, Author and Price are not present in the non-clustered index, so they will be retrieved from the clustered index (the Book table). This results in an additional key lookup step and may decrease the performance. It’s like, you are looking for records in two places (non clustered index and clustered index).

[Read More]
sql 

Dotnet Service Lifetime : AddTransient(), AddScoped(), AddSingleton()

AddTransient() AddScoped() AddSingleton() in dotnet core

Example Setup

I am using a MinimalApi application. Create a new one if you need.

dotnet new webapi -n DITest

Open it in a IDE or editor of your choice.

public interface IMyService
{
    Guid InstanceId { get; }
}

public class MyService : IMyService
{
    public Guid InstanceId { get; }

    public MyService()
    {
        InstanceId = Guid.NewGuid();
        // We are logging in the constructor, so that we get notified whenever the instance is created
        Console.WriteLine($"==> Service created with InstanceId: {InstanceId}");
    }
}

IMyService have a read-only property named InstanceId of type Guid, which is set from the constructor. We are logging inside the constructor, so that we can get notified whenever the new instance is created.

[Read More]

LINQ: Zip() operator

zip() operator in

There is also a video version of this tutorial.

Let’s understand it with example.

int[] nums1 = [1, 2, 3, 4];
int[] nums2 = [3, 4, 5, 6];

IEnumerable<int>? product = nums1.Zip(nums2, (n1, n2) => n1 * n2);

Console.WriteLine(string.Join(", ", product));  // 3, 8, 15, 24

Let’s break it down:

IEnumerable<int>? product = nums1.Zip(nums2, (n1, n2) => n1 * n2);

It takes nums1[i] and nums2[i], evaluates it (nums1[0]*nums2[0]) and returns it. Here i is the index of the array. For example.

[Read More]

SingleAsync vs SingleOrDefaultAync vs FirstAsync vs FirstOrDefaultAsync vs FindAync

SingleAsync() vs SingleOrDefaultAync() vs FirstAsync() vs FirstOrDefaultAsync() vs FindAync() in c#

I don’t think there is any need of introduction. Let’s jump to the code section. We coders understand with code more. Let’s understand the concept then you don’t need to remember any definition.

This is the recordset against which I am running queries.

IdFirstNameLastName
1JohnDoe
2RavindraDevrani
3MohanSingh
20MaheshSoni
21JohnSnow

First and foremost let’s say we need a record with LastName=”Doe”.

[Read More]

Database Firsts Approach In EF Core

Database first approach with DotNet Core

I have used database first approach in the .NET Framework 4.X. But It is the first time I am trying to use Db First approach in the .NET Core (I am using .net 9). Microsoft refers it ‘Scaffolding (Reverse Engineering)’. Personally I prefer Dapper for DB First approach. May be you have an existing database and you want to use it with ENTITY FRAMEWORK, then this approach might be helpful. I am playing around it and documenting it and sharing that journey with you. Let’s see what it offers.

[Read More]

Curious Case of LINQ Group By

curious case of linq group by

Schema

  • Department (DepartmentId, Name)
  • Employee (EmployeeId, Name, DepartmentId)

Result set I need

Show all departments with total number of employees. Do not skip the departments which have 0 employees. As shown below:

DepartmentIdNameTotalEmployees1Engineering22Marketing13HR0

I have applied various queries and checked their equivalent sql.

1. Straightforward but skips the department which has no employees

This query does not meet my requirement. It would be a good choice if I don’t need departments without any employees.

[Read More]

LINQ: SelectMany()

select many operator in linq

NOTE: You can find the source code here.

Schema Overview

// Department
public class Department
{
    public int DepartmentId { get; set; }
    public string Name { get; set; } = string.Empty;

    public ICollection<Employee> Employees { get; set; } = [];
}

// Employee

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; } = string.Empty;

    public int DepartmentId { get; set; }

    public Department Department { get; set; } = null!;

    public ICollection<EmployeeSkill> EmployeeSkills { get; set; } = [];
}

// Skills

public class Skill
{
    public int SkillId { get; set; }
    public string Name { get; set; } = string.Empty;

    public ICollection<EmployeeSkill> EmployeeSkills { get; set; } = [];
}

// EmployeeSkills (Junction table)

public class EmployeeSkill
{
    public int EmployeeId { get; set; }
    public int SkillId { get; set; }

    public Employee Employee { get; set; } = null!;
    public Skill Skill { get; set; } = null!;
}

In simpler terms:

[Read More]

What Makes My Query Non Sargable?

Sargable queries

A query is SARGable (Search ARGument able) if a database engine can take advantage of index.

What makes a query non SARGable?

These are the few factors that makes a query non sargable.

1. Put a column inside a function in the where clause.

select
 s.SalesOrderID,
 s.SalesPersonID,
 s.OrderDate,
 s.SalesOrderNumber
from Sales.SalesOrderHeader s
where YEAR(s.OrderDate) = 2011; -- Row Retrieved: 1607 and Row read : 31465

Note: I have created covering index on the OrderDate:

[Read More]
sql 

SQL Server: Table Scan, Clustured Index Scan, Index Seek, RID Lookup, Key Lookup

SQL SERVER: Table scan, clustered index scan, index seek, RID lookup, Key lookup

Initially, it was not intended to be an article. I was tinkering around sql and documenting few things, then I thought, it could turnout to a nice article. I have wrote lots of article and created lots of videos on c#, .net core and angular. But it is my first article on the SQL.

In this blog post, we are going to explore few terms of execution plan, like table scan, clustered index scan, index seek, RID lookup and key lookup.

[Read More]
sql