Встроенная проверка .NET Minimal API перестает работать, если сопоставление конечных точек находится в сборке, отличной C#

Место общения программистов C#
Ответить
Anonymous
 Встроенная проверка .NET Minimal API перестает работать, если сопоставление конечных точек находится в сборке, отличной

Сообщение Anonymous »

Я использую встроенную минимальную проверку API (

Код: Выделить всё

AddValidation()
+ аннотации к данным/сгенерированные преобразователи).
У меня есть модульная установка с несколькими сборками:
  • Хост (

    Код: Выделить всё

    Host.Api
    ) — точка входа, где происходит подключение DI (

    Код: Выделить всё

    Program.cs
    )
  • Функция (

    Код: Выделить всё

    Feature.Users
    ) – содержит определения срезов/конечных точек + DTO
  • Shared (

    Код: Выделить всё

    Shared.Endpoints
    ) — содержит самоуверенные оболочки/соглашения MapPost (стиль CQRS).
Я ранее читал этот вопрос и использовал его, чтобы обеспечить работу проверки, когда конечные точки/DTO находятся в другой сборке:
Встроенная поддержка проверки для минимальных API
Этот вопрос помог мне понять, что метаданные проверки генерируются для каждой сборки, и мне может потребоваться зарегистрировать преобразователи из других сборок.
Сценарий № 1: конечная точка сопоставлена непосредственно в сборке объекта (работает)

Код: Выделить всё

// App.FeatureA
public static class FeatureAEndpoints
{
public static void Map(IEndpointRouteBuilder app)
{
app.MapPost("/items", (CreateItemRequest request) => Results.Ok());
}
}

public sealed class CreateItemRequest
{
[Required]
public string? Name { get; set; }
}
В App.Host проверка работает, если я объединяю преобразователи проверки из сборок функций:

Код: Выделить всё

builder.Services.AddValidation(options =>
{
foreach (var resolver in DiscoverResolvers(typeof(FeatureAEndpoints).Assembly))
options.Resolvers.Add(resolver);
});

static IEnumerable DiscoverResolvers(Assembly assembly) =>
assembly.GetTypes()
.Where(t => typeof(IValidatableInfoResolver).IsAssignableFrom(t)
&& !t.IsAbstract
&& t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => (IValidatableInfoResolver)Activator.CreateInstance(t)!);
Это соответствует тому, что описано в связанном вопросе.
Примечание: сборка функций также должна содержать вызов .AddValidation() (даже если на него нет прямых ссылок в моем коде!), чтобы генератор источника проверки работал для этой сборки; в противном случае может отсутствовать IValidatableInfoResolver, который можно было бы обнаружить при сканировании.
Например, мне пришлось добавить этот файл в эту сборку:

Код: Выделить всё

/// 
/// Required so validation source generation sees an .AddValidation() inside this assembly.
/// See https://github.com/dotnet/AspNetCore.Docs/issues/35090#issuecomment-3661156506
/// 
internal static class ValidationCodegenTrigger
{
public static IServiceCollection Trigger(this IServiceCollection services)
=> services.AddValidation();
}
Сценарий №2: конечная точка сопоставлена ​​с помощью общего общего расширения (прерывания проверки)
Теперь я перемещаю фактический вызов MapPost в общую библиотеку:

Код: Выделить всё

// App.FeatureA
public static class FeatureAEndpoints
{
public static void Map(IEndpointRouteBuilder app)
{
app.MapCommand("/items"); //it's calling an extension method
}
}

public sealed class CreateItemRequest
{
[Required]
public string? Name { get; set; }
}
А в другой сборке сопоставляется фактическая конечная точка и DTO принимается в конечную точку как общий TRequest:

Код: Выделить всё

// App.SharedEndpoints
public static class CommandEndpointExtensions
{
public static RouteHandlerBuilder MapCommand(
this IEndpointRouteBuilder app,
string pattern)
where TRequest : class
{
return app.MapPost(pattern, (TRequest request) => Results.Ok());
}
}
Наблюдаемое поведение:
  • Привязка JSON работает
  • Генерация OpenAPI работает
  • Конечная точка выполняется
  • Проверка больше не выполняется (недопустимые запросы не возвращают 400)
Даже если я оставлю преобразователь логика агрегации из сценария №1, проверка по-прежнему не срабатывает.
Вопросы

[*]Почему встроенная минимальная проверка API перестает работать в сценарии №2?
[*]Почему здесь недостаточно «сканировать и регистрировать преобразователи из других сборок»?
[*]Каковы правильные обходные пути и когда требуется каждый из них?


Подробнее здесь: https://stackoverflow.com/questions/798 ... ping-is-in
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»