Start a project with Me today!

Contact Me

Building lightweight services in ASP.NET Core 6

When working with ASP.NET Core, you may want to build lightweight services, i.e without templates or controller classes, to reduce resource consumption and improve performance. You can create these lightweight services and APIs in the Startup or Program classes. Let’s see how you can build such lightweight services in ASP.NET Core 6

First of all, create an ASP.NET Core project.
Following these steps will create a new ASP.NET Core Web API 6 project in Visual Studio 2022:

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project” and select “ASP.NET Core Web API” from the list of templates displayed.
  3. Click Next, and “Configure your new project” window, specify the name and location for the new project.
  4. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  5. Click Next and in the “Additional Information” window shown next, select .NET 6.0 (Preview) as the target framework from the drop-down list at the top. Leave the “Authentication Type” as “None” (default).

To building lightweight services that don’t require a controller, you should now delete the Controllers solution folder and any model classes that are created by default.

Next, open the launchSettings.json file under the Properties solution folder and remove or comment out the launchUrl key-value pair as shown in the code snippet given below.

The launchUrl refers to the host of your application. When the application is started, the URL specified in launchURL is used to start the application. If the URL is wrong or does not exist, the application will throw an error at startup. By removing launchUrl or commenting it out, we ensure that the application doesn’t use the default launchUrl to launch the application and thus we avoid any errors. Once the launchUrl is removed, the application will fall back to port 5000.

We’ll now take advantage of some of the extension methods of the IEndpointConventionBuilder interface to map requests. Here is the list of these extension methods:

  • MapGet
  • MapPost
  • MapDelete
  • MapPut
  • MapRazorPages
  • MapControllers
  • MapHub
  • MapGrpcServices

The MapGet, MapPost, MapDelete, and MapPut methods are used to connect the request delegate to the routing system. MapRazorPages is used for RazorPages, MapControllers for Controllers, MapHub for SignalR, and MapGrpcService for gRPC.

The following code snippet illustrates how you can use MapGet to create an HTTP Get endpoint.

endpoints.MapGet("/", async context =>
{
     await context.Response.WriteAsync("Hello World!");
});

Now create a new C# file named Person and enter the following code:

public class Person
{
   public int Id { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

Create a read-only list of Person and populate it with some data as shown in the code snippet given below.

private readonly List<Person> _persons;
        public Startup(IConfiguration configuration)
        {
            _authors = new List<Person>
            {
                new Person
                {
                    Id = 1,
                    FirstName = "Ravi",
                    LastName = "Kandel"
                },
                new Person
                {
                    Id = 2,
                    FirstName = "David",
                    LastName = "Warner"
                },
                new Person
                {
                    Id = 3,
                    FirstName = "John",
                    LastName = "Doe"
                }
            };
            Configuration = configuration;
        }

You can use the following code to create another endpoint and return the list of Person in JSON format.

endpoints.MapGet("/persons", async context =>
{
      var persons = _persons == null ? new List<Person>() : _persons;
      var response = JsonSerializer.Serialize(persons);
      await context.Response.WriteAsync(response);
});

To retrieve a particular record based on the Id, you can write the following code:

endpoints.MapGet("/persons/{id:int}", async context =>
{
   var id = int.Parse((string)context.Request.RouteValues["id"]);
   var person = _persons.Find(x=> x.Id == id);
   var response = JsonSerializer.Serialize(person);
   await context.Response.WriteAsync(response);
});

To add data using an HTTP Post endpoint, you can take advantage of the MapPost extension method as shown below.

endpoints.MapPost("/", async context =>
{
    var person = await context.Request.ReadFromJsonAsync<Person>();
    _persons.Add(person);
    var response = JsonSerializer.Serialize(person);
    await context.Response.WriteAsync(response);
});

To delete data, you can take advantage of the MapDelete extension method as shown below.

endpoints.MapDelete("/persons/{id:int}", async context =>
{
    var id = int.Parse((string)context.Request.RouteValues["id"]);
    var person = _persons.Find(x => x.Id == id);
    _persons.Remove(person);
    var response = JsonSerializer.Serialize(_persons);
    await context.Response.WriteAsync(response);
});

Finally, The complete source code of the Configure method of the Startup class:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   if (env.IsDevelopment())
   {
        app.UseDeveloperExceptionPage();
   }
   app.UseRouting();
   app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
   await context.Response.WriteAsync("Hello World!");
});
endpoints.MapGet("/persons", async context =>
{
    var persons = _persons == null ? new List<Person>() : _persons;
    var response = JsonSerializer.Serialize(persons);
    await context.Response.WriteAsync(response);
});
endpoints.MapGet("/persons/{id:int}", async context =>
{
    var id = int.Parse((string)context.Request.RouteValues["id"]);
    var person = _persons.Find(x=> x.Id == id);
    var response = JsonSerializer.Serialize(person);
    await context.Response.WriteAsync(response);
});
endpoints.MapPost("/", async context =>
{
    var person = await context.Request.ReadFromJsonAsync<Person>();
    _persons.Add(person);
    var response = JsonSerializer.Serialize(person);
    await context.Response.WriteAsync(response);
});
endpoints.MapDelete("/persons/{id:int}", async context =>
{
    var id = int.Parse((string)context.Request.RouteValues["id"]);
    var person = _persons.Find(x => x.Id == id);
    _persons.Remove(person);
    var response = JsonSerializer.Serialize(_persons);
    await context.Response.WriteAsync(response);
});
   });
}

Lightweight services or APIs don’t have a template and don’t need a controller class to create them in. You can create such services in the Startup or the Program class.

If you want to implement authorization in the lightweight services demonstrated in this post, you should take advantage of the RequireAuthorization extension method of the IEndpointConventionBuilder interface.

Happy Coding…!!! 😉

Posted : 3 years ago