Подтвердить что ты не робот

Как реализовать "чистый" ASP.NET Core Web API с помощью AddMvcCore()

Я видел много проектов ASP.NET Core Web API, которые используют службу по умолчанию AddMvc(), не понимая, что использование AddMvcCore() является превосходной опцией из-за контроля над службами.

Как именно вы реализуете ASP.NET Core Web API с помощью AddMvcCore() и , почему это лучше?

4b9b3361

Ответ 1

В чем разница между AddMvc() и AddMvcCore()?

Первое, что нужно понять, это то, что AddMvc() - это только предварительно загруженная версия AddMvcCore(). Вы можете увидеть точную реализацию расширения AddMvc() в репозитории GitHub.

Мне нравится использовать шаблоны VS по умолчанию, как и для следующего парня, но иногда вам нужно знать, когда это неправильный выбор. Я видел несколько руководств в Интернете, которые больше склоняются к попытке "отменить" эти службы по умолчанию, а не просто идти с решением, которое просто не реализует их в первую очередь.

С появлением ASP.NET Core, являющегося открытым исходным кодом, действительно нет веской причины, по которой мы не можем отслаиваться от слоя и работать на более низком уровне, не опасаясь потерять "волшебство".


Определение "минимального" и "чистого"

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

Этот ответ больше склоняется к "чистому", а не "минимальному". Я хотел бы описать, почему, так что яснее, о чем я говорю.

Минимальное. "Минимальное" решение будет реализацией, которая вообще не вызывает метод AddMvcCore() . Причиной этого является то, что MVC на самом деле не является "обязательным" компонентом для сборки вашего собственного веб-API, и, конечно же, он добавляет некоторый вес вашему коду с дополнительными зависимостями. В этом случае, поскольку вы не используете метод AddMvcCore(), вы также не вводите его в свое приложение, здесь

public void Configure(IApplicationBuilder app)
{
    app.UseMvc(); // you don't need this
}

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

public void Configure(IApplicationBuilder app)
{
    app.Map("/api", HandleMapApi);
    // notice how we don't have app.UseMvc()?
}    

private static void HandleMapApi(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        // implement your own response
        await context.Response.WriteAsync("Hello WebAPI!");
    });
}

Для многих проектов "минимальный" подход означает, что мы отказываемся от некоторых функций, найденных в MVC. Вам действительно нужно будет взвесить ваши варианты и посмотреть, правильно ли вы выбрали этот путь проектирования, так как существует баланс между шаблоном проектирования, удобством, ремонтопригодностью, защитой кода и, самое главное, производительностью и задержкой. Проще говоря: "минимальное" решение означает минимизацию сервисов и промежуточного программного обеспечения между вашим кодом и запросом.

Чистое. "Чистое" решение (в контексте этого ответа) заключается в том, чтобы избежать всех сервисов и промежуточного ПО по умолчанию, которые "предварительно упакованы" с помощью AddMvc(), не реализуя это в первую очередь. Вместо этого мы используем AddMvcCore(), что объясняется далее в следующем разделе:


Реализация наших собственных услуг/промежуточного программного обеспечения с помощью AddMvcCore()

Первое, на что нужно начать, - установить ConfigureServices на использование AddMvcCore(). Если вы посмотрите на репозиторий GitHub, вы увидите, что AddMvc() вызывает AddMvcCore() со стандартным набором услуг/промежуточного программного обеспечения:

Вот некоторые из услуг/промежуточного программного обеспечения, которые выделяются как "ненужные":

var builder = services.AddMvcCore();

builder.AddViews();
builder.AddRazorViewEngine();
builder.AddRazorPages();

Многие из этих служб по умолчанию отлично подходят для общего веб-проекта, но обычно нежелательны для "чистого" веб-API.

Ниже приведен пример реализации ConfigureServices с использованием AddMvcCore() для веб-API:

public void ConfigureServices(IServiceCollection services)
{
    // Build a customized MVC implementation, without using the default AddMvc(),
    // instead use AddMvcCore(). The repository link is below:
    // https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

    services
        .AddMvcCore(options =>
        {
            options.RequireHttpsPermanent = true; // this does not affect api requests
            options.RespectBrowserAcceptHeader = true; // false by default
            //options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

            // these two are here to show you where to include custom formatters
            options.OutputFormatters.Add(new CustomOutputFormatter());
            options.InputFormatters.Add(new CustomInputFormatter());
        })
        //.AddApiExplorer()
        //.AddAuthorization()
        .AddFormatterMappings()
        //.AddCacheTagHelper()
        //.AddDataAnnotations()
        //.AddCors()
        .AddJsonFormatters();
}

Реализация выше в основном дублирует метод расширения AddMvc(), однако я добавил несколько новых областей, чтобы другие могли видеть дополнительные преимущества этого.

  • Пользовательские форматы ввода/вывода.. Здесь вы можете использовать собственные оптимизированные сериализаторы (такие как Protobuf, Thrift, Avro и т.д.) вместо использования сериализации JSON (или хуже XML).
  • Обработка заголовка запроса. Вы можете убедиться, что заголовок Accept распознан или нет.
  • Управление авторизацией.. Вы можете реализовать свою собственную авторизацию или воспользоваться встроенными функциями.
  • ApiExplorer. Для некоторых проектов вы можете включить его, иначе некоторые WebAPI могут не захотеть этой функции.
  • Запросы на перекрестный поиск (CORS). Если вам нужна более расслабленная система безопасности в вашем WebAPI, вы можете включить ее.

Надеемся, что с помощью этого примера "чистого" решения вы можете увидеть преимущества использования AddMvcCore() и быть удобным с его использованием.

Если вы серьезно относитесь к контролю над производительностью и задержкой во время работы над веб-хостом ASP.NET Core, возможно, глубокое погружение в "минимальное" решение - это то, где вы имеете дело прямо на границе конвейера запросов, вместо того, чтобы позволить ему увязнуть с промежуточным программным обеспечением MVC.


Дополнительное чтение

Визуальный взгляд на то, как выглядит конвейер промежуточного ПО... Как и в моих определениях, меньшее количество слоев означает "минимальное" , тогда как "чистый" - это просто чистая версия MVC.

введите описание изображения здесь

Подробнее об этом читайте в документах Microsoft: Основы базового промежуточного уровня ASP.NET