Programming

CRUD operations using .Net Core Web API and Swagger

Gautam Gautam Donate Sep 25, 2019 · 20 mins read
CRUD operations using .Net Core Web API and Swagger

 

 

Share

.Net Core is been improving since from its first release on November 12, 2014. The latest version of .Net Core is .Net Core 3.0 its still in Preview version, however you can try it to check out its cool features, you can download it from here. In this article, I'm gonna use .Net Core Web API to handle all the client's requests and perform a simple CRUD (Create Read Update Delete) operations. Lets get started...

To know more about the .NET core web api, read this article. I'm gonna break down into several steps for better understanding :)

Step 1 - Initial Follow ups

Open Visual Studio, I recommend visual studio version 2017 or 2019, since it has better intellinse and .net core support, create a new project. Click on File → New → Project, select Visual C# → .Net Core → .Net Core Web Application, then provide a name and location of your project, in my case i've named as - "CRUDApi" then click OK

Step 1 - CRUD API

Now from the Project Template Window, select API and in the Authentication Section, leave it to default i.e. No Authentication, make sure you've checked the "Configure for HTTPS" checkbox then press OK. Let the IDE do its initial stuffs, this will load some project nuget packages and requirements for your projects, give it some time :) If anything goes wrong with the above steps follow the screenshots.

Step 2: Coding, mind testing

By default, your project will contain controller as values, we don't need that unless you want to test it, remove the unused code and files from your project, clean is better. Add new folder named "Data" in your root folder, and then add new class file name it as "Students" and add the following properties for Students, use the following code - 

public class Students
{
        [ScaffoldColumn(false)]
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Grade { get; set; }
        public DateTime DateRegistered { get; set; }
        public bool isVerified { get; set; }
}

As for now, I'm gonna perform the crud operation on the above defined class only, next we need to a context class inherited with DbContext, for this either we can create manually or by using Visual Studio Intellisense, let's use the intellisense, 

Right Click on Controllers folder, Click on Add → Controller, choose "API Controller with actions, using Entity Framework"

Now you will be prompted with select Model class and Context class, for Model class choose Students Class and for Context class, click on plus icon to create new Context class, name it as your preference, i've named as CRUDApiContext, then click on Add. Refer the image below - 

This will install all the necessary nuget package like Entity Framework Core, if not installed, and will create the database connection string that you can find it in appsettings.json file located in your root directory - 

 "ConnectionStrings": {
    "CRUDApiContext": "Server=(localdb)\\mssqllocaldb;Database=CRUDApiContext-a10f782d-6acd-4454-ae03-60a55cfa2327;Trusted_Connection=True;MultipleActiveResultSets=true"
  }

and the CRUDApi Context class file - 

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

        public DbSet<Students> Students { get; set; }
}

and now finally in the controller section, name your controller as Students and press Add.

Now you need to run the Migration command to create database defined in the project configuration, Open Package Manage Console, navigate to Tools > Nuget Package Manager > Package Manager Console and type the following command - 

add-migration init

this command will create a init migration that need to be seeded to database, next run the following command to update your database with seeded values and entity - 

update-database

 Now open StudentsController, and check the generated code with CRUD methods - 

For Read - 

// GET: api/Students
[HttpGet]
public IEnumerable<Students> GetStudents()
{
      return _context.Students;
}

The above code will return all the students found in the database, in the json format, I've discussed this in the testing section.

To fetch the individual records of a student with repective Ids or another unique parameter, you need to pass that to the GET method as described below - 

For Read, Individual record - 

// GET: api/Students/5
[HttpGet("{id}")]
public async Task<IActionResult> GetStudents([FromRoute] Guid id)
{
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var students = await _context.Students.FindAsync(id);
            if (students == null)
            {
                return NotFound();
            }
            return Ok(students);
}

If you want to add new record, HTTP Method POST  is used in that case, make sure you've got the correct name defined in the body section or in your form, since this name matches the properties defined in the Student's class. Use the following method - 

For Create -

 // POST: api/Students
[HttpPost]
public async Task<IActionResult> PostStudents([FromBody] Students students)
{
      if (!ModelState.IsValid)
       {
             return BadRequest(ModelState);
       }
         _context.Students.Add(students);
         await _context.SaveChangesAsync();
         return CreatedAtAction("GetStudents", new { id = students.Id }, students);
}

For edit purpose, use the HTTPPUT method, where we find a student with its Id and matches with the database records, if found, we replace it with new values passed from the form, and return the updated value as json format back to the client, use the following code - 

For Update - 

[HttpPut("{id}")]
public async Task<IActionResult> PutStudents([FromRoute] Guid id, [FromBody] Students students)
{
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != students.Id)
            {
                return BadRequest();
            }

            _context.Entry(students).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!StudentsExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return NoContent();
}

For delete, it follows the same method as Get, we can use HTTPDelete method passing Id of Student as route value and then finding and deleting the record from the database. 

For Delete - 

// DELETE: api/Students/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteStudents([FromRoute] Guid id)
{
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var students = await _context.Students.FindAsync(id);
            if (students == null)
            {
                return NotFound();
            }

            _context.Students.Remove(students);
            await _context.SaveChangesAsync();

            return Ok(students);
}

That's it, your controller will contain the following code - 

[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
        private readonly CRUDApiContext _context;

        public StudentsController(CRUDApiContext context)
        {
            _context = context;
        }

        // GET: api/Students
        [HttpGet]
        public IEnumerable<Students> GetStudents()
        {
            return _context.Students;
        }

        // GET: api/Students/5
        [HttpGet("{id}")]
        public async Task<IActionResult> GetStudents([FromRoute] Guid id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var students = await _context.Students.FindAsync(id);

            if (students == null)
            {
                return NotFound();
            }

            return Ok(students);
        }

        // PUT: api/Students/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutStudents([FromRoute] Guid id, [FromBody] Students students)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != students.Id)
            {
                return BadRequest();
            }

            _context.Entry(students).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!StudentsExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Students
        [HttpPost]
        public async Task<IActionResult> PostStudents([FromBody] Students students)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _context.Students.Add(students);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetStudents", new { id = students.Id }, students);
        }

        // DELETE: api/Students/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteStudents([FromRoute] Guid id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var students = await _context.Students.FindAsync(id);
            if (students == null)
            {
                return NotFound();
            }

            _context.Students.Remove(students);
            await _context.SaveChangesAsync();

            return Ok(students);
        }

        private bool StudentsExists(Guid id)
        {
            return _context.Students.Any(e => e.Id == id);
        }
}

Now let's test the code, use can use multiple methods to test your code out, one of the best method that I prefer is Swagger, since its best for debugging and testing your codes. Let's install and configure Swagger.

Step 3: Testing and Debugging  

We will be installing 3 main components for Swagger to work: 

  • Swashbuckle.AspNetCore.Swagger: a Swagger object model and middleware to expose SwaggerDocument objects as JSON endpoints.

  • Swashbuckle.AspNetCore.SwaggerGen: a Swagger generator that builds SwaggerDocument objects directly from your routes, controllers, and models. It's typically combined with the Swagger endpoint middleware to automatically expose Swagger JSON.

  • Swashbuckle.AspNetCore.SwaggerUI: an embedded version of the Swagger UI tool. It interprets Swagger JSON to build a rich, customizable experience for describing the web API functionality. It includes built-in test harnesses for the public methods.

Swashbuckle can be added with the following approaches:

  • From the Package Manager Console window:

    • Go to View > Other Windows > Package Manager Console

    • Execute the following command:

      Install-Package Swashbuckle.AspNetCore -Version 5.0.0-rc2
      
  • From the Manage NuGet Packages dialog:

    • Right-click the project in Solution Explorer > Manage NuGet Packages
    • Set the Package source to "nuget.org"
    • Ensure the "Include prerelease" option is enabled
    • Enter "Swashbuckle.AspNetCore" in the search box
    • Select the latest "Swashbuckle.AspNetCore" package from the Browse tab and click Install

For Swagger to work, configure it in your Project Startup.cs file and add the following code inside ConfigureServices method

services.AddSwaggerGen(c =>
{
     c.SwaggerDoc("v1", new OpenApiInfo { Title = "CRUD API", Version = "v1" });
});

and in Configure method, allow the app to use Swagger, add the following code

app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
      c.SwaggerEndpoint("/swagger/v1/swagger.json", "CRUD API V1");
});

Now, to open Swagger, debug your app, and in the Url after the port end type "/Swagger" to access the Swagger UI, you will see the HTTP method created for you to test it out along with model that you've defined in your Project - 

Let's test with POST first, click on POST, next click on "Try it out", provide the values in the specified fields and press Execute - 

You will get server's response, now use GET method to fetch the lastest records, you will see the records in following json format with respective header - 

[
  {
    "id": "063dd90d-7617-494a-a48e-6b4762269b50",
    "firstName": "Gautam",
    "lastName": "Sharma",
    "email": "gautamsharma972@gmail.com",
    "grade": "A",
    "dateRegistered": "2019-09-23T00:00:00",
    "isVerified": true
  },
  {
    "id": "c982f732-6665-4310-a051-ac6a498a1cc9",
    "firstName": "John",
    "lastName": "Smith",
    "email": "john@gmail.com",
    "grade": "A",
    "dateRegistered": "2019-09-25T10:04:52.097",
    "isVerified": true
  }
]

Conclusion

Using Swagger you can perform test on many different api operations and debug your app accordingly, you can host this API online and create multiple Client apps that can be Xamarin apps, Angular applications, etc and use this API for server database transactions, which is much faster and using native database apps.

Thanks for reading! :)

Join Newsletter
Get the latest news right in your inbox. We never spam!
Gautam
Written by Gautam Sharma Profile
Hi Gautam here, I'm a Web Developer, a blogger, loves to travel and explore! helping old and poors and needys'!

Connect with Gautam

Facebook  Buy me a Coffee  Instagram  Twitter 

Automate WhatsApp with PyAutoGUI

Automatically send WhatsApp messages at a given time using PyAutoGUI, a module to automate GUI of a computer by emulating keyboad and mouse movements...

Mithu Mondal In Programming about 1 months ago

TinyMCE Image upload to seperate folder in .NET MVC

Upload images to a seperate folder from TinyMCE in ASP.NET MVC, since TinyMCE links images as blob, and sometimes it becomes hard to identify your images... 

Gautam Sharma In Programming about 2 months ago

Basic OSPF Configuration - CCNA

OSPF was designed expressly for IP networks and it supports IP subnetting and tagging of externally derived routing information.

Gautam Sharma In Programming about 2 months ago