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):
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:
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
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.




















http://corevitalpharmacy.com/# CoreVital Pharmacy
I’m gone to inform my little brother, that he should also pay a visit this web site on regular basis to take updated from newest news.
Cheap Sildenafil 100mg: cheapest viagra – NovaMen Pharmacy
ed online pharmacy: erectile dysfunction meds online – best online ed pills
https://primelinepharmacy.shop/# cheap erection pills
https://corevitalpharmacy.com/# CoreVital Pharmacy
discount ed pills: ed pills pharmacy – cheap ed pills online
https://primelinepharmacy.com/# ed pills for sale
http://corevitalpharmacy.com/# CoreVital Pharmacy
NovaMen Pharmacy: cheap viagra – Viagra Tablet price
http://corevitalpharmacy.com/# Generic Cialis without a doctor prescription
Asking questions are truly fastidious thing if you are not understanding something entirely, however this piece of writing gives pleasant understanding even.
Палаточный кемпинг хутор Каменный стол — сочетание природы, простора и свободы. Локация у озера подходит для купания, прогулок и дружеских встреч. Территория организована так, чтобы отдых оставался комфортным и спокойным. Живописные пейзажи, лес и вода формируют атмосферу настоящего загородного отдыха. Кемпинг выбирают те, кто ценит тишину, чистый воздух и возможность провести время активно или размеренно — в зависимости от настроения.
Generic Tadalafil 20mg price: п»їcialis generic – CoreVital Pharmacy
CoreVital Pharmacy: п»їcialis generic – CoreVital Pharmacy
low cost ed meds: ed pills pharmacy – ed online pharmacy
https://novamenpharmacy.com/# generic sildenafil
order viagra: viagra without prescription – buy Viagra online
online pharmacy india: TrustRx India – india online pharmacy
legit online pharmacy: MedBridge Pharmacy – rate online pharmacies
I am in fact delighted to glance at this webpage posts which contains lots of useful data, thanks for providing such information.
https://medbridgepharmacy.com/# MedBridge Pharmacy
https://medicobridgerx.shop/# MedicoBridge RX
https://medbridgepharmacy.shop/# us pharmacy
MedicoBridge RX: MedicoBridge RX – mexican farmacia
india pharmacy mail order: TrustRx India – online shopping pharmacy india
https://medbridgepharmacy.shop/# pharmacy discount coupons
MedBridge Pharmacy: 24 hour pharmacy – reputable online pharmacy no prescription
indianpharmacy com: Online medicine order – india pharmacy mail order
mexipharmacy reviews: farmacia mexicana en linea – mexican pharmacy online
MedBridge Pharmacy: legal online pharmacies in the us – MedBridge Pharmacy
https://medbridgepharmacy.shop/# mexican pharmacy
MedicoBridge RX: reputable mexican pharmacy – mexico pharmacy
MedBridge Pharmacy: online pharmacy store – MedBridge Pharmacy
MedicoBridge RX: MedicoBridge RX – MedicoBridge RX
MedBridge Pharmacy: MedBridge Pharmacy – MedBridge Pharmacy
I was recommended this blog by my cousin. I’m not sure whether this post is written by him as nobody else know such detailed about my problem. You are incredible! Thanks!
bet7k – https://www.bet7k-br.com
п»їlegitimate online pharmacies india: TrustRx India – indian pharmacy
MedBridge Pharmacy: MedBridge Pharmacy – global pharmacy
MedBridge Pharmacy: prices pharmacy – canada pharmacy online legit
MedicoBridge RX: MedicoBridge RX – MedicoBridge RX
MedicoBridge RX: mexico pharmacy list – order medication from mexico
Asking questions are actually nice thing if you are not understanding something completely, however this post provides good understanding even.
https://happypawspharmacy.shop/# pet antibiotics and care
HappyPaws Pharmacy discount pet meds pet antibiotics and care
True Health Pharm: True Health Pharm – True Health Pharm
References:
Steroid basic structure
References:
http://rito.synology.me:3000/martycarrell22
http://truehealthpharm.com/# True Health Pharm
canada drugs online review: VitalCore Pharmacy – pharmacy website india