Development of a .NET Web application on Yandex Cloud Functions


Introduction

Yandex Cloud provides the ability to deploy .NET applications in various ways, a typical of which is docker containers deployed on the created computing resources, which implies payment for allocated processors and memory. A more economical option is provided by serverless Cloud Functions and Serverless Containers services, where payment is based on actually consumed resources, scaling is carried out by the cloud itself. Containers are a good development option, but simpler and lighter is Cloud Functions.

Tools

Visual Studio provides the ability to create any Web application, but they must be deployed on hosts that open ports for user interaction. An option for Cloud Functions is to create a module that has a predefined entry point. The handler method must be public, have the name FunctionHandler and one input parameter. But I would like to create full-fledged Web Api, where under the hood is midlware and all the power of dependency injection created by MS. Yandex does not have such a tool, but Amazon does. AWS SDK for .NET makes it possible to create and transfer existing Web applications to the cloud, and integrates with Visual Studio, which we simply use. This technology makes it possible to run and debug locally using Visual Studio.

AWS Project Templates

Components

The AWS SDK implements IHostBuilder but replaces the IServer service with an empty stub on startup, so the host doesn’t open ports on startup, etc. but the midleware processing chain works. The entry point and call signature do not match Yandex, but this is not a problem, open source makes it possible to complete the project, and now our AWS SDK with Yandex support.

Development

Download and install nuget packet locally Amazon.Lambda.Yandex.0.0.1.nupkgwhich we created by running the nuget add command with the local repository options, which can be viewed in the VS settings.

Let’s create in Visual Studio web api project :

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace WebApplication
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }


        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapGet("/", () => "Welcome to running ASP.NET Core Minimal API");
                endpoints.MapGet("/test", () => "Welcome to Yandex");
            });
        }
    }
}
using Amazon.Lambda.AspNetCoreServer;
using Microsoft.AspNetCore.Hosting;

namespace WebApplication
{
    public class YandexFunction : YandexGatewayProxyFunction
    {
        protected override void Init(IWebHostBuilder builder)
        {
            builder.UseStartup<Startup>();
        }
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using WebApplication.Model;

namespace WebApplication.Controllers
{
    [ApiController]
    [Route("api/test")]
    public class ApiController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public ApiController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

Deployment

Yandex probably optimized and cut the net6 execution environment, so you have to do the Self-contained assembly, otherwise the loader swears at the lack of kernel libraries, then we will remove the system libraries.

We do a local deployment of Publish, set the parameters:

  • linux-x64

  • net6.0

  • Self-contained

  • Trim unused code

Delete System.*.dll and *.so files except System.Diagnostics.*.dll System.IO.*.dll System.Text.*.dll
Packed in .zip, shipped to the cloud.

Entry point: WebApplication.YandexFunction

Create a separate Yandex API for the function Gateway:

openapi: 3.0.0
info:
  title: Sample Web API
  version: 1.0.0
servers:
- url: https://....apigw.yandexcloud.net
paths:
  /test:
    get:
      summary: Get Test
      operationId: gettest10
      tags:
        - example
      x-yc-apigateway-integration:
        type: cloud_functions
        function_id: ...
        payload_format_version: "1.0"
        tag: "$latest"
      responses:
        '200':
          description: Ok
  /api/{param+}:
    x-yc-apigateway-any-method:
      summary: Get Controllers
      parameters:
        - name: param
          in: path
          required: true
          schema:
            type: string
      operationId: getcontrollers
      tags:
        - example
      x-yc-apigateway-integration:
        type: cloud_functions
        function_id: ...
        payload_format_version: "1.0"
        tag: "$latest"
      responses:
        '200':
          description: Ok

Our application is ready and available on the Internet at the gateway address.

Links to sources:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *