ASP.NET Core 7 WebAPI Refit

ASP .NET Core Project for learning. Every one should be able to use this templae to build a ASP .NET Core web API with Refit and Fake API. 0 comments
By Sopheaktra Eang | July 04, 2024

Key Functions

  1. Swagger for API's Endpoint
  2. API-Versioning
  3. Refit

Getting Started

These instructions will get you to setup the project, install sdk and add package (CLI or Package manager console).

Prerequisites

  • Visual Studio 2022 or higher
  • .NET 7.x SDK

Installing

  1. Install .net SDK 7
    Download .NET SDK here.
  2. Create new Web API's project
    dotnet new webapi –-name ASP.NET_Core7_WebAPI_Refit
  3. Add package
    • API-Versioning 
      dotnet add package Asp.Versioning.Mvc.ApiExplorer
    • Refit 
      dotnet add package Refit

Languages and Tools

dotnet core  csharp  Refit 
 

What's Refit?

Refit is an automatic type-safe REST library for .NET CoreXamarin, and .NET. It’s heavily inspired by Square’s Retrofit library. With Refit, you can turn your REST API into a live interface.

How it works?

Here’s how it works:

  • Define an Interface: Create an interface that represents your API. For example:
public interface IApi
{
    [Get("/users/{user}")]
    Task<User> GetUser(string user);
}
  • Generate Implementation: Refit generates an implementation of IGitHubApi that uses HttpClient to make API calls:
var api = RestService.For<IApi>("https://api.com");
var result = await api.GetUser("octocat");
  • HttpClientFactory Support: .NET Core supports registering Refit clients via HttpClientFactory services:
services.AddRefitClient<IApi>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.com"));
  • Features:
    • Querystrings
    • Dynamic querystring parameters
    • Custom querystring parameter formatting
    • Body content
    • Request headers (static and dynamic)
    • Bearer authentication
    • Exception handling
    • Multipart uploads
    • Using generic interfaces
    • ...etc

Refit enhances reliability and quality assurance by providing a type-safe way to consume APIs in your ASP.NET Core applications.

Let's Start Code with ASP.NET Core

Override config 'appsettings.json':

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "FakeAPI": {
    "URL": "https://fakestoreapi.com/"
  }
}

And then override 'Program.cs':

using Asp.Versioning;
using ASP.NET_Core7_WebAPI_Refit.Services;
using ASP.NET_Core7_WebAPI_Refit.Configurations.Swagger;
using Microsoft.Extensions.Options;
using Refit;
using Swashbuckle.AspNetCore.SwaggerGen;

const string SwaggerRoutePrefix = "api-docs";

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

builder.Services
    .AddApiVersioning(
                options =>
                {
                    // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
                    options.ReportApiVersions = true;
                })
    .AddApiExplorer(options =>
    {
        options.DefaultApiVersion = new ApiVersion(1, 0);
        // Add the versioned API explorer, which also adds IApiVersionDescriptionProvider service
        // note: the specified format code will format the version as "'v'major[.minor][-status]"
        options.GroupNameFormat = "'v'VVV";

        // note: this option is only necessary when versioning by url segment. the SubstitutionFormat
        // can also be used to control the format of the API version in route templates
        options.SubstituteApiVersionInUrl = true;
        options.AssumeDefaultVersionWhenUnspecified = true;
    });

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
builder.Services.AddSwaggerGen(options =>
{
    // Add a custom operation filter which sets default values
    options.OperationFilter<SwaggerDefaultValues>();
});
string FakeAPIUrl = builder.Configuration["FakeAPI:URL"] ?? string.Empty;
//add Refit for User Fake API
builder.Services.AddScoped<IUsersApiClientService>(x => RestService.For<IUsersApiClientService>(FakeAPIUrl));
//add Regit for Product Fake API
builder.Services.AddScoped<IProductsApiClientService>(x => RestService.For<IProductsApiClientService>(FakeAPIUrl));
//add Regit for Cart Fake API
builder.Services.AddScoped<ICartsApiClientService>(x => RestService.For<ICartsApiClientService>(FakeAPIUrl));



var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger(options => { options.RouteTemplate = $"{SwaggerRoutePrefix}/{{documentName}}/docs.json"; });
    app.UseSwaggerUI(options =>
    {
        options.RoutePrefix = SwaggerRoutePrefix;
        foreach (var description in app.DescribeApiVersions())
            options.SwaggerEndpoint($"/{SwaggerRoutePrefix}/{description.GroupName}/docs.json", description.GroupName.ToUpperInvariant());
    });
}

app.UseHttpsRedirection();

app.MapControllers();

app.Run();

In this tutorial I am using FAKE API with 3 Serivces:

  • ICartsApiClientService: using for consume carts's API: create service "Services/ICartsApiClientService.cs":
using ASP.NET_Core7_WebAPI_Refit.Dtos.Cart;
using ASP.NET_Core7_WebAPI_Refit.Payloads.Requests.Cart;
using Refit;

namespace ASP.NET_Core7_WebAPI_Refit.Services {
    public interface ICartsApiClientService {
        [Get("/carts")]
        Task<IEnumerable<CartDto>> GetAllCartsQuery(QueryParamCart queryParam);
        [Get("/carts/user/{userId}")]
        Task<IEnumerable<CartDto>> GetAllCartsByUserId(int userId);
        [Get("/carts/{id}")]
        Task<CartDto> GetCartById(int id);
        [Post("/carts")]
        Task<CartDto> CreateCart(CreateCartDto createCartDto);
        [Put("/carts")]
        Task<CartDto> UpdateCart(UpdateCartDto updateCartDto);
        [Delete("/carts/{id}")]
        Task<CartDto> DeleteCartById(int id);
    }
}
  • IProductsApiClientService: using for consume products's API: create service "Services/IProductsApiClientService.cs":
using ASP.NET_Core7_WebAPI_Refit.Dtos.Product;
using ASP.NET_Core7_WebAPI_Refit.Payloads.Requests;
using Refit;

namespace ASP.NET_Core7_WebAPI_Refit.Services {
    public interface IProductsApiClientService {
        [Get("/products")]
        Task<IEnumerable<ProductDto>> GetAllProductsQuery(QueryParam queryParam);
        [Get("/products/category/{category}")]
        Task<IEnumerable<ProductDto>> GetAllProductsByCategory(string category);
        [Get("/products/{id}")]
        Task<ProductDto> GetProductById(int id);
        [Post("/products")]
        Task<ProductDto> CreateProduct(CreateProductDto createProductDto);
        [Put("/products")]
        Task<ProductDto> UpdateProduct(UpdateProductDto updateProductDto);
        [Delete("/products/{id}")]
        Task<ProductDto> DeleteProductById(int id);
    }
}
  • IUsersApiClientService: using for consume users's API: create service "Services/IUsersApiClientService.cs":
using ASP.NET_Core7_WebAPI_Refit.Dtos.User;
using ASP.NET_Core7_WebAPI_Refit.Payloads.Requests;
using Refit;

namespace ASP.NET_Core7_WebAPI_Refit.Services {
    public interface IUsersApiClientService {
        [Get("/users")]
        Task<IEnumerable<UserDto>> GetAllUsersQuery(QueryParam queryParam);
        [Get("/users/{id}")]
        Task<UserDto> GetUserById(int id);
        [Post("/users")]
        Task<UserDto> CreateUser(CreateUserDto createUserDto);
        [Put("/users")]
        Task<UserDto> UpdateUser(UpdateUserDto updateUserDto);
        [Delete("/users/{id}")]
        Task<UserDto> DeleteUserById(int id);
    }
}

Summary

Download the source code for the sample application implementing rest service on application. Also you will learn about refit and consume api for faster and easy.