Reputation: 159
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
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