.NET Core — WebApi tips. Building Api with good practices and…
By: Ibrahim Jaber
Tags: Api Development, Net Core, Aspnetcore, Asynchronous Programming, Swagger

Photo by Nick Fewings on Unsplash

Building Api with good practices and proper documentation is important for the development life span of API service.

Today, I will walk you through a sample of an API(that can be improved upon). we will build upon that API example and add a couple of features Like Swagger, Async calls to the Database, and so on.

Let Get Started!!.

1-Cloning the existing Repo.

You can find the Repo link here

2-Making our Database calls Asynchronous.

As you can see below the methods in the Interface aren’t Async.

we will go ahead and change that to be Async.

a-Making the Interface methods Asynchronous.

Making the methods Asynchronous improves the response time where you can run multiple calls simultaneously and, save time instead of waiting for each call individually.

Old version

public interface IBaseRepo<T>

{

List<T> GetAll();

T Get(int id);

int Save(T item);

int Delete(T item); }

Updated

public interface IBaseRepo<T> { Task<List<T>> GetAll(); Task<T> Get(int id); Task<int> Save(T item); Task<int> Delete(T item); }

b-Updating the Repo class methods implementation to be Asynchronous

Old version

public class ProductRepo : IProductRepo

{ private readonly ProductContext _context; public ProductRepo(ProductContext context)

{

_context = context;

} public Product Get(int id)

{

var product = _context.Products.FirstOrDefault

(i => i.ID == id); return product;

} public List<Product> GetAll()

{

var products = _context.Products.ToList(); return products;

} public int Save(Product item)

{

if(item.ID == 0)

{

_context.Products.Add(item);

}

else

{

_context.Products.Update(item);

} return _context.SaveChanges();

} public int Delete(Product item)

{

_context.Remove(item); return _context.SaveChanges();

}

}

Updated

public class ProductRepo : IProductRepo { private readonly ProductContext _context; public ProductRepo(ProductContext context) { _context = context; } public async Task<Product> Get(int id) { var product = _context.Products.FirstOrDefaultAsync

(i => i.ID == id); return await product; } public async Task<List<Product>> GetAll() { var products = _context.Products.ToListAsync(); return await products; } public async Task<int> Save(Product item) { if(item.ID == 0) { _context.Products.Add(item); } else { _context.Products.Update(item); } return await _context.SaveChangesAsync(); } public async Task<int> Delete(Product item) { _context.Remove(item); return await _context.SaveChangesAsync(); } }

3- Updating the controller

In the product Controller, we will make the methods return types strongly typed by specifying the object returned in the ActionResult. This will make sure that we are not returning the wrong data by making the method strongly typed.

Updated

4- Adding Swagger for API documentation

a-Downloading the required packages for Swagger.

below are the packages that are required for Swagger and the whole application.

b-applying changes in Startup.cs

In Startup.cs we will need to add the required configuration to enable Swagger and its related dependencies.

ConfigureServices

public void ConfigureServices(IServiceCollection services) { services.AddScoped<IProductRepo, ProductRepo>(); services.AddDbContext<ProductContext>(options => options .UseSqlServer (Configuration.GetConnectionString("DefaultConnection"))); var apiInfo = Configuration.GetSection("SwaggerApiInfo") .Get<OpenApiInfo>(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", apiInfo); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); //Ignore Circular relationships. services.AddControllers().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore ); }

Configure

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); c.RoutePrefix = string.Empty; }); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

5-Adding our Swagger Information Object in appSettings.json

We’re adding the information related to the API page in appSettings.json and then we are serializing it to an OpenApiInfo object in ConfigureServices method.

"SwaggerApiInfo": { "title": "Products API - Demo", "description": "API demo in .NET Core", "version": "V1", "Contact": { "name": "Your Name - API", "email": "intorToApi@mail.com", "url": "example.com" }, "Licesne": { "name": "Your name - License", "url": "license@example.com" } }

6-Modifying the Project properties to insert XML comments to provide extra information in the UI.

I have applied the below changes to the Project properties in the Build section to enable XML documentation.