Розробка сайту на 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 моделі
│   ├── 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 тижнів.