This is Web API tutorial using Asp.net Core 3.1 for beginners and professionals with some real-time examples.
If you are very new to asp.net core web API, please take a look at how to create basic asp.net code web API [Part-1]
What do I learn from this tutorial?
Note: In this post I will explain the life cycle of web api call with get methods, so you know how to create an api using asp.net core 3.1 framework. (not covering other post, put and delete methods). you can check those examples here.
In this tutorial you learn how to create asp.net core Web API using asp.net core 3.1, like earlier version of Web API you will see many similarities and also learn many new things from asp.Net Core framework
In this example, we focus on Asp.net Core 3.1 framework and some new changes compare to earlier version
Here in example below I have created an API controller with two methods “Get” and “GetOrders”
Things to learn:
private readonly ILogger<OrderController> _logger; private readonly IQueryService _queryService; public OrderController(ILogger<OrderController> logger, IQueryService query) { _logger = logger; _queryService = query; }
[Route("")] [HttpGet] public IEnumerable<OrderItem> Get() { }
[Route("GetOrders")] [HttpGet] [ProducesResponseType(typeof(IEnumerable<Order>),(int)HttpStatusCode.OK)] public async Task<IActionResult> GetOrders() { return Ok(results); }
Here is the complete ApiController code
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System.Net; [ApiController] [Route("[controller]")] public class OrderController : ControllerBase { private readonly ILogger<OrderController> _logger; private readonly IQueryService _queryService; public OrderController(ILogger<OrderController> logger, IQueryService query) { _logger = logger; _queryService = query; } [Route("")] [HttpGet] public IEnumerable<OrderItem> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index =< new OrderItem { OrderDate = DateTime.Now.AddDays(index), ProductId = rng.Next(-20, 55), }) .ToArray(); } [Route("GetOrders")] [HttpGet] [ProducesResponseType(typeof(IEnumerable<Order>),(int)HttpStatusCode.OK)] public async Task<IActionResult> GetOrders() { var orders = await _queryService.GetNewOrdersAsync(); return Ok(orders); } [HttpPost] public void Post([FromBody]string value) { } [HttpPut("{id}")] public void Put(int id, [FromBody]string value) { } [HttpDelete("{id}")] public void Delete(int id) { } }
Notice, in above controller I am calling the function from a service instance called _queryService
, so now let's look at the "QueryService" class design
We can create any number of services that we want to consume in Web API, as an example here we have created IQueryService
interface and QueryService
class.
You will also learn how to return strongly typed class object and dynamic object from database query.
Look at the code below, how to create DbConnection
object using constructor dependency injection (DI).
private readonly DbConnection dbconfig; public QueryService(IOptions<DbConnection> dbcon) { dbconfig = dbcon.Value; }
You need to install Dapper
from Nuget package, Dapper provides many ready to use extension method,
In this example "Dapper" will be used for creating dynamic object from database query, and the advantage of creating dynamic object is that you don’t have to make changes in your business object every time you make changes in database table or view. It will directly create object from SQL query
connection.QueryAsync<dynamic>(@"SELECT * from tbProducts");
Here is the example of how your service class will look like!
using Dapper; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Threading.Tasks; public interface IQueryService { Task GetNewOrders(); Task<IEnumerable<dynamic>> GetNewOrdersAsync(); } public class QueryService : IQueryService { private readonly DbConnection dbconfig; public QueryService(IOptions<DbConnection> dbcon) { dbconfig = dbcon.Value; } public Task GetNewOrders() { using (var connection = new SqlConnection(dbconfig.ConnectionString)) { connection.Open(); // do whatever connection.Close(); } throw new NotImplementedException(); } public async Task<IEnumerable<dynamic>> GetNewOrdersAsync() { using (var connection = new SqlConnection(dbconfig.ConnectionString)) { connection.Open(); return await connection.QueryAsync<dynamic>(@"SELECT * from tbProducts"); } } }
Now create a class for loading database connection string related information from appsettings.json, we need to register this class in startup service class like example below.
services.Configure<DbConnection>(Configuration.GetSection("DbConnectionConfig"));
Notice, how the connection string (read only) property has been formed
public string ConnectionString { get { return string.Format("Server={0};Database={1};User ID={2};Password={3};" + "Trusted_Connection=False;MultipleActiveResultSets=true;", ServerName, DatabaseName, UserName, Password); } }
Here is the code for DbConnection class
public class DbConnection { public string DatabaseName { get; set; } public string UserName { get; set; } public string Password { get; set; } public string ServerName { get; set; } public string ConnectionString { get { return string.Format("Server={0};Database={1};User ID={2};Password={3};" + "Trusted_Connection=False;MultipleActiveResultSets=true;", ServerName, DatabaseName, UserName, Password); } } }
Now we add a new section in appsettings file, as you can see at the file below, we have added a new section called “DbConnectionConfig” with all database related information
"DbConnectionConfig": { "DatabaseName": "FoodServiceDB", "UserName": "dbusername", "Password": "dbpassword", "ServerName": "ACMachine1\\SQLEXPRESS" },
We can create different section to classify configuration related information.
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "DbConnectionConfig": { "DatabaseName": "FoodServiceDB", "UserName": "dbusername", "Password": "dbpassword", "ServerName": "ACMachine1\\SQLEXPRESS" }, "AllowedHosts": "*" }
If you are very new to appsettings.json, then you may be interested to know how to read information from appsettings.json
Now we create a custom DbContext class inherited from DbContext AppContext:DbContext
Notice, how DbConnection object is created using constructor dependency injection.
private readonly DbConnection dbconfig; public AppContext(IOptions<DbConnection> dbcon) { dbconfig = dbcon.Value; }
You may need to install Microsoft.EntityFrameworkCore.SqlServer
from Nuget package for using UseSqlServer
function, UseSqlServer is the extension method
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer(ConnectionString); } base.OnConfiguring(optionsBuilder); }
Here is the code for your AppContext class
public class AppContext:DbContext { private readonly DbConnection dbconfig; public AppContext() : base() { } public AppContext(IOptions<DbConnection> dbcon) { dbconfig = dbcon.Value; } public string ConnectionString { get { return dbconfig.ConnectionString; } } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer(ConnectionString); } base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { //modelBuilder.Entity<Student>().HasKey(s => s.StuId); base.OnModelCreating(modelBuilder); } //public DbSet<Student> Orders { get; set; } }
Now, we need make some changes in Startup.cs file; Configure DbConnection
class and QueryService
class in ConfigureServices method
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.Configure<DbConnection>(Configuration.GetSection("DbConnectionConfig")); services.AddScoped<IQueryService, QueryService>(); }
public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.Configure<DbConnection>(Configuration.GetSection("DbConnectionConfig")); services.AddScoped<IQueryService, QueryService>(); } }
This was a basic example of creating asp.net core web API on localhost, now we create an asp.net core web api with database methods including security and different serialization settings, exception handing etc.