Проекты ASP.NET Core 5 MVC / RazorPages и WebAPI в одном решении

Многие сайты разделены на две части:

  • www.example.com: общедоступный MVC / Серверное приложение RazorPages для гостей
  • app.example.com: частный WebAPI приложение для клиентов и администраторов (доступно через SPA)

Эти два приложения имеют много общего, например код, база данных, стили, поэтому было бы лучше иметь их в одном решении, возможно, разделенном на несколько проектов. Я полагаю, что это можно сделать, как-нибудь подправив стандартную конфигурацию (например, Startup.cs).

Документы не охватывают этот сценарий. Существуют различные решения этой проблемы, но они предназначены для более старые версии фреймворка.

Как это делается для ASP.NET Core 5?




Ответы (3)


Я бы сказал, что вы можете сделать это по-разному, в зависимости от ваших требований и того, как вы хотите стилизовать архитектуру вашего решения, процесс тестирования, развертывания и т. Д.


Одно единственное приложение

Вы можете просто предоставить как веб-API, так и приложение с интерфейсом в одном веб-проекте. Затем, например, сопоставив свои контроллеры, вы можете указать, что есть что.

  • Пример скаффолда контроллера API:
[ApiController]
[Area("api")]
[Route("[area]/[controller]")]
public class ResourceController : ControllerBase
{
    ...
}
  • Пример скаффолда контроллера WebApp:
public class FeatureController : Controller
{
    ...
}

(Обратите внимание, что для контроллера MVC требуется базовый класс Controller. Для контроллера API достаточно ControllerBase.)

Что касается Startup приложения, выполнения сопоставления по умолчанию между контроллерами и маршрутами может быть достаточно:

app.UseEndpoints(endpoint =>
{
    endpoint.MapDefaultControllerRoute();
});

При таком подходе вы даже можете, например, сопоставить разные классы промежуточного программного обеспечения в зависимости от маршрута:

app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
   {
       appBuilder.UseMiddleware<ApiRelatedMiddleware>();
   })
   .UseWhen(context => !context.Request.Path.StartsWithSegments("/api"), appBuilder =>
   {
       appBuilder.UseMiddleware<FrontEndRelatedMiddleware>();
   });

Что касается других нужд приложения, вы можете зарегистрировать нужные вам услуги.


Отдельные приложения:

Однако такой простой подход может привести к чрезмерной сложности вашего приложения, поскольку это всего лишь одно приложение, но такие вещи, как аутентификация, авторизация, ведение журнала или развертывание, например, могут иметь разные требования. Тестирование тоже бывает разным.

Более того, управление доступом и видимостью каждого маршрута также должно быть обеспечено в восходящем направлении.

По этим причинам и для более понятной архитектуры в большинстве случаев я бы предпочел разделить проекты.

По схеме из нескольких уровней или даже чистой архитектуры (Microsoft doc здесь) решит большинство проблем.

Общие части между приложениями, естественно, будут находиться на общих уровнях, поскольку они будут связаны, например, с бизнес-логикой или инфраструктурой. Затем оба веб-приложения могут ссылаться на требуемые проекты.

person N Pinheiro    schedule 14.01.2021

В качестве альтернативы двум другим отличным ответам вы можете дополнительно добавить проекты как Часть приложения.

Как и в документации, части приложения позволяют разделить контроллеры / представления / страницы / конечные точки ASP.NET на отдельные библиотеки и по-прежнему объединять их под одной крышей.

// MVC.csproj - Startup.cs
public void ConfigureServices(IServiceCollection services)
{
     services.AddControllersWithViews().AddApiControllers();
}

// Api.csproj - StartupExtensions.cs
public static void AddApiControllers(this IMvcBuilder builder)
{
    builder.AddApplicationPart(Assembly.GetExecutingAssembly());
}
person Ben Sampica    schedule 15.01.2021

Насколько мне известно, вы можете напрямую создать веб-контроллер api и контроллер MVC в одном проекте.

Поскольку веб-контроллер api будет иметь такие атрибуты, как [Route("api/[controller]")] и [ApiController].

В ядре asp.net, когда произошло сопоставление маршрута, он сначала найдет маршрут атрибута, а затем найдет сопоставление конечной точки в файле startup.cs, как показано ниже:

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=home}/{action=index}/{id?}");

        });
person Brando Zhang    schedule 14.01.2021