HttpClient.PostAsync (UrlPath, stream) не может пересылать сообщения, отправленные потоком multipart / form-data, полученным в FileUpload HttpRequest - PullRequest
0 голосов
/ 11 октября 2019

Используя POSTMAN, я могу публиковать на http://XXXXXXXazurewebsites.net/api/Blob/UploadDoc с BODY, содержащим данные формы, которые представляют собой 2 текстовых поля и поток файлов. На самом деле, с помощью Postman тело может быть пустым, и оно все еще отправляет сообщения на конечную точку Api, как я подтвердил с точкой останова при удаленной отладке.

И код, использующий HttpClient, можетотправлять сообщения на конечную точку Api AspnetCore, когда она выполняется локально (т. е. http://localhost:8888/api/Blob/UploadDoc).

. Но когда тот же код конечной точки развернут в Azure, HttpClient.PostAsync получает 404 при отправке на тот же URL, что и Postman. в состоянии сделать запрос POST для.

ВОПРОС: Как это может работать на 2 экземплярах IISExpress, работающих локально, но не удается при развертывании в Azure?


Код клиента находится внутриметода [HttpPost] на контроллере в приложении Presentation App Svc, и перенаправляет запрос содержимого потока в контроллер Api, работающий в другом приложении Svc:

            HttpClient localclient = new HttpClient();
            //localclient.BaseAddress = new System.Uri("http://localhost:8888/api/"); //works posting to here
            localclient.BaseAddress = new System.Uri("http://XXXXXXXXX.azurewebsites.net/api/");  //404 posting to site on azure!
            HttpContent contentStream = new StreamContent(request.Body);
            await localclient.PostAsync("Blob/UploadDoc", contentStream); 

Я также пытался прочитать вПоток в виде байта [] и создание HttpContent из байта []. Но HttpClient.Post также получает 404, ala:

  var memstream = new MemoryStream();
  await request.Body.CopyToAsync(memstream);
  memstream.Position = 0;
  var contentba = new ByteArrayContent(memstream.ToArray());
  var response = await localclient.PostAsJsonAsync("Blob/UploadDoc", contentba);
  response.EnsureSuccessStatusCode();  // 404 when posting to site on Azure

Код API выглядит следующим образом:

        [HttpPost("UploadDoc")]
        [DisableFormValueModelBinding]
        public async Task<IActionResult> UploadBlobAsync()
        { 
        //work with Request  ...
        }

И браузер загружает файл ala:

<form id="uploadForm" action="https://AAAAAA.azurewebsites.net/api/Blob/UploadDoc" method="post"
      enctype="multipart/form-data" onsubmit="AJAXSubmit(this);return false;">
            <input id="submissionId" type="text" name="submissionId" maxlength="25" />
            <input id="file" type="file" name="file" />
    <input class="btn" type="submit" value="Upload"  />

</form>

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Я думаю, что это было вызвано тем, что в настройке Request.Body Position не было нуля или каким-то образом неправильно сформирован запрос, что, в свою очередь, приводит к тому, что целевой хост не считает, что запрос Post соответствует какой-либо из его конечных точек.

Если я сделаю запрос следующим образом, то он будет работать:

        public async Task<IActionResult> UploadAsync(HttpRequest request, HttpContext httpContext)
        {
            var requestMessage = new HttpRequestMessage();
            var requestMethod = request.Method;

            if (!HttpMethods.IsGet(requestMethod) &&
                !HttpMethods.IsHead(requestMethod) &&
                !HttpMethods.IsDelete(requestMethod) &&
                !HttpMethods.IsTrace(requestMethod))
            {
                request.EnableRewind();
                request.Body.Seek(0, SeekOrigin.Begin);
                var streamContent = new StreamContent(request.Body);
                requestMessage.Content = streamContent;
            }

            foreach (var header in request.Headers)
            {
                if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()))
                {
                    requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
                }
            }

            var uri = new Uri(Client.BaseAddress, "UploadDoc");
            requestMessage.Headers.Host = uri.Authority;
            requestMessage.RequestUri = uri;
            requestMessage.Method = new HttpMethod(request.Method);
            var response = await Client.SendAsync(requestMessage);

            httpContext.Response.RegisterForDispose(response);
            return new HttpResponseMessageResult(response);
      }
    public class HttpResponseMessageResult : IActionResult
    {
        private readonly HttpResponseMessage _responseMessage;

        public HttpResponseMessageResult(HttpResponseMessage responseMessage)
        {
            _responseMessage = responseMessage; // could add throw if null
        }

        public async Task ExecuteResultAsync(ActionContext context)
        {
            context.HttpContext.Response.StatusCode = (int)_responseMessage.StatusCode;

            foreach (var header in _responseMessage.Headers)
            {
                context.HttpContext.Response.Headers.TryAdd(header.Key, new StringValues(header.Value.ToArray()));
            }
            using (var stream = await _responseMessage.Content.ReadAsStreamAsync())
            {
                await stream.CopyToAsync(context.HttpContext.Response.Body);
                await context.HttpContext.Response.Body.FlushAsync();
            }
        }
    }
0 голосов
/ 14 октября 2019

Как вы развертываете в Azure Web Apps? Как и основные приложения asp.net, работающие в Azure Web Apps, размещаются на IIS. Таким образом, для настройки приложения в IIS необходим файл web.config.

Вы можете проверить этот файл в корневой директории своего сайта на Azure, если он находится в правильной конфигурации.

Вот пример файла web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
        </handlers>
        <aspNetCore processPath="dotnet" arguments=".\WebAppEver.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
   </system.webServer>
</configuration>
...