Build a web API with C# & ASP NET Core 7.0

Photo by Andrew Neel on Unsplash

Build a web API with C# & ASP NET Core 7.0

Learn how to create a web API with C# and ASP NET Core 7.0

This is a repost from my origin article post on my blog: Unit Coding please go and check it out! โœจ

Hello, guys today we will be building a web API with C# and ASP NET Core 7.0 which is the latest version as of now while I'm writing this article. What will our API be about? well, it will be a web API for a blog, we will be able to publish, edit, delete, and get all the posts that we have stored in our database.

Blogs have a soft spot in my heart when I was younger I always wanted to be part of a blog but since I feared that what I would write would not be read by anybody or that criticism would hit hard on my low confidence at that time so for that reason this kind of projects bring me joy and that's precisely the reason why I chose a blog functionality for this API hoping you enjoy it as much as I will, so now without further ado let's begin ๐Ÿ’ช๐Ÿพ

Create a new web API application

Let's begin by creating a new asp net core web API with the help of the dotnet cli.

dotnet new webapi -o BlogAPI

Something you should consider is that creating the web api this way will set up swagger by default so if you are using Visual Studio make sure that you mark the "Enable OpenAPI support" checkbox so you can test your application much easier.

Now let's proceed to delete the boilerplate code that dotnet web API ships with, delete the WeatherForcastController.cs file inside controllers folder and also WeatherForecast.cs model class.

Let's add our blog post model Now that we have cleaned our API from the unnecessary code let's create a folder called Models where we will create the models for blog posts. So this is how the Post model should end up looking.

public class Post
{
    public int Id { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

Once we have our model in place we may proceed to create the PostsController.

Create a Controller for our Posts Inside the Controllers folder create a new PostsControllers.cs file and add the initial code as follows.

using AspNetCoreWebApi.Models;
using Microsoft.AspNetCore.Mvc;

namespace AspNetCoreWebApi.Controllers
{
    [ApiController]
    [Route("api/post")]
    public class PostsController : ControllerBase
    {
        private static List<Post> posts = new List<Post>{
            new Post{Id = 1, Title = "My first Post", Author = "Oscar Montenegro", Body = "Hello guys, this is my first post!"},
            new Post{Id = 2, Title = "My second Post", Author = "Oscar Montenegro", Body = "Hello guys, this is my second post!"}
        };

        public PostsController()
        {

        }

    }
}

The PostsController class in inheriting from ControllerBase and using the [ApiController] attribute and we define the route with the Route attribute defining the base route of this controller.

Inside the PostsController we have a list of posts, this will serve as our in-memory database later we will use SQL Server.

And last but not least we added the PostsController constructor as we will need it in a minute.

Get your posts

Now we can start getting the posts from our in-memory database (list). We can achieve this by adding a get method in our controller.

[HttpGet]
public IActionResult GetPost()
{
    return Ok(posts);
}

[HttpGet("{id:int}")]
public IActionResult GetPost(int id)
{
    var post = posts.Find(x => x.Id == id);
    return Ok(post);
}

๐Ÿ’ก Both methods have an HttpGet attribute above them that is to tell the routing engine that both methods support Http Get method. The first method returns all the existing posts in our database with a status code of 200 (ok) which means that the response is successful.

The second method accepts an id parameter because we will just get one post and we will look for it using the id, also if you noticed within the HttpGet attribute tag above the method we are passing the id and saying that it will be an int. We declare a post variable

Adding a new post

[HttpPost]
public IActionResult CreatePost(Post post)
{
    posts.Add(post);
    return CreatedAtAction(nameof(GetPost), new {id = post.Id}, null);
}

For this CreatePost method, we use the HttpPost attribute as we will be posting new items(blog posts) whit it. The code is pretty straightforward forward we add a new post to the posts list and then return the location of the newly created resource(post).

๐Ÿ’ก The CreatedAtActionmethod returns the location of the newly created resource and it accepts three parameters:

  • actionName represents the name of the action that's used for generating the location URL.

  • routeValues is an object that contains all the parameters of the action.

  • value is an object that represents the content of the response.

Editing a post

[HttpPut]
public IActionResult EditPost(int id)
{
    var post = posts.Find(x => x.Id == id);
    post.Body = "Hello guys, this is my second post";

    return NoContent();
}

This editing method will have an HttpPut attribute and we will pass the post id as a parameter. We use the Find method against the posts list to look for a single post with the exact Id that we provided, after this, we update the body of the post and return NoContent HTTP status code.

Deleting a post

[HttpDelete("{id:int}")]
public IActionResult DeletePost(int id)
{
    var post = posts.Find(x => x.Id == id);
    posts.Remove(post);

    return NoContent();
}

For this post, we use the HttpDelete attribute and we pass the id as with the Get method. As in the previous methods, we look for the post we want to delete, remove it from the list, and return a NoContent HTTP status code.

Testing the API with the In-Memory database

Now you are ready to test the API in its current state. To test it you can use you swagger enpoints or a tool like Postman to make the web API calls. If you are not sure how to call it you should open a new request on postman, set it to the type of request you want to make(get, post, put, delete), and then pass the URL for example localhost:5095/api/post calling this address using a get request will return all the existing posts.

So now that you have tested the API you must realize that we can manipulate the data but it will not persist, by this, we mean that once your application stops all the changes will be undone and the only way to store all changes is to use a database so there's where we are heading now.

Adding a real database

Let's begin by adding a connection string in the appsettings.json file.

"ConnectionStrings": {
    "DbConnection": "Server=DESKTOP-5KN3GBB;Database=BlogDb;Trusted_Connection=True;Integrated Security=true;TrustServerCertificate=true"
  }

Now install the following NuGet packages using the following dotnet cli commands:

dotnet add package Microsoft.EntityFrameworkCore.Core

dotnet add package Microsoft.EntityFrameworkCore.SqlServer

dotnet add package Microsoft.EntityFrameworkCore.Tools

Add a DbContext class

Create a Data folder and inside it create a class called BlogDbContext and add the following code.

public class BlogDbContext : DbContext
{
    public BlogDbContext(DbContextOptions<BlogDbContext> options) : base(options)
    {

    }

    public DbSet<Post> Posts { get; set; }
}

We make BlogDbContext inherit from DbContext and inside the constructor, we call the base constructor passing the options and we create a DbSet for our posts, this is to create a SQL table to store our blog posts.

Register the DbContext service

In our Program.cs register the DbContext to use SQL Server with the configuration that we already added.

builder.Services.AddDbContext<BlogDbContext>(options =>
{                options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnection"));
});

Now run the following dotnet cli commands:

dotnet ef migrations add "Initial Migration"

dotnet ef database update

with these commands, you will create the database with a table for the Posts and now we can start modifying the controller class to use the DbContext to call the database and improve our web API to its final form.

Using the DbContext in our PostsController class

Let's update all our CRUD methods to use the BlogDbContext class to retrieve, update and delete posts from the database. We have to update the PostsController constructor to inject the BlogDbContext so that we can use it to communicate with the database.

private readonly BlogDbContext context;

public PostsController(BlogDbContext context)
{
    this.context = context;
}

Get methods

Starting with both get methods they will almost have no change

[HttpGet]
public IActionResult GetPost()
{
    var posts = context.Posts.ToList();
    return Ok(posts);
}

[HttpGet("{id:int}")]
public IActionResult GetPost(int id)
{
    var post = context.Posts.Find(id);
    return Ok(post);
}

In the first get method we just call the context field and call the posts collection to finally call the ToList() function and get all the posts.

For the single get method, we will call to context, then to the posts collection, and finally, call the Find method and pass the blog id as a parameter.

Post method

[HttpPost]
public IActionResult CreatePost(Post post)
{
    context.Add(post);
    context.SaveChanges();

    return CreatedAtAction(nameof(GetPost), new {id = post.Id}, null);
}

What will change in this method is that we will call the context Add method and pass the post as a parameter then after this save the changes on the database with the SaveChanges method and the return method are the same as before.

Edit method

[HttpPut]
public IActionResult EditPost(int id, [FromBody]Post post)
{
    var postToEdit = context.Posts.Find(id);
    postToEdit.Title = post.Title;
    postToEdit.Body = post.Body;
    postToEdit.Author = post.Author;

    context.SaveChanges();

    return NoContent();
}

Here we see a lot of changes. We now pass the post as a parameter and use the [FromBody] attribute so that the post data gets taken from the body of the request. We look for the post and update all its parameters with the value from the post that is passed from the body, then we save the changes and return NoContent.

Delete Method

[HttpDelete("{id:int}")]
public IActionResult DeletePost(int id)
{
    var post = context.Posts.Find(id);
    context.Posts.Remove(post);
    context.SaveChanges();

    return NoContent();
}

After looking for the post to delete we call the Remove method of the context class and save the changes to en returning no content and that's it for this method.

And that's it!

Now you can test your fully functional web API with your database and you will be amazed by the result. You can read the data from the database in real-time, you can look for a specific post, update it, create a new one, or delete as many posts as you want!

This is it for now I did not use any advanced techniques like repository patter or mappers as this tutorial is intended for complete beginners, also if you want to follow this tutorial using PostgreSQL you can do it by checking my article on Connecting C# to PostgreSQL it's almost all the same except to the database configuration and some NuGet packages that you have to download but the code in the controller remains untouched.

I feel highly encouraged to keep writing on web API development as is my specialty and what I've been working on almost since I had my first job in software development. So there's a big chance that I will continue using this blog API as an example in future articles.

Consider supporting me ๐Ÿ™๐Ÿพ

If you enjoyed this article please consider supporting me by subscribing to my blog Unit Coding or my youtube channel which has the same name. I will continue writing and uploading new content on Web Development and Software Engineering and also really cool projects so that you can continue learning more. Thanks for reading my article and I wish you the best and all success on your learning journey thank you for allowing me on being part of it. Thanks and see you soon!

Did you find this article valuable?

Support Oscar Montenegro ๐Ÿง™๐Ÿพโ€โ™‚๏ธ๐ŸŒŸ by becoming a sponsor. Any amount is appreciated!

ย