У меня есть стороннее проприетарное приложение, для которого мне нужно написать конечную точку API в моем приложении веб-API ASP.NET Core 5.0.
Стороннее приложение отправляет почтовый запрос HTTP, содержащий только двоичные данные в теле запроса, наряду с типом контента application/x-www-form-urlencoded
или, иногда, application/octet-stream
(случайно, но данные одинаковы).
Мой обработчик действий выглядит так:
[Route("~/Validation")]
[ApiController]
public class ValidationController : ControllerBase
{
[HttpPost("{requestId}")]
[Consumes(@"application/octet-stream", @"application/x-www-form-urlencoded")]
[Produces(@"application/octet-stream")]
public async Task<IActionResult> Validation_Post([FromRoute] string requestId)
{
byte[] rawRequestBody = Array.Empty<byte>();
{
long streamInitialPos = 0;
if (Request.Body.CanSeek) // rewind for this read.
{
streamInitialPos = Request.Body.Position;
Request.Body.Seek(0, SeekOrigin.Begin);
}
using (var ms = new MemoryStream())
{
await Request.Body.CopyToAsync(ms);
rawRequestBody = ms.ToArray() ?? throw new NullReferenceException();
}
if (Request.Body.CanSeek) // rewind to initial position.
Request.Body.Seek(streamInitialPos, SeekOrigin.Begin);
}
// TODO: Handle rawRequestBody data.
return new FileContentResult(new byte[] { 1 }, @"application/octet-stream")
{
EnableRangeProcessing = true,
LastModified = DateTime.UtcNow
};
}
Когда стороннее приложение отправляет свой почтовый запрос HTTP на конечную точку моего API, мое приложение API аварийно завершает работу с System.ArgumentException
:
Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer: Error: Connection ID "18374686481282236432", Request ID "80000011-0000-ff00-b63f-84710c7967bb": An unhandled exception was thrown by the application.
System.ArgumentException: The key '[omitted binary data]' is invalid JQuery syntax because it is missing a closing bracket. (Parameter 'key')
at Microsoft.AspNetCore.Mvc.ModelBinding.JQueryKeyValuePairNormalizer.NormalizeJQueryToMvc(StringBuilder builder, String key)
at Microsoft.AspNetCore.Mvc.ModelBinding.JQueryKeyValuePairNormalizer.GetValues(IEnumerable`1 originalValues, Int32 valueCount)
at Microsoft.AspNetCore.Mvc.ModelBinding.JQueryFormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.TryCreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished HTTP/1.1 POST http://localhost:10891/validation/dummy application/x-www-form-urlencoded 11072 - 500 - - 164.0024ms
Журналы показывают, что используется правильное действие маршрута.
Как отключить автоматическую привязку модели только для этого конкретного обработчика действий?
Напоминание: я не могу вносить изменения в стороннее приложение. Я должен справиться с тем, что я получаю. Я знаю, что тип содержимого запроса неверен. Пожалуйста, не делайте никаких заметок по этому поводу.
Изменить: я обнаружил поверхностную причину этой ошибки. Когда я удаляю [FromRoute] string requestId
из сигнатуры функции, ошибка не возникает. Когда я повторно ввожу его, ошибка повторяется.
Не работает (вызывает внутреннее исключение ASP.NET Core):
public async Task<IActionResult> Validation_Post([FromRoute] string requestId)
Работает:
public async Task<IActionResult> Validation_Post()
Однако мне нужно получить доступ к переменной маршрута через Request.RouteValues["requestId"]
.
В любом случае, вопрос остается в силе: Как отключить автоматическую привязку модели только для этого конкретного обработчика действий?
ArgumentException
? А откудаstream
? - person mxmissile   schedule 19.12.2020stream
, я настолько сократил код, что добавил ошибки во фрагмент кода. Исходный код действия теперь исправлен, и я добавил в вопрос полную трассировку стека. - person burnersk   schedule 19.12.2020~
использовалось в маршрутизации, но если это работает, это хорошо для вас. - person Roar S.   schedule 19.12.2020~
относится к корневой точке mount (в отличие от/
для фактического корневого пути). Удаление[ApiController]
не помогло, см. обновление моего вопроса. - person burnersk   schedule 20.12.2020