.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. OLanepiliA's avatar OLanepiliA says:

    This is very fascinating, You are an excessively professional blogger. I’ve joined your rss feed and sit up for seeking more of your fantastic post. Also, I’ve shared your web site in my social networks
    https://http-kra38.cc/

  2. chickenroad's avatar chickenroad says:

    Chicken Road strategyhttps://apkpure.com/p/app.chickenroad.game

  3. Timsothybioli's avatar Timsothybioli says:

    Its like you read my mind! You seem to know a lot about this, like you wrote the book in it or something. I think that you can do with some pics to drive the message home a little bit, but other than that, this is fantastic blog. An excellent read. I’ll certainly be back.
    https://http-kra38.cc/

  4. 462495 420710youre in point of fact a very good webmaster. The website loading velocity is remarkable. It seems that youre performing any distinctive trick. In addition, The contents are masterpiece. youve done a fantastic activity on this topic! 649443

  5. Stephenviaps's avatar Stephenviaps says:

    I used to be able to find good advice from your blog posts.

    Seattle airport transportation service

  6. Alton Tables's avatar Alton Tables says:

    Открыл альбом на Roads.ru — https://roads.ru/forum/gallery/album/176-dadonz_img/ — и подумал, что визуал можно использовать как вдохновение для тизеров под недвижку или тревел-офферы. Картинки = креативы.

  7. 422576 790242Fantastic post will likely be posting this on my weblog today keep up the good function. 677956

  8. Была идея, которую я не знал, как реализовать технически. На Буствин вход помогли не только с реализацией, но и с доработкой. Причём предложили улучшения, о которых я сам бы не подумал. Результат получился даже лучше, чем я ожидал.

  9. У меня был проект, который «висел» месяцами. Все откладывали, никто не брался по-нормальному. Решил попробовать Boostwin рабочее зеркало — и это было лучшее решение. С первого звонка — конкретика, сроки, действия. Сейчас проект не просто запущен, а уже приносит результат. Круто, когда работа движется!

  10. Benphymn's avatar Benphymn says:

    Хотите построить загородный дом своей мечты? Мы предлагаем профессиональное строительство домов, коттеджей и бань с гарантией качества. Работаем в Санкт-Петербурге и области, возводим объекты из кирпича, газоблоков, сибита, дерева и комбинированных материалов. Наша строительная компания учитывает все детали: от толщины стен до выбора отделочных материалов. Вы можете заказать строительство «под ключ» или отдельные виды работ — кладка стен https://builder-spb.ru/kamenschiki-kladka.html , устройство фундамента, перекрытий, кровли. Подробный прайс и расценки фиксируются в договоре, чтобы цена была прозрачной. Мы полагаем, что загородный дом должен быть надежным, долговечным и соответствовать уровню современного комфорта. Доверьте работу профессионалам, и уже этим летом сможете заехать в новый дом.

  11. Был обычный день, из тех, что тянутся медленно. Решил, что пора встряхнуться — и зашёл в казино, про которое недавно рассказывали друзья. Сначала просто развлекался, а потом внезапно сорвал сумму, которой хватило на вечер в баре и небольшую покупку для себя. Отличное чувство! https://boostwin-casino.com/

  12. 983134 544020really good put up, i surely really like this internet website, carry on it 872304

  13. av's avatar av says:

    419093 326904This Los angeles Weight Loss diet happens to be an low and flexible going on a diet application meant for typically trying to drop the weight as nicely within the have a a lot healthier lifetime. lose weight 132054

  14. 426830 100960Its a shame you dont have a donate button! Id without a doubt donate to this brilliant weblog! I suppose for now ill settle for book-marking and adding your RSS feed to my Google account. I appear forward to fresh updates and will share this blog with my Facebook group. Chat soon! 269470

  15. 323775 334190The electronic cigarette uses a battery and a small heating factor the vaporize the e-liquid. This vapor can then be inhaled and exhaled 966089

  16. Purple Urkle strain
    You always have good humor in your blogs. Keep going!

  17. Would you be fascinated by exchanging links?

  18. 367281 418693This web-site can be a walk-through rather than the information you wished about it and didnt know who need to. Glimpse here, and you will surely discover it. 675474

  19. Candy Jack strain
    Your consistency and creativity in blogging are impressive. Keep it up!

  20. Michaeldonee's avatar Michaeldonee says:

    поручень для лестницы металлические Перила для лестницы – это неотъемлемая часть конструкции, обеспечивающая безопасность и удобство использования. Они должны быть прочными, надежными и соответствовать требованиям безопасности. Важно учитывать высоту перил, расстояние между балясинами и удобство хвата. }

  21. Jamescug's avatar Jamescug says:

    школа музыки куркино Уроки вокала Куркино – это ваш путь к красивому и уверенному голосу. Наши преподаватели вокала помогут вам развить технику пения, расширить вокальный диапазон и научиться правильно дышать.

  22. Frankrinia's avatar Frankrinia says:

    оформление бровей севастополь Брови Севастополь – это не просто ухоженные дуги, это обрамление вашего взгляда, выражение индивидуальности и уверенности в себе. В современном мире, где каждая минута на счету, перманент Севастополь становится спасением для тех, кто ценит свое время и стремится всегда выглядеть безупречно. Забудьте о ежедневном макияже бровей!

  23. TimVon's avatar TimVon says:

    Предлагаем качественную ветошь обтирочную в наличии на складе в Санкт-Петербурге. Хлопчатобумажная, трикотажная, цветная и белая — под любые задачи. Подходит для предприятий, автосервисов, производств и клининга. Цена — от 125 руб/кг, при заказе от 300 кг — скидки. Ветошь отобрана https://vetosh-optom.ru , без фурнитуры и загрязнений, готова к применению. Отгружаем от 10 кг, работаем с физ. и юр. лицами. Возможна доставка по СПб и Ленобласти. Оформить заказ можно через сайт или по телефону.

  24. namayti57's avatar namayti57 says:

    630411 370398There is noticeably a good deal to know about this. I believe you made some nice points in capabilities also. 469945

  25. LewisGor's avatar LewisGor says:

    Wow that was odd. I just wrote an extremely long comment but after I clicked submit my comment didn’t appear. Grrrr… well I’m not writing all that over again. Anyway, just wanted to say excellent blog!
    казино либет

  26. Timsothybioli's avatar Timsothybioli says:

    Hi there to every one, since I am genuinely eager of reading this web site’s post to be updated daily. It includes nice data.
    сайт zooma casino

  27. LewisGor's avatar LewisGor says:

    Wonderful, what a web site it is! This web site provides useful data to us, keep it up.
    регистрация казино либет

  28. LhanepiliA's avatar LhanepiliA says:

    Hello I am so glad I found your site, I really found you by mistake, while I was researching on Digg for something else, Nonetheless I am here now and would just like to say thank you for a tremendous post and a all round interesting blog (I also love the theme/design), I don’t have time to read through it all at the minute but I have bookmarked it and also included your RSS feeds, so when I have time I will be back to read more, Please do keep up the fantastic work.
    официальный сайт cat casino

  29. IsmaelNiz's avatar IsmaelNiz says:

    Hi there everyone, it’s my first visit at this website, and article is genuinely fruitful in support of me, keep up posting these articles or reviews.
    cat casino

  30. LewisGor's avatar LewisGor says:

    Hello i am kavin, its my first time to commenting anyplace, when i read this paragraph i thought i could also make comment due to this brilliant paragraph.
    вход zooma casino

  31. ShanepiliA's avatar ShanepiliA says:

    Hi! Do you know if they make any plugins to safeguard against hackers? I’m kinda paranoid about losing everything I’ve worked hard on. Any suggestions?
    Comprare medicine online convenientemente

  32. 874893 601081Thanks for the information provided! I was researching for this post for a long time, but I was not able to see a dependable source. 442048

  33. Первая ставка — и азарт вспыхивает мгновенно. Если ищешь что-то настоящее, что держит от начала до конца — начни с бонусы от Vodka Casino. Интерфейс не важен, если внутри огонь. Слоты могут удивлять и затягивать. Промокоды придают игре вкус. Игры продуманы до деталей. Тут главное — динамика и отдача. Бонусы не просто на словах — они реально работают. Такие впечатления редко где получишь.

  34. GichardAmomi's avatar GichardAmomi says:

    Please let me know if you’re looking for a writer for your blog. You have some really great posts and I feel I would be a good asset. If you ever want to take some of the load off, I’d really like to write some articles for your blog in exchange for a link back to mine. Please send me an e-mail if interested. Many thanks!
    https://clients1.google.ro/url?sa=t&url=https://premierlimousineservice.net

  35. 288080 340452Naturally I like your web-site, even so you need to check the spelling on several of your posts. Several of them are rife with spelling troubles and I discover it very silly to inform you. On the other hand I will undoubtedly come again once more! 661159

  36. 473510 985759Precisely what I was searching for, thankyou for putting up. 268220

  37. ShanepiliA's avatar ShanepiliA says:

    Do you have any video of that? I’d like to find out more details.
    order vibramycin 100 mg pill

  38. Werazithype's avatar Werazithype says:

    Я всегда думал, что математика задачи — это скучно. Но здесь они поданы как логические задачки, и стало даже интересно. Некоторые решаю просто ради тренировки. Помогло прокачать мышление, особенно для ОГЭ — там ведь тоже много задач на логику.

  39. Fobertnap's avatar Fobertnap says:

    Escape the Limits – Explore Non GamStop Casinos!
    Tired of restrictions? Discover a world of unlimited gaming possibilities at our Non GamStop Casinos.

    What we offer:
    – Unrestricted access to top games
    – Generous welcome bonuses
    – Lightning-fast payouts
    – 24/7 customer support
    – Secure & fair gaming environment

    Join thousands of satisfied players who have already found their perfect gaming experience. No GamStop limitations mean endless fun and excitement!
    Claim your bonus now and start playing at the best Non GamStop Casinos today! ??
    https://vaishakbelle.com/review/1red-casino-2/
    #NonGamStopCasinos #OnlineGaming #CasinoBonus

  40. LewisGor's avatar LewisGor says:

    Hi there to every single one, it’s really a good for me to pay a quick visit this web site, it consists of precious Information.
    can you buy generic vermox without rx

  41. ShanepiliA's avatar ShanepiliA says:

    you are really a good webmaster. The site loading pace is amazing. It seems that you are doing any distinctive trick. In addition, The contents are masterwork. you have performed a magnificent process on this matter!
    spin city

Leave a Reply

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