Infragistics IgniteUI IGFileUpload не загружает файлы на сервер в ASP.NET MVC CORE 3.0 - PullRequest
1 голос
/ 21 октября 2019

Допустим, у меня есть простое Index.cshtml представление:

<link href="~/libs/JQueryUI/jquery-ui.css" rel="stylesheet" />
<link href="~/libs/infragistics/css/themes/infragistics/infragistics.theme.css" rel="stylesheet" />
<link href="~/libs/infragistics/css/structure/infragistics.css" rel="stylesheet" />

@using CommonLib.Source.Common.Converters
@using CommonLib.Source.Common.Extensions
@using Infragistics.Web.Mvc
@using Microsoft.AspNetCore.Http
@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<div id="chart" style="color: blue"></div>

<div id="indicator"></div>

<div id="igFileUpload" style="color: blue"></div>

<script src="~/libs/JQuery/jquery.js"></script>
<script src="~/libs/JQueryUI/jquery-ui.js"></script>
<script src="~/libs/infragistics/js/infragistics.core.js"></script>
<script src="~/libs/infragistics/js/infragistics.lob.js"></script>
<script src="~/libs/Lightweight-Charts/dist/lightweight-charts.standalone.development.js"></script>
<script src="~/MyScripts.js"></script>

@(
    Html.Infragistics().Upload()
        .ID("igFileUpload")
        .Mode(UploadMode.Multiple)
        .AutoStartUpload(true)
        .ProgressUrl(Context.GetAbsoluteUrl("~/IGUploadStatusHandler.ashx"))
        .UploadUrl(Context.GetAbsoluteUrl("~/Data/UploadedFiles")) // just use Url.Content for testing purposes
        .ControlId("serverID1")
        .Width("600px")
        .Render()
)

<div id="error-message" style="color: #FF0000; font-weight: bold;"></div>

<script type="text/javascript">
    $(function () {
        $("#igFileUpload").bind({ iguploadonerror: function (e, args) {
                $("#error-message").html(args.errorMessage).stop(true, true).fadeIn(500).delay(3000).fadeOut(500);
            }
        });
    });
</script>

Я также получил Startup.cs файл:

using System;
using System.IO;
using CommonLib.Source.Common.Utils;
using Infragistics.Web.Mvc;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;

namespace CryptoBotCoreMVC
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddMvc(option => option.EnableEndpointRouting = false);
            //services.Configure<UploadAppSettings>(options =>
            //{
            //    options.FileUploadPath = $@"{Directory.GetCurrentDirectory()}\Data"; //WebUtils.GetWebAppAbsolutePath("
            //}); // TODO: fu doesn't work | FileUploadPath is set in the View because it is too early to do it here
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider svp)
        {
            WebUtils.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>(), env); 
            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();

            app.UseStaticFiles();
            app.UseRouting();
            app.UseUploadModuleMiddleware();
            app.UseUploadHandlerMiddleware();
            app.UseFileServer(new FileServerOptions
            {
                FileProvider = new PhysicalFileProvider($@"{Directory.GetCurrentDirectory()}\Data"),
                RequestPath = "/Data",
                EnableDirectoryBrowsing = true
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Ссылка здесь: https://www.igniteui.com/help/using-igniteui-controls-in-asp.net-core-1.0-project

Для безопасности я установил максимальный размер файла в web.config:

<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="1073741824" /> <!-- 1 GB -->
  </requestFiltering>
</security>

и в IIS:

enter image description here

ЭтоФиддлер показывает:

enter image description here

1-й:

enter image description here

2-йи 3-й:

enter image description here

В соответствии с этим:https://www.igniteui.com/help/igupload-using-http-handler-and-modules
Ошибка означает:

Status: 3 - File not found - this status is used when it is not found such key in the dictionary
Error: 5 - File does not exist with the specified key in the request

Вот сам результат:

enter image description here

Здесьявляется справочной для контрольной документации (некоторые из них не применимы для ASP.NET CORE):

https://www.igniteui.com/help/igupload-iguploadhttps://www.igniteui.com/file-upload/overview

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

/ EDIT

В соответствии с предложением @MasLoo я реализовал промежуточное программное обеспечение для замены явно необходимого IgnoreRoute, но мне не удалосьчтобы понять, как бросок 404 непосредственно из него может заставить обработчик работать:

(...)
app.UseMiddleware<IgnoreRouteMiddleware>();
(...)

:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace CryptoBotCoreMVC.Middlewares
{
    public class IgnoreRouteMiddleware
    {
        private readonly RequestDelegate _next;

        public IgnoreRouteMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("IGUploadStatusHandler.ashx"))
            {
                context.Response.StatusCode = 404;
                return;
            }

            await _next.Invoke(context);
        }
    }
}

После выполнения теста он действительно выбрасывает 404 сразу, фактически дважды:

enter image description here

При комментировании:

//context.Response.StatusCode = 404;

Скрипач ловит это:

enter image description here

со следующим сообщением:

enter image description here

Я не публиковал сообщения, потому что они точно такие же, как и первоес Content-Length: 0.

Будем тепло приветствовать дальнейшие идеи.

// РЕДАКТИРОВАТЬ 2

Я думаю, что я почти на месте, но не совсем. Я заметил, что по какой-то причине, если я оставлю URL по умолчанию, IF Code вместо поиска папки для файлов в UploadUrl ищет путь ig_fua34sf345sdf13sdf3454erdsf2345asd3425df5235d54df345.aspx, поэтому я изменил свой HtmlHelper на:

Html.Infragistics().Upload()
    .ID("igFileUpload")
    .Mode(UploadMode.Multiple)
    .AutoStartUpload(true)
    .ProgressUrl(Context.GetAbsoluteUrl("~/IGUploadStatusHandler.ashx"))
    .UploadUrl(Context.GetAbsoluteUrl("~/ig_fua34sf345sdf13sdf3454erdsf2345asd3425df5235d54df345.aspx"))
    .ControlId("serverID1")
    .Width("600px")
    .Render()

и теперь я получаю 500 с:

enter image description here

со следующей трассировкой стека:

HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Thu, 21 Nov 2019 00:17:16 GMT
Content-Length: 1398

System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
   at Microsoft.AspNetCore.Server.IIS.Core.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at Microsoft.AspNetCore.Server.IIS.Core.WrappingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at Infragistics.Web.Mvc.MiddleWare.UploadModuleMiddleware.ReadFully(Stream input)
   at Infragistics.Web.Mvc.MiddleWare.UploadModuleMiddleware.Invoke(HttpContext context)
   at CryptoBotCoreMVC.Middlewares.IgnoreRouteMiddleware.Invoke(HttpContext context) in <Path>\CSharp\Projects\CryptoBotCoreMVC\CryptoBotCoreMVC\Middlewares\IgnoreRouteMiddleware.cs:line 23
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 244
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3RFkBWmZhhsbjzXr
Host: localhost
Pragma: no-cache
Referer: http://localhost/CryptoBotCoreMVC
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36
Sec-Fetch-Mode: cors
Origin: http://localhost
Sec-Fetch-Site: same-origin

Теперь мы получаем что-тоПохоже, что в этом случае достаточно изменить конфигурацию Kestrel или IIS:

services.Configure<KestrelServerOptions>(options =>
{
    options.AllowSynchronousIO = true;
});
services.Configure<IISServerOptions>(options =>
{
    options.AllowSynchronousIO = true;
});

и это действительно так, я скоро опубликую подробный ответ.

1 Ответ

1 голос
/ 22 октября 2019

Для того, чтобы IgUpload Управление из IgniteUI работало с ASP.NET CORE MVC 3.0, вам необходимо выполнить следующие шаги (Однако учтите, что он по-прежнему не выполняет потоковую передачу больших файлов в чанках, см. эта статья (которая не была обновлена ​​для ASP.NET CORE)):

  1. Добавить Infragistics.Web.AspNetCore и IgniteUI NuGet пакеты ИЛИ добавить сценарии, .css файлыи .dll файл вручную из вашей установочной папки Infragistics как зависимости:

    enter image description here

  2. Установить maxAllowedContentLength в web.config файл:

    enter image description here

  3. Набор Maximum allowed content length (Bytes) in IIS: CTRL + R> inetmgr> <Server or Website>> IIS Category> RequestFiltering> Actions Pane (to the right side)> Edit Feature Settings...

  4. Включить options.AllowSynchronousIO = true в ваш файл Startup.cs для Kestrel и / или IIS для предотвращенияMiddleware от выброса Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead исключение.

  5. Установите maxFileSizeLimit в положительное значение, потому что, несмотря на утверждение документации, оно не будет работать для больших файлов, если вы установите его в null, -1 или если вы вообще не установите эту опцию.

  6. Установите FileUploadPath в качестве физического каталога на диске приложения (не виртуального).

    enter image description here

  7. Визуализация элемента управления, включая параметры ProgressUrl, UploadUrl и ControlID, и установка для них точных значений, отображаемых ниже, чтобы Middleware не генерировал различные неявные 404 ошибки (примеры кода будут включенынижняя часть этого ответа).

    enter image description here

  8. Получите желаемый результат:

    enter image description here

ВАЖНО: IgnoreRoute НЕ требуется!

Образцы кода:

Startup.cs:

using System.IO;
using Infragistics.Web.Mvc;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace IgUpload
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => options.EnableEndpointRouting = false);
            services.Configure<KestrelServerOptions>(options => options.AllowSynchronousIO = true);
            services.Configure<IISServerOptions>(options => options.AllowSynchronousIO = true);
            services.Configure<UploadAppSettings>(options =>
            {
                options.maxFileSizeLimit = "1073741824"; // 1 GB
                options.FileUploadPath = $@"{Directory.GetCurrentDirectory()}\Data\UploadedFiles";
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseUploadModuleMiddleware();
            app.UseUploadHandlerMiddleware();
            app.UseMvc(routes => routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"));
        }
    }
}

Index.cshtml:

@using Infragistics.Web.Mvc
@using Microsoft.AspNetCore.Http
@{
    ViewData["Title"] = "Index";
}

<div id="igFileUpload"></div>

<script src="~/libs/JQuery/jquery.js"></script>
<script src="~/libs/JQueryUI/jquery-ui.js"></script>
<script src="~/libs/infragistics/js/infragistics.core.js"></script>
<script src="~/libs/infragistics/js/infragistics.lob.js"></script>

@(
    Html.Infragistics().Upload()
        .ID("igFileUpload")
        .Mode(UploadMode.Multiple)
        .AutoStartUpload(true)
        .ProgressUrl(Url.Content("~/IGUploadStatusHandler.ashx"))
        .UploadUrl(Url.Content("~/ig_fua34sf345sdf13sdf3454erdsf2345asd3425df5235d54df345.aspx"))
        .ControlId("serverID1")
        .Width("600px")
        .Render()
)

<div id="error-message" style="color: #FF0000; font-weight: bold;"></div>

<script type="text/javascript">
    $(function () {
        $("#igFileUpload").bind({ iguploadonerror: function (e, args) {
                $("#error-message").html(args.errorMessage).stop(true, true).fadeIn(500).delay(3000).fadeOut(500);
            }
        });
    });
</script>
...