Dibakar
Dibakar

Reputation: 159

Cannot access a disposed object. Object name: 'FileBufferingReadStream' Error while uploading multiple files

I am trying to write a Razor Page which accepts multiple files and save them in a table. The Files uploaded through the following partial page -

@model CommonApplicationDTO
<table>
        <tr>
            <th>Name</th>
            <th>Date of Birth</th>
            <th>Guardian Name</th>
            <th>Mobile No</th>
            <th>Aadhaar/Birth Certificate</th>
            <th>Document Type</th>
            <th>File Upload</th>
        </tr>
    @for (var i = 0; i < Model.ApplctnDocuments.Count; i++)
        {
        var applicationDocument = Model.ApplctnDocuments[i];
        if (i < Model.ApplctnDocuments.Count - 1)
        {
            <tr>
                <td>@applicationDocument.Name</td>
                <td>@applicationDocument.DateofBirth.ToShortDateString()</td>
                <td>@applicationDocument.GuardianName</td>
                <td>@applicationDocument.MobileNo</td>
                <td>@applicationDocument.AadhaarBrthCertificate</td>
                <td>
                    <input type="hidden" name="ApplctnDocuments[@i].BeneficiaryId" value="@applicationDocument.BeneficiaryId" />
                    <input type="hidden" name="ApplctnDocuments[@i].BeneficiaryId" value="@applicationDocument.BeneficiaryId" />

                <select name="ApplctnDocuments[@i].SupportingDocumentType">
                    <option value="1" selected="@(applicationDocument.SupportingDocumentType == 1)">Aadhaar</option>
                    <option value="2" selected="@(applicationDocument.SupportingDocumentType == 2)">Birth Certificate</option>
                    </select>
                </td>
                <td>
                <input type="file" name="ApplctnDocuments[@i].SupportingDocument"  />
                </td>
            </tr>
        }
        else
        {
            <tr>
                <td colspan="6">
                    <label for="CommonDocument">Common Document:</label>
                    <input type="file" name="ApplctnDocuments[@i].SupportingDocument" />
                    <input type="hidden" asp-for="ApplctnDocuments[@i].DocumentType" />
                </td>
            </tr>
        }
    }
    
    </table>

The main page has the following html -

<form method="post" enctype="multipart/form-data">
<div>
                    @Html.Partial("_DocumentUploadPartial", Model.Application)
                </div>
<button type="submit" class="btn btn-primary" formnovalidate asp-page-handler="FileUpload">@Model.ButtonText</button>

</form>

ApplctnDocuments is an instance of the class

public class ApplicationDocumentDTO 
    {
        public int BeneficiaryId { get; set; }
        public Guid ApplicationNo { get; set; }
        public string Name { get; set; }
       //Other fields
        
        public IFormFile SupportingDocument { get; set;}
        public int SupportingDocumentType { get; set; }
        public int? DocumentType { get; set; } = 1;
    }

The Post handler calls a Repository function -

public async Task<Int64> InsertDocumentsAsync(Guid applicationNo,  List<ApplicationDocumentDTO> appDocument)
        {
            Int64 returnValue = 0;
            using (var connection = new SqlConnection(configuration.GetConnectionString("DBConnection")))
            {
                await connection.OpenAsync();
                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        foreach (var applicationDocument in appDocument)
                        {
                            using (var memoryStream = new MemoryStream()) // Create a new MemoryStream for each file
                            {
                                await applicationDocument.SupportingDocument.CopyToAsync(memoryStream);
                                var fileContent = memoryStream.ToArray();
                                var parameters = new
                                {
                                    ApplicationNo = applicationNo,
                                    BeneficiaryId = applicationDocument.BeneficiaryId,
                                    FileContent = fileContent,
                                    FileType = applicationDocument.IdentificationType,
                                    DocumentType = applicationDocument.DocumentType,
                                };

                                await connection.ExecuteAsync(RCApplicationQuery.InsertDocument, parameters, transaction: transaction, commandType: CommandType.Text);
                            }
                        } // end Document Files

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        return -1;
                        // Handle exception
                    }
                    finally
                    {
                        transaction.Dispose();
                    }
                }
            }
            return 1;
        }

However I am always getting an Error while trying to upload second file in the collection at the point -

await applicationDocument.SupportingDocument.CopyToAsync(memoryStream);

The error is -Cannot access a disposed object Object name: 'FileBufferingReadStream

StackTrace shows -

   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ThrowIfDisposed()
   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.set_Position(Int64 value)
   at Microsoft.AspNetCore.Http.ReferenceReadStream..ctor(Stream inner, Int64 offset, Int64 length)
   at Microsoft.AspNetCore.Http.FormFile.OpenReadStream()
   at Microsoft.AspNetCore.Http.FormFile.<CopyToAsync>d__25.MoveNext()
   at WBRationCardApplication.Infrastructure.Repositories.RCApplicationRepository.<InsertDocumentsAsync>d__4.MoveNext() in F:\mycode\RCApplication\WBRationCardApplication.Infrastructure\Repositories\RCApplicationRepository.cs:line 170

Any help will be appreciated.

NB - Although InsertDocumentsAsync Repository function is called through MediateR CommandHandler which has been removed here for simplicity.

Upvotes: 0

Views: 870

Answers (1)

Dibakar
Dibakar

Reputation: 159

I could not make it running using async processes. Hence the way out I used is -

using (var connection = new SqlConnection(configuration.GetConnectionString("DBConnection")))
            {
                await connection.OpenAsync();
                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        foreach (var applicationDocument in appDocument)
                        {
                            //using (var memoryStream = new MemoryStream()) // Create a new MemoryStream for each file
                            //{
                            var memoryStream = new MemoryStream();
                                 applicationDocument.SupportingDocument.CopyTo(memoryStream);
                                var fileContent = memoryStream.ToArray();
                            var parameters = new
                            {
                                ApplicationNo = applicationNo,
                                BeneficiaryId = applicationDocument.BeneficiaryId,
                                FileContent = fileContent,
                                FileType = applicationDocument.IdentificationType,
                                DocumentType = applicationDocument.DocumentType,
                            };

                            connection.ExecuteAsync(RCApplicationQuery.InsertDocument, parameters, transaction: transaction, commandType: CommandType.Text) ;
                            //}
                        } // end Document Files

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        return -1;
                        // Handle exception
                    }
                    finally
                    {
                        transaction.Dispose();
                    }
                }
            }

Upvotes: 1

Related Questions