Base solution for your next web application
Open Closed

Passing stream from controller to service #1619


User avatar
0
carelearning created

I am trying to stream a file to a service class (import). In this simplified example I am getting an error:

public class DepartmentController : AmsControllerBase
    {
        private readonly IDepartmentAppService _departmentAppService;

        public DepartmentController(IDepartmentAppService departmentAppService)
        {
            _departmentAppService = departmentAppService;
        }

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Import()
        {
            var data = System.IO.File.ReadAllBytes(@"c:\temp\departments.csv");

            var stream = new MemoryStream(data);
            _departmentAppService.Import(stream);//<--Exception throws here and method is not executed

            return null;
        }
    }

Controller base class is:

public abstract class AmsControllerBase : AbpController
    {
        protected AmsControllerBase()
        {
            LocalizationSourceName = AmsConsts.LocalizationSourceName;
        }

        protected void CheckErrors(IdentityResult identityResult)
        {
            identityResult.CheckErrors(LocalizationManager);
        }
    }

The error I get is:

Timeouts are not supported on this stream

Is there a different way I should be passing a stream around? The file's size is about 1 kb. Thanks again for your time and effort.


4 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Which version of ABP do you use ?

  • User Avatar
    0
    carelearning created

    @ismcagdas

    Sorry for the tardy reply and the long explanatory post to follow.

    To illustrate the problem I created a File->New Project->ASP.NET Web Application (.NET Framework)

    • Authentication: No Authentication
    • MVC: include
    • Web API: include

    Working Branch git clone <a class="postlink" href="http://git.carelearning.com/dxabp.git">http://git.carelearning.com/dxabp.git</a> example -b working

    When I build and run the Example project from the working branch; I select click "Upload", a DevExpress FileUploader widget, and navigate to an included sample file located at the [cloned-project-dir]\assets\departments.csv. This in return executes the controller's Upload method shown below.

    [HttpPost]
            public ActionResult Upload()
            {
                var file = Request.Files[0];
                if (file == null ||
                    file.ContentLength == 0)
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    
                var content = _departmentAppService.Upload(file.InputStream);
                return Content(content);
            }
    

    Here is the DepartmentAppService Upload method which uses Gembox.Spreadsheet and Json.Net.

    public string Upload(Stream stream)
            {
                SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
    
                var workbook = ExcelFile.Load(stream, LoadOptions.CsvDefault);
                var worksheet = workbook.Worksheets.ActiveWorksheet;
               
               // TODO optimize
                var dataTable = worksheet.CreateDataTable(new CreateDataTableOptions()
                {
                    ColumnHeaders = true
                });
    
                return JsonConvert.SerializeObject(dataTable, new DataSetConverter());
            }
    

    When I breakpoint and debug I see the expected Json content string.

    Broken Branch git clone <a class="postlink" href="http://git.carelearning.com/dxabp.git">http://git.carelearning.com/dxabp.git</a> example -b broken

    To prevent licensing issues when sharing this example code; yesterday I created a brand new Asp.Net Boilerplate project. I created a Custom controller with single Index view. I then transplanted the code from the Working project, slightly altering the code to use the idomatic Abp code and the suggested inheritance hierarchy. I also had to disable the CSRF/XSS protection according to this post.

    After building and setting Web as the Startup Project I run update-database -verbose -projectname EntityFramework to bootstrap the required database. The project uses (localdb) for the data source in the connection string.

    When running and selecting the same test file at[cloned-project-dir]\assets\departments.csv. The Upload method now throws the aforementioned ReadTimeout not supported exception (see attached screenshot, ReadTimeout_Exception.png).

    When searching the forums another user experienced this issue with Kendo Upload Widget. We tried the presented solution of adding MethodInvocationValidator.IgnoredTypesForRecursiveValidation.AddIfNotContains(typeof(HttpPostedFileWrapper)); in the Global.aspx code-behind in our real AbpZero project and it did not work. I also tried adding this code to this example project, however it would not compile. I left it in but commented out.

    Thank you for your time and an outstanding library.

    -Chris

  • User Avatar
    0
    carelearning created

    After scouring the Git repository's comment messages, I determined we had some out-of-date NuGet packages. I eventually updated all the packages except for EntityFramework.DynamicFilters. Next, I added the missing Changed_Code_MaxLength_Of_OrganizationUnit migration. Finally, I built and ran and the exception went away. I push the changes the broken branch of the example repo.

    I replicated the changes in our real project and after fixing several changes like; Clock.SupportsMultipleTimezone from a method to a property, renaming IdentityFrameworkClaimsAbpSession to ClaimsAbpSession and updating the CustomDtoMapper's CreateMappingsInternal method. I built and ran and the exception is gone.

    -Chris

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    First of all, thank you for your detailed work on this, it's really appreciated. I'm glad that you have solved the problem.

    By the way, ABP adds below 4 items to ignored types for validation and auditing.

    typeof(HttpPostedFileBase),
    typeof(IEnumerable<HttpPostedFileBase>),
    typeof(HttpPostedFileWrapper),
    typeof(IEnumerable<HttpPostedFileWrapper>)