Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimal Footprint / Bare-bones ASP.NET Core WebAPI

Just for fun, earlier today one of my colleagues asked if I could try and make a tiny-footprint WebAPI that echoed requests using ASP.NET Core. I was able to get the WebAPI done in about 70 lines of code. All thanks to ASP.NET Core being amazing! So, this is what I ended up with so far.

The Code

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Linq;

namespace TinyWebApi
{
    class Program
    {
        static readonly IWebHost _host;
        static readonly string[] _urls = { "http://localhost:80" };

        static Program()
        {
            IConfiguration _configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .Build();
            _host = BuildHost(new WebHostBuilder(), _configuration, _urls);
        }

        static void Main(string[] args)
        {
            _host.Run();
        }

        static IWebHost BuildHost(
            IWebHostBuilder builder, IConfiguration configuration, params string[] urls)
        {
            return builder
                .UseKestrel(options =>
                {
                    options.NoDelay = true;
                })
                .UseConfiguration(configuration)
                .UseUrls(urls)
                .Configure(app =>
                {
                    app.Map("/echo", EchoHandler);
                })
                .Build();
        }

        static void EchoHandler(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                await context.Response.WriteAsync(
                    JsonConvert.SerializeObject(new
                    {
                        StatusCode = (string)context.Response.StatusCode.ToString(),
                        PathBase = (string)context.Request.PathBase.Value.Trim('/'),
                        Path = (string)context.Request.Path.Value.Trim('/'),
                        Method = (string)context.Request.Method,
                        Scheme = (string)context.Request.Scheme,
                        ContentType = (string)context.Request.ContentType,
                        ContentLength = (long?)context.Request.ContentLength,
                        QueryString = (string)context.Request.QueryString.ToString(),
                        Query = context.Request.Query
                            .ToDictionary(
                                _ => _.Key,
                                _ => _.Value,
                                StringComparer.OrdinalIgnoreCase)
                    })
                );
            });
        }
    }
}

(The code above works as expected, and it's not broken.)


The WebAPI

The WebAPI is supposed to echo back the request with a JSON.

Example Request

http://localhost/echo?q=foo&q=bar

Example Response

{
  "StatusCode": "200",
  "PathBase": "echo",
  "Path": "",
  "Method": "GET",
  "Scheme": "http",
  "ContentType": null,
  "ContentLength": null,
  "QueryString": "?q=foo&q=bar",
  "Query": {
    "q": [
      "foo",
      "bar"
    ]
  }
}

My Problem

I blew my colleague away with just the 70+ lines of code to do the job, but then when we took a look at the file size it wasn't as impressive...

At the moment with all these dependencies, my WebAPI is compiling to 54.3MB.

I am stuck with trying to figure out how to reduce the disk footprint of this project. The packages I have installed are bundled up with so much stuff we don't really need and I keep running into trouble trying to find out the best resource or method to removing the unneeded references for this project.

The .csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
    <ApplicationIcon>Icon.ico</ApplicationIcon>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="1.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" />
    <PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
  </ItemGroup>

</Project>

Is there any quick way for me to know what references my project needs based on the code provided? I started earlier by wiping clear all the above dependencies and then trying to add them one by one, but it turns out to become a never ending headache of trying to solve missing references and it seems to take forever to solve. I'm sure someone out there has a solution for something like this, but I can't seem to find it. Thanks.

like image 627
Svek Avatar asked Jun 04 '17 16:06

Svek


1 Answers

What I did was just copy the code to a new .NET Core console project and resolved the missing references. To figure out which ones you need to add for the missing APIs I just did F12 on the missing member (Go to definition) in the working project with all references to see in which assembly the API is defined.

Since you're not using anything fancy here, so the ASP.NET Core Web application template shipped in VS already uses all of these APIs, so you could use that as the 'working project'.

The AddJsonFile for example was defined in Microsoft.Extensions.Configuration.Json package.

So in the end I was left with

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
    <PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
  </ItemGroup>

</Project>

When published it added up to 2.41MB.

Granted you probably wouldn't want to do this on a bigger project. On this project in only takes a minute or so.

like image 169
erikbozic Avatar answered Nov 14 '22 05:11

erikbozic