Розробка бекенду сайту на C# (.NET / ASP.NET Core)

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка бекенду сайту на C# (.NET / ASP.NET Core)
Складна
від 2 тижнів до 3 місяців
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка бекенду сайту на C# (.NET / ASP.NET Core)

ASP.NET Core — зріла платформа з передбачуваною поведінкою під навантаженням, строгою типізацією та обширною екосистемою NuGet. Вибирають її, коли в команді вже є .NET-інженери, коли потрібна інтеграція з Active Directory/Azure AD, або коли вимоги до продуктивності занадто серйозні для Node.js.

Коли .NET виправданий

Якщо API буде обробляти тисячі запитів на секунду з синхронними операціями до БД — ASP.NET Core на Kestrel без реверс-прокси легко утримує 50–80k RPS на одному ядрі. Якщо проект вже використовує C# у фронтенді (Blazor) чи desktop-частині — монорепо з єдиною мовою знижує накладні видатки. Якщо потрібен вбудований DI, OpenAPI, gRPC і WebSocket без шести окремих бібліотек.

Структура проекту

Мінімальний API на .NET 8 без контролерів:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseNpgsql(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opt =>
    {
        opt.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidateAudience = false,
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Secret"]!))
        };
    });

var app = builder.Build();

app.MapGet("/users/{id:int}", async (int id, IUserService svc) =>
    await svc.GetByIdAsync(id) is { } user
        ? Results.Ok(user)
        : Results.NotFound());

app.MapPost("/users", async (CreateUserDto dto, IUserService svc) =>
{
    var user = await svc.CreateAsync(dto);
    return Results.Created($"/users/{user.Id}", user);
});

app.Run();

Для проектів складніших за три сутності краще окремі шари: Domain, Application, Infrastructure, WebApi. Vertical Slice Architecture з MediatR — хороша альтернатива класичному layered-підходу:

// Features/Users/GetUser.cs
public static class GetUser
{
    public record Query(int Id) : IRequest<UserDto?>;

    public class Handler(AppDbContext db) : IRequestHandler<Query, UserDto?>
    {
        public async Task<UserDto?> Handle(Query req, CancellationToken ct) =>
            await db.Users
                .Where(u => u.Id == req.Id)
                .Select(u => new UserDto(u.Id, u.Email, u.CreatedAt))
                .FirstOrDefaultAsync(ct);
    }
}

Entity Framework Core vs Dapper

EF Core з міграціями — стандарт для CRUD-тяжких сервісів. Dapper беруть для отчетних запитів, де ORM генерує неоптимальний SQL.

// EF Core — автоматичні міграції
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
    public DbSet<User> Users => Set<User>();

    protected override void OnModelCreating(ModelBuilder mb)
    {
        mb.Entity<User>(e =>
        {
            e.HasIndex(u => u.Email).IsUnique();
            e.Property(u => u.CreatedAt).HasDefaultValueSql("now()");
        });
    }
}

// Dapper — коли потрібен сирий SQL
public async Task<IEnumerable<ReportRow>> GetReportAsync(DateRange range)
{
    await using var conn = new NpgsqlConnection(_connStr);
    return await conn.QueryAsync<ReportRow>("""
        SELECT date_trunc('day', created_at) AS day,
               count(*) AS orders,
               sum(total) AS revenue
        FROM orders
        WHERE created_at BETWEEN @From AND @To
        GROUP BY 1
        ORDER BY 1
        """, new { range.From, range.To });
}

Кеширування та фонові задачі

Output Cache на .NET 8 — декларативне кеширування відповідей прямо на endpoint:

builder.Services.AddOutputCache(opt =>
{
    opt.AddPolicy("products", p => p.Expire(TimeSpan.FromMinutes(10)).Tag("products"));
});

app.MapGet("/products", async (IProductRepo repo) => await repo.GetAllAsync())
   .CacheOutput("products");

// Інвалідація після змін
app.MapPost("/products", async (CreateProductDto dto, IOutputCacheStore cache, ...) =>
{
    var product = await svc.CreateAsync(dto);
    await cache.EvictByTagAsync("products", CancellationToken.None);
    return Results.Created($"/products/{product.Id}", product);
});

Фонові задачі через IHostedService або Hangfire:

// Проста фонова задача
public class EmailWorker(IServiceProvider sp) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            using var scope = sp.CreateScope();
            var queue = scope.ServiceProvider.GetRequiredService<IEmailQueue>();
            var mailer = scope.ServiceProvider.GetRequiredService<IMailer>();

            await foreach (var msg in queue.DequeueAsync(ct))
                await mailer.SendAsync(msg, ct);
        }
    }
}

SignalR для реального часу

public class NotificationHub : Hub
{
    public async Task JoinGroup(string groupName) =>
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}

// Відправлення із сервісу
public class OrderService(IHubContext<NotificationHub> hub)
{
    public async Task UpdateStatusAsync(int orderId, string status)
    {
        await _db.Orders.Where(o => o.Id == orderId)
            .ExecuteUpdateAsync(s => s.SetProperty(o => o.Status, status));

        await hub.Clients.Group($"order-{orderId}")
            .SendAsync("StatusChanged", new { orderId, status });
    }
}

Деплой

Dockerfile для production:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApi.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApi.dll"]

Health checks для оркестраторів:

builder.Services.AddHealthChecks()
    .AddNpgsql(connStr, name: "postgres")
    .AddRedis(redisConn, name: "redis");

app.MapHealthChecks("/health/live", new HealthCheckOptions { Predicate = _ => false });
app.MapHealthChecks("/health/ready");

Графік

Простий REST API (5–10 endpoints, одна БД, JWT-аутентифікація): 5–8 робочих днів. Повноцінний бекенд з ролями, фоновими задачами, WebSocket, інтеграційним тестуванням і CI/CD: 3–5 тижнів. Міграція існуючого .NET Framework проекту на .NET 8 залежить від глибини legacy — оцінюємо окремо після аудиту кодової бази.