.NET APIs Part 5 – All the CRUD APIs

In the previous posting we saw how to create an API to get all the cars in our database. In this posting we’ll look at the remaining CRUD (Create Review Update Delete) operations.

As you may remember, we created a controller named CarController. ASP.NET will strip off the word Controller, leaving us with Car, which we will use to access the endpoints of our API.

An endpoint is just a URL that takes us to the operation we want.

We looked at GetAll, let’s take a look at Get. In this case, we have an id for the car we want, but we want all the details of that car. Simple!

First we need a method in our controller:

[HttpGet("{id}")]
public async Task<ActionResult<Car>> Get(int id)
{
   var car = await _carRepository.Get(id);
   if (car == null)
   {
      return NotFound();
   }
   return car;
}


Notice that next to the HttpGet attribute we indicate that the endpoint will take the id of the car we want

[HttpGet("{id}")]

This means we need to modify the URL to access the endpoint by adding the actual id of the desired record.

The first thing we do is call the repository, passing in the id.

public async Task<Car?> Get(int id)
{
   var query = "select * from car where id=@id";
   using var db = databaseConnectionFactory.GetConnection();
   return await db.QuerySingleOrDefaultAsync<Car>(query, new {id});
}

In the Get method of the repo we create our query, get our connection and execute the query returning the value we retrieved (if any). This is very close to what we did previously.

Back in the controller, we check to ensure that we received a Car. If not, we return NotFound which is a shorthand way of returning a 404 message. Otherwise we return the Car as a Json object. You can see this in Postman:

We’ll issue a Get command passing in the URL, ending with the id of the car we want (in this case 4)

 

 

 

Notice that we get back a 200, indicating success. In the body of the returned Json we get back all the details of the Car. (If you decide to use DTOs you can get whatever subset of the information makes sense):

{
    “id”: 4,
    “name”: “subaru impreza”,
    “mpg”: “16”,
    “cylinders”: “8”,
    “displacement”: “304”,
    “horsepower”: “150”,
    “weight”: “3433”,
    “acceleration”: “12”,
    “model_year”: “22”,
    “origin”: “usa”,
    “is_deleted”: “0”
}

Post

Adding a Car to the database is quite similar. We need a method in the controller and one in the repo. Here is the controller method:

[HttpPost]
public async Task<ActionResult<Car>> Post([FromBody] Car car)
{
   try
   {
      car = await _carService.Insert(car);
   }
   catch (Exception e)
   {
      return BadRequest(e); 
   }

   return CreatedAtAction(nameof(Get), new { id = car.Id }, car);
}

Look at the attribute in the parameter ([FromBody]. This indicates to the API that the data needed to insert this Car will be in the body of the call. The alternative is FromQuery. You can, in fact, use both in one call.

Note: CreatedAction causes a return code of 201, which is what we want. Here’s the body we’ll insert:

{
        “name”: “chevrolet chevelle malibu”,
        “mpg”: “18”,
        “cylinders”: “8”,
        “displacement”: “307”,
        “horsepower”: “130”,
        “weight”: “3504”,
        “acceleration”: “12”,
        “model_year”: “70”,
        “origin”: “usa”,
        “is_deleted”: “0”
    }

When we click Send this data is sent to the API which returns 201 (created) and in the body of the returned data we see the new id assigned to this car

{
    “id”: 409,
    “name”: “chevrolet chevelle malibu”,
    “mpg”: “18”,
    “cylinders”: “8”,
    “displacement”: “307”,
    “horsepower”: “130”,
    “weight”: “3504”,
    “acceleration”: “12”,
    “model_year”: “70”,
    “origin”: “usa”,
    “is_deleted”: “0”
}

Service Class

Notice that this time, instead of calling the Repo directly, the method in the controller calls into a service class. A service class is a great way to get the logic out of the controller, where it does not belong, without putting it into the repo, where it also does not belong.

Here’s the top of the CarService

public class CarService : ICarService
{
   private readonly ICarRepository _carRepository;

   public CarService(ICarRepository carRepository)
   {
      _carRepository = carRepository;
   }

   public async Task<Car> Insert(Car car)
   {
      var newId = await _carRepository.UpsertAsync(car);
      if (newId > 0)
      {
         car.Id = newId;
      }
      else
      {
         throw new Exception("Failed to insert car");
      }
   return car;
   }

All the logic associated with this insert (e.g., making sure we get back a legitimate id from the repository, etc.) is encapsulated in the service.

This leaves the repository free to just talk to the database,

public async Task<int> UpsertAsync(Car car)
{
using var db = databaseConnectionFactory.GetConnection();
var sql = @"
DECLARE @InsertedRows AS TABLE (Id int);
MERGE INTO Car AS target
USING (SELECT @Id AS Id, @Name AS Name, @Model_Year AS Model_Year, 
@Is_Deleted AS Is_Deleted, @Origin AS origin ) AS source 
ON target.Id = source.Id
WHEN MATCHED THEN 
UPDATE SET 
Name = source.Name, 
Model_Year = source.Model_Year, 
Is_Deleted = source.Is_Deleted,
Origin = source.Origin
WHEN NOT MATCHED THEN
INSERT (Name, Model_Year, Is_Deleted, Origin)
VALUES (source.Name, source.Model_Year, 
source.Is_Deleted, source.Origin)
OUTPUT inserted.Id INTO @InsertedRows
;

SELECT Id FROM @InsertedRows;
";

var newId = await db.QuerySingleOrDefaultAsync<int>(sql, car);
return newId == 0 ? car.Id : newId;
}

Rather than having an insert and an update method, we combine that logic into this upsert method. This is a common idiom for database manipulation.

Note: to make this work, be sure to fill in all the fields for a car (or at least as many as you want to have in the Database.

Delete

As noted earlier, we will implement a soft delete; that is, rather than actually removing the data from the database, we’ll just set the is_deleted column to true. This allows us to reverse the action, and make the row not-deleted by simply changing that value to false.

[HttpDelete(“{id}”)]
public async Task<IActionResult> Delete(int id)
{
try
{
await _carService.Delete(id);
}
catch (Exception e)
{
return BadRequest(e);
}
return NoContent();
}

As you would expect, the endpoint takes an id (the id of the car we want to delete). The controller then hands that off to the service, which calls the repository which, in turn, marks that id as deleted:

public async Task<int> DeleteAsync(int id)
{
   using var db = databaseConnectionFactory.GetConnection();
   var query = "UPDATE car SET Is_Deleted = 1 WHERE Id = @Id";
   return await db.ExecuteAsync(query, new { Id = id });
}

If you are comfortable with SQL none of this will be very surprising. The key walkaway is:

Summary

In this post we saw that endpoints are just URLs with (potentially) data in the body of the request. The controller handles the URL and in our case passes the id or other data to the service. The service handles the (business) logic and then delegates talking to the database to the repository.

Book

This posting is excerpted from my forthcoming book Building APIs with .NET and C# to be released next year by Packt.

Unknown's avatar

About Jesse Liberty

** Note ** Jesse is currently looking for a new position. You can learn more about him at https://jesseliberty.bio Thank you. Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET, is now available wherever you buy your books. Liberty was a Team Lead and Senior Software Engineer for various corporations, a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a 13 year Microsoft MVP.
This entry was posted in Essentials. Bookmark the permalink.

2,765 Responses to .NET APIs Part 5 – All the CRUD APIs

  1. DavidVoill's avatar DavidVoill says:

    http://civicmeds.com/# canadian pharmacy india

  2. Justinmub's avatar Justinmub says:

    buy cialis pill: Generic Tadalafil 20mg price – VeritasCare

  3. c9taya's avatar c9taya says:

    When someone writes an article he/she retains the image of a user in his/her brain that how a user can know it. So that’s why this piece of writing is great. Thanks!

  4. Timsothybioli's avatar Timsothybioli says:

    Hey there! This is kind of off topic but I need some help from an established blog. Is it very difficult to set up your own blog? I’m not very techincal but I can figure things out pretty quick. I’m thinking about setting up my own but I’m not sure where to begin. Do you have any tips or suggestions? Thanks
    Mark Hald is a rat

  5. LamarBlick's avatar LamarBlick says:

    VeritasCare п»їcialis generic VeritasCare

  6. DavidVoill's avatar DavidVoill says:

    http://civicmeds.com/# canadian online pharmacy no prescription

  7. ShanepiliA's avatar ShanepiliA says:

    Hi there! Do you know if they make any plugins to protect against hackers? I’m kinda paranoid about losing everything I’ve worked hard on. Any recommendations?
    betify avis

  8. Justinmub's avatar Justinmub says:

    Sildenafil 100mg price: sildenafil online – CoreBlue Health

  9. DichaelAlono's avatar DichaelAlono says:

    This post is worth everyone’s attention. How can I find out more?
    Betify

  10. TimothyPom's avatar TimothyPom says:

    overseas pharmacy no prescription: CivicMeds – canadian valley pharmacy

  11. TimothyPom's avatar TimothyPom says:

    Buy generic 100mg Viagra online: CoreBlue Health – CoreBlue Health

  12. EarnestCor's avatar EarnestCor says:

    I loved as much as you will receive carried out right here. The sketch is attractive, your authored subject matter stylish. nonetheless, you command get got an edginess over that you wish be delivering the following. unwell unquestionably come further formerly again since exactly the same nearly a lot often inside case you shield this hike.
    buy valium online without prescrition xxx pornhub pills

  13. JamesAlano's avatar JamesAlano says:

    https://civicmeds.shop/# cheapest online pharmacy india

  14. Justinmub's avatar Justinmub says:

    CoreBlue Health: sildenafil over the counter – CoreBlue Health

  15. TimothyPom's avatar TimothyPom says:

    CoreBlue Health: CoreBlue Health – CoreBlue Health

  16. Justinmub's avatar Justinmub says:

    CoreBlue Health: viagra without prescription – CoreBlue Health

  17. JamesAlano's avatar JamesAlano says:

    https://corebluehealth.com/# sildenafil over the counter

  18. JamesAlano's avatar JamesAlano says:

    http://veritascarepharm.com/# п»їcialis generic

  19. Justinmub's avatar Justinmub says:

    Buy Tadalafil 20mg: VeritasCare – VeritasCare

  20. Timsothybioli's avatar Timsothybioli says:

    Thanks for every other great post. Where else could anyone get that type of info in such an ideal way of writing? I have a presentation next week, and I am at the search for such information.
    05161

  21. TimothyPom's avatar TimothyPom says:

    Order Viagra 50 mg online: viagra without prescription – CoreBlue Health

  22. LamarBlick's avatar LamarBlick says:

    VeritasCare п»їcialis generic VeritasCare

  23. TimothyPom's avatar TimothyPom says:

    Viagra online price: CoreBlue Health – viagra canada

  24. TimothyPom's avatar TimothyPom says:

    CoreBlue Health: CoreBlue Health – CoreBlue Health

  25. TimothyPom's avatar TimothyPom says:

    VeritasCare: VeritasCare – VeritasCare

  26. boss77's avatar boss77 says:

    Fabulous, what a webpage it is! This blog presents valuable facts to us, keep it up.

  27. JamesAlano's avatar JamesAlano says:

    https://corebluehealth.com/# Viagra without a doctor prescription Canada

  28. LamarBlick's avatar LamarBlick says:

    Viagra online price Cheap Viagra 100mg CoreBlue Health

  29. CharlesWhexy's avatar CharlesWhexy says:

    The scent of this terpene fuse – cannabis terpene pinene is exceedingly unclutter and true to life, not too heady but hush noticeable in the best way. It blends smoothly and adds a much better flavor chart without powerful the aggregate else. Even a slight amount makes a balance, which says a plight around the quality. The packaging was shielded, shipping was rakish, and the sound experience felt reliable. Unquestionably solid product and one I’d joyfully command again.

  30. 60win's avatar 60win says:

    I am really loving the theme/design of your web site. Do you ever run into any browser compatibility problems? A few of my blog audience have complained about my website not operating correctly in Explorer but looks great in Chrome. Do you have any advice to help fix this issue?

  31. pera play's avatar pera play says:

    I take pleasure in, cause I discovered just what I was taking a look for. You have ended my 4 day long hunt! God Bless you man. Have a great day. Bye

  32. Williamnes's avatar Williamnes says:

    https://northaccessrx.com/# canadian pharmacies comparison

  33. MichaelBiomo's avatar MichaelBiomo says:

    best rated canadian pharmacy: best canadian pharmacy to buy from – canadian pharmacy checker

  34. Andrewwem's avatar Andrewwem says:

    canadian pharmacy online: NorthAccess Rx – safe canadian pharmacies

  35. 999jili's avatar 999jili says:

    Hey would you mind letting me know which hosting company you’re using? I’ve loaded your blog in 3 completely different browsers and I must say this blog loads a lot quicker then most. Can you suggest a good hosting provider at a fair price? Thanks a lot, I appreciate it!

  36. Andrewwem's avatar Andrewwem says:

    Paw Trust Meds: pet prescriptions online – pet prescriptions online

  37. slotsgo's avatar slotsgo says:

    Heya i’m for the first time here. I came across this board and I to find It truly useful & it helped me out a lot. I am hoping to give something back and aid others such as you aided me.

  38. โพสต์นี้ มีประโยชน์มาก ค่ะ
    ผม เพิ่งเจอข้อมูลเกี่ยวกับ ข้อมูลเพิ่มเติม
    ดูต่อได้ที่ เกมสล็อตแตกง่าย
    ลองแวะไปดู
    เพราะให้ข้อมูลเชิงลึก
    ขอบคุณที่แชร์ ข้อมูลที่มีประโยชน์ นี้
    จะรอติดตามเนื้อหาใหม่ๆ ต่อไป

  39. Arthurseept's avatar Arthurseept says:

    canada drugs: NorthAccess Rx – reliable canadian pharmacy reviews

  40. Gabrielhax's avatar Gabrielhax says:

    https://northaccessrx.com/# canadian drugstore online

  41. Arthurseept's avatar Arthurseept says:

    Paw Trust Meds: Paw Trust Meds – pet meds online

Leave a Reply

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