Разработка бэкенда сайта на 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 — декларативное кэширование ответов прямо на эндпоинте:

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 эндпоинтов, одна БД, JWT-аутентификация): 5–8 рабочих дней. Полноценный бэкенд с ролями, фоновыми задачами, WebSocket, интеграционным тестированием и CI/CD: 3–5 недель. Миграция существующего .NET Framework проекта на .NET 8 зависит от глубины legacy — оцениваем отдельно после аудита кодовой базы.