Answered by:
Upload image array with other fields, not just images.

Question
-
User-1209166642 posted
I currently have the following:
@page @model pcore31.AddimgModel @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Addimg</title> </head> <body> <h4>Petimg</h4> <hr /> <div class="row"> <div class="col-md-4"> <form enctype="multipart/form-data" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Petimg.PetName" class="control-label"></label> <input asp-for="Petimg.PetName" class="form-control" /> <span asp-validation-for="Petimg.PetName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Upload1" class="control-label"></label> <input asp-for="Upload1" class="form-control" type="file" /> </div> <div class="form-group"> <label asp-for="Upload2" class="control-label"></label> <input asp-for="Upload2" class="form-control" type="file" /> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-page="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} } </body> </html>
And code behind:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using pcore31.Models; using pcore31.Helpers; using System.IO; namespace pcore31 { public class AddimgModel : PageModel { private readonly pcore31.Models.DatabaseContext _context; private IWebHostEnvironment _environment; private string fileName; //private string filename; public AddimgModel(pcore31.Models.DatabaseContext context, IWebHostEnvironment environment) { _context = context; _environment = environment; } public IActionResult OnGet() { return Page(); } [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public IFormFile Upload1 { get; set; } [BindProperty] public IFormFile Upload2 { get; set; } // To protect from overposting attacks, enable the specific properties you want to bind to, for // more details, see https://aka.ms/RazorPagesCRUD. public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } int k = -1; int j = 0; string[] items = new string[2]; string[] newfile = new string[2]; Lqtest csql = new Lqtest(); var idcount = csql.Idcount(); string stringcount = idcount.ToString(); foreach (IFormFile postpic in Request.Form.Files) { k = k + 1; j = j + 1; string sj = j.ToString(); if (postpic == null) { items[k] = ""; newfile[k] = ""; } else { items[k] = postpic.Name.ToString(); int thisid = idcount + j; string thiscount = thisid.ToString(); var filename = $"{postpic.FileName}"; Array getparts = StrHelper.SplitString(filename); string parta = getparts.GetValue(0).ToString(); string partb = getparts.GetValue(1).ToString(); newfile[k] = parta + thiscount + "." + partb; var file = Path.Combine(_environment.ContentRootPath, "wwwroot\\images\\upload", newfile[k]); using (var fileStream = new FileStream(file, FileMode.Create)) { await postpic.CopyToAsync(fileStream); } } } Petimg.PetName = StrHelper.Ucfirst(Petimg.PetName); Petimg.Petpic1 = $"{newfile[0]}"; Petimg.Petpic2 = $"{newfile[1]}"; _context.Petimg.Add(Petimg); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); } } }
This all works.
My question is how do I convert this to an array, like:
@page @model pcore31.AddimgModel @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Addimg</title> </head> <body> <h4>Petimg</h4> <hr /> <div class="row"> <div class="col-md-4"> <form enctype="multipart/form-data" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Petimg.PetName" class="control-label"></label> <input asp-for="Petimg.PetName" class="form-control" /> <span asp-validation-for="Petimg.PetName" class="text-danger"></span> </div> <div class="form-group"> <input asp-for="Upload[]" class="form-control" type="file" /> </div> <div class="form-group"> <input asp-for="Upload[]" class="form-control" type="file" /> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-page="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} } </body> </html>
How do I change the binding to reflect an array of files:
// Currently I have: [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public IFormFile Upload1 { get; set; } [BindProperty] public IFormFile Upload2 { get; set; } // And what would this change to: foreach (IFormFile postpic in Request.Form.Files) ???
Thanks
And I am not wanting
type="file" multiple
I want the array, as files can come from more than one folder.
Thursday, May 14, 2020 11:17 PM
Answers
-
User-474980206 posted
Just give the file controls the same name, and the post back binding is an array. It doesn’t change the files collection.
[BindProperty] public IFormFile[] Uploads { get; set; }
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, May 15, 2020 1:27 AM -
User-2054057000 posted
You can upload any other files along with image file. There is no issues. You are using:
// Currently I have: [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public IFormFile Upload1 { get; set; } [BindProperty] public IFormFile Upload2 { get; set; }
It means you need to add 2 file controls by name of Upload1 and Upload2 in your view only then the Model Binding will work. If you don't want to restrict it then change them to List<IformFile> and use only one. So updated code will become:
// Currently I have: [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public List<IFormFile> Upload1 { get; set; } // remove the below property //[BindProperty] //public IFormFile Upload2 { get; set; }
Now in your view you can use use as many file controls you like to upload files. These file controls should have the same name as 'Upload1'.
Also take a look to some of the Advanced Model Binding Ways you can use in your ASP.NET Core app.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, May 15, 2020 4:50 AM
All replies
-
User-474980206 posted
Just give the file controls the same name, and the post back binding is an array. It doesn’t change the files collection.
[BindProperty] public IFormFile[] Uploads { get; set; }
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, May 15, 2020 1:27 AM -
User-2054057000 posted
You can upload any other files along with image file. There is no issues. You are using:
// Currently I have: [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public IFormFile Upload1 { get; set; } [BindProperty] public IFormFile Upload2 { get; set; }
It means you need to add 2 file controls by name of Upload1 and Upload2 in your view only then the Model Binding will work. If you don't want to restrict it then change them to List<IformFile> and use only one. So updated code will become:
// Currently I have: [BindProperty] public Petimg Petimg { get; set; } [BindProperty] public List<IFormFile> Upload1 { get; set; } // remove the below property //[BindProperty] //public IFormFile Upload2 { get; set; }
Now in your view you can use use as many file controls you like to upload files. These file controls should have the same name as 'Upload1'.
Also take a look to some of the Advanced Model Binding Ways you can use in your ASP.NET Core app.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, May 15, 2020 4:50 AM -
User-1209166642 posted
That works, seems slower. And weird, in php I am used of
<div><input name="ufile[]" type="file" id="ufile[]" size="50" /></div> <div><input name="ufile[]" type="file" id="ufile[]" size="50" /></div> But in .net core it's <div class="form-group"> <input asp-for="Upload1" class="form-control" type="file" /> </div> <div class="form-group"> <input asp-for="Upload1" class="form-control" type="file" /> </div> Upload1 instead of Upload1[] Weird it works. List instead of array. How would you use array instead.
Saturday, May 16, 2020 4:55 PM -
User-474980206 posted
The asp.net binding syntax is different than php. If you want array in the binding name include the index. If you don’t want to specify the index, don’t use the brackets. This because c# is strongly typed, and you declare the type of what you are binding to. It knows it’s an array. This is different than php which can build an anonymous type from the post data and use the binding name to know it’s an array. Also because backers are not allowed in Id names, asp.net convert them to underscore.
<div><input name="ufile[0]" type="file" id="ufile_0_" size="50" /></div> <div><input name="ufile[1]" type="file" id="ufile_1_" size="50" /></div>
Saturday, May 16, 2020 8:21 PM