Разработка сайта на CMS Umbraco

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка сайта на CMS Umbraco
Сложная
~2-4 недели
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • 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

Разработка сайта на CMS Umbraco

Umbraco — CMS на ASP.NET Core с открытым исходным кодом. Работает на .NET 8, использует SQL Server или SQLite, поддерживает кластеризацию. Хорошо подходит для корпоративных сайтов, порталов, multisite-инфраструктур — там, где заказчик привязан к Microsoft-стеку или нужен headless CMS с enterprise-возможностями.

Архитектура проекта

MyProject/
├── MyProject.Web/            # основной веб-проект
│   ├── Controllers/          # Surface и Render Controllers
│   ├── Models/               # strongly-typed models
│   ├── Views/                # Razor Views
│   │   ├── Partials/
│   │   └── Shared/
│   ├── Composers/            # внедрение данных в вьюхи
│   ├── NotificationHandlers/ # события Umbraco
│   ├── wwwroot/
│   └── Program.cs
├── MyProject.Core/           # бизнес-логика
│   ├── Services/
│   └── Models/
└── MyProject.Tests/

Настройка хост-приложения

// Program.cs
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.CreateUmbracoBuilder()
    .AddBackOffice()
    .AddWebsite()
    .AddDeliveryApi()         // headless API
    .AddComposers()
    .Build();

WebApplication app = builder.Build();

await app.BootUmbracoAsync();

app.UseUmbraco()
    .WithMiddleware(u =>
    {
        u.UseBackOffice();
        u.UseWebsite();
    })
    .WithEndpoints(u =>
    {
        u.UseInstallerEndpoints();
        u.UseBackOfficeEndpoints();
        u.UseWebsiteEndpoints();
    });

await app.RunAsync();

Strongly-typed модели

Umbraco генерирует модели через ModelsBuilder. После настройки типов контента в backoffice:

dotnet run -- umbraco-models-builder generate

Использование в контроллере:

using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;

public class ArticleController : RenderController
{
    private readonly ILogger<ArticleController> _logger;

    public ArticleController(
        ILogger<ArticleController> logger,
        ICompositeViewEngine viewEngine,
        IUmbracoContextAccessor umbracoContextAccessor)
        : base(logger, viewEngine, umbracoContextAccessor)
    {
        _logger = logger;
    }

    [HttpGet]
    public IActionResult Index()
    {
        if (CurrentPage is not ContentModels.Article article)
        {
            return NotFound();
        }

        var viewModel = new ArticleViewModel
        {
            Title       = article.Title,
            Body        = article.Body,
            PublishDate = article.PublishDate,
            Author      = article.Author?.Name,
            Tags        = article.Tags?.Split(',').Select(t => t.Trim()).ToArray() ?? [],
        };

        return CurrentTemplate(viewModel);
    }
}

Razor View

@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ArticleViewModel>

@{
    Layout = "_Layout.cshtml";
}

<article class="article">
    <header>
        <h1>@Model.Title</h1>
        @if (Model.PublishDate.HasValue)
        {
            <time datetime="@Model.PublishDate.Value.ToString("yyyy-MM-dd")">
                @Model.PublishDate.Value.ToString("dd.MM.yyyy")
            </time>
        }
        @if (!string.IsNullOrEmpty(Model.Author))
        {
            <span class="author">@Model.Author</span>
        }
    </header>

    <div class="article__body">
        @Html.Raw(Model.Body)
    </div>

    @if (Model.Tags?.Length > 0)
    {
        <footer class="tags">
            @foreach (var tag in Model.Tags)
            {
                <a href="/[email protected](tag)">@tag</a>
            }
        </footer>
    }
</article>

Composers — настройка DI

using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;

public class SiteComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        builder.Services.AddScoped<IArticleService, ArticleService>();
        builder.Services.AddScoped<ISitemapService, SitemapService>();

        // регистрация обработчиков событий
        builder.AddNotificationHandler<ContentPublishedNotification, SearchIndexHandler>();
        builder.AddNotificationHandler<ContentSavedNotification, CacheInvalidationHandler>();
    }
}

Headless через Delivery API

Umbraco 12+ включает встроенный Delivery API:

// appsettings.json
{
  "Umbraco": {
    "CMS": {
      "DeliveryApi": {
        "Enabled": true,
        "PublicAccess": true,
        "ApiKey": "your-api-key",
        "DisallowedContentTypeAliases": ["settings", "internalPage"],
        "RichTextOutputAsJson": false
      }
    }
  }
}

Запросы к API:

GET /umbraco/delivery/api/v2/content?contentType=article&sort=createDate:desc&take=10
Authorization: Api-Key your-api-key

GET /umbraco/delivery/api/v2/content/item/my-article-slug

Ответ типизированный, включает свойства типа контента, медиафайлы, связи.

Surface Controller для форм

public class ContactFormController : SurfaceController
{
    private readonly IMailService _mailService;

    public ContactFormController(
        IUmbracoContextAccessor contextAccessor,
        IUmbracoDatabaseFactory databaseFactory,
        ServiceContext services,
        AppCaches appCaches,
        ILogger<ContactFormController> logger,
        IProfilingLogger profilingLogger,
        IPublishedUrlProvider publishedUrlProvider,
        IMailService mailService)
        : base(contextAccessor, databaseFactory, services, appCaches,
               logger, profilingLogger, publishedUrlProvider)
    {
        _mailService = mailService;
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Submit(ContactFormModel model)
    {
        if (!ModelState.IsValid)
        {
            return CurrentUmbracoPage();
        }

        await _mailService.SendContactEmailAsync(model);

        TempData["FormSuccess"] = true;
        return RedirectToCurrentUmbracoPage();
    }
}

Мультисайт

// один инстанс Umbraco, несколько сайтов
// Настраивается в backoffice: Content → правой кнопкой → "Allow as root"
// Для каждого корневого узла — свой домен в Domains

// Получение текущего сайта в шаблоне:
@inject IUmbracoContextAccessor UmbracoContext

@{
    var root = UmbracoContext.GetRequiredUmbracoContext()
                             .Content?
                             .GetAtRoot()
                             .First(n => n.IsAncestorOrSelf(Model.Content!));
    var siteName = root?.Value<string>("siteName");
}

Производительность

// appsettings.json — кэш
{
  "Umbraco": {
    "CMS": {
      "Runtime": {
        "Mode": "BackofficeDevelopment"
      },
      "WebRouting": {
        "DisableAlternativeTemplates": false,
        "DisableFindContentByIdentifierPath": false
      },
      "NuCache": {
        "BTreeBlockSize": 4096
      }
    }
  }
}

Umbraco использует NuCache (in-memory + disk) для хранения опубликованного контента — без обращений к БД при чтении публичных страниц.

Сроки

Корпоративный сайт 10–15 типов контента с кастомными шаблонами: 3–5 недель. С headless API, интеграцией со внешними сервисами, мультисайтом: 6–10 недель. Настройка существующего инстанса под новый дизайн — от 2 недель.