ASP.NET MVC Two file upload, different destinations - asp.net-mvc

I'm trying to upload two different files into two different database fields on same form.
------------------------------------
reportid | name | image | template |
------------------------------------
this is the table look. So I want to upload files to image and template. My model:
public class Report
{
[Key]
public int ReportID { get; set; }
[Required]
public string Name { get; set; }
public byte[] Image { get; set; }
public byte[] Template { get; set; }
}
My Create method in controller:
public ActionResult Create(Report report, HttpPostedFileBase file, HttpPostedFileBase temp)
{
if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
report.Image = ms.GetBuffer();
}
}
if (temp != null && temp.ContentLength > 0)
{
using (MemoryStream ms1 = new MemoryStream())
{
temp.InputStream.CopyTo(ms1);
report.Template = ms1.GetBuffer();
}
}
db.Reports.Add(report);
db.SaveChanges();
db.Configuration.ValidateOnSaveEnabled = true;
return RedirectToAction("Index");
}
And part of view concerning uploads:
<div class="editor-label">
<%:Html.LabelFor(model => model.Image) %>
</div>
<div class="editor-field">
<input type="file" id="fuImage" name="file" />
</div>
<div class="editor-label">
<%:Html.Label("Template") %>
</div>
<div class="editor-field">
<input type="file" id="temp" name="temp"/>
</div>
<p>
<input type="submit" value="Create" />
</p>
I'm quite stuck in this since I can not use IEnumerable<HttpPostedFileBase> files as a parameter in Create method because I need to save it in a different field, or can I? How should I approach this? Please help :S
Note: Image upload works fine.

Why not use IEnumerable<HttpPostedFileBase> ? You may use it like this.
[HttpPost]
public ActionResult Create(Report report, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
//Let's take first file
if(files.ElementAt(0)!=null)
{
var file1=files.ElementAt(0);
if (file1!= null && file1.ContentLength > 0)
{
//do processing of first file
}
}
//Let's take the second one now.
if(files.ElementAt(1)!=null)
{
var temp =files.ElementAt(1);
if (temp!= null && temp.ContentLength > 0)
{
//do processing of second file here
}
}
}
//Do your code for saving the data.
return RedirectToAction("Index");
}
EDIT : After seeing your View Markup in your EDIT.
The name of the file input element should be same as the parameter name in your action method. (files in this example)
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<b>File 1</b>
<input type="file" name="files" id="file1" />
<b>File 2</b>
<input type="file" name="files" id="file2" />
<input type="submit" />
}
This code assumes that read ONLY the first 2 entries from the collection.Since you wanted only 2 files, i hardcoded the indexes.
Phil has a nice blog post explaining about it very nicely.

Related

Photo Upload Problem in ASP.NET MVC My Blog Project

When I upload a photo, the page just refresh, not upload the photo in ASP.NET MVC My Blog Project. I looked the solution in Stack OverFlow but I didn't handle this problem. I don't know to write which code here because I am firstly trying to make a blog site in ASP.NET. If you are ask to me whatever code, I publish here quickly. Thanks for cooperation.
Say for example your model is
public class blog
{
public int Id { get; set; }
public string Code { get; set; }
public string Photo1 { get; set; }
}
Here I'm storing the photo in the server (Not in the database)
There goes the controller
public ActionResult BeginUploadPhoto(int Id)
{
var Blog= db.blog.Where(a => a.Id == Id).FirstOrDefault();
return View(Blog);
}
public ActionResult UploadPhoto(int? Id, HttpPostedFileBase Logo)
{
BlogCP = db.Blog.Find(Id);
WebImage img = new WebImage(Logo.InputStream);
if (img.Width > 500)
img.Resize(500, 500);
// to reduce the size upon upload
string extension = Path.GetExtension(Logo.FileName);
// get your photo extenstion
string filename = Guid.NewGuid().ToString();
// rename the upload photo
var path = Path.Combine(Server.MapPath("~/BlogPhoto/"), filename + extension);
// make sure that you create a folder BlogPhoto in your project or you can
//name it anything you like
string savepath = "~/BlogPhoto/" + filename + extension;
BlogCP.Photo1= savepath;
img.Save(path);
// save photo in your server
if (ModelState.IsValid)
{
db.Entry(BlogCP ).Property(r => r.Photo1).IsModified = true;
db.SaveChanges();
return RedirectToAction("Index","Staff");
}
return RedirectToAction("Index");
}
There goes the View
#model ProjectName.Entities.Blog
#{
ViewBag.Title = "BeginUploadPhoto";
}
<div class="container">
#if (Model.Photo1 != null)
{
<img id="Preview" class="img-thumbnail" src=#Model.Photo1/>
}
#using (Html.BeginForm("UploadPhoto", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
{
#Html.HiddenFor(m => m.Id)
<div>
<a>Select and upload Photo</a>
<input type="file" id="Logo" name="Logo"
<input type="file" id="Logo" name="Logo" accept="image/*" onchange="loadFile(event)">
</div>
<div class="form-group">
<button id="btnUpload"
class="btn btn-sm btn-primary"
formnovalidate="formnovalidate"
data-pdsa-action="upload">
<i class="glyphicon glyphicon-upload"></i>
Upload
</button>
</div>
}
}

Upload Image in Asp.Net Core?

I want to upload image in "wwwroot/uploads/img" folder but i get error.I wrote the following code:
Create View :
#model imageuploader.Models.Employee
<form method="post" enctype="multipart/form-data" asp-controller="Employee" asp-action="Create">
<div class="form-group">
<div class="col-md-10">
<input asp-for="FirstName" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input asp-for="LastName" Class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input asp-for="ImageName" type="file" Class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Create" />
</div>
</div>
Model :
public class Employee
{
[Key]
public int ID { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string ImageName { get; set; }
}
Controller
private readonly RegisterDBContext _context;
private readonly IHostingEnvironment _appEnvironment;
public EmployeeController(RegisterDBContext context, IHostingEnvironment appEnvironment)
{
_context = context;
_appEnvironment = appEnvironment;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Employee emp)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
foreach (var Image in files)
{
if (Image != null && Image.Length > 0)
{
var file = Image;
//There is an error here
var uploads = Path.Combine(_appEnvironment.WebRootPath, "uploads\\img");
if (file.Length > 0)
{
var fileName = Guid.NewGuid().ToString().Replace("-", "") + Path.GetExtension(file.FileName);
using (var fileStream = new FileStream(Path.Combine(uploads, fileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
emp.BookPic = fileName;
}
}
}
}
_context.Add(emp);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
else
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
}
return View(emp);
}
When i click on submit button i get an error (error line is marked), how can i upload image or file in Specified path?
Error:
NullReferenceException: Object reference not set to an instance of an object.
imageuploader.Controllers.EmployeeController+<Create>d__2.MoveNext() in EmployeeController.cs
var uploads = Path.Combine(_appEnvironmen.WebRootPath, "uploads\\img\\");
How can i upload image correctly in Specified path?
I Solved it. I understood i initial bad
_appEnvironment
in Constructor.
With repeated edits, all of the codes in question are currently correct.
Thanks #Shyju user.
Here is how to upload an image in C# Asp.net core Web Application 2.1 MVC:
First I'm assuming you've created a model, added to db and now working in the controller.
I've created a Person model
person model
For create get:
//Get : Person Create
public IActionResult Create()
{
return View();
}
post Action (please see screen shot)
create post action method
Finally the view
Create View
Project Output:
Here is the output of my project

How to pass a complex model back to the controller in asp.net mvc

New to web development.
I have a view that allows user to select an excel file.
When submit "preview" button is pressed file is read and data is sent back to the user to preview the data.
Then I want to be able send the model back to the control for db upload.
(this is the part I'm struggling with).
ViewModel:
public class UploadItemsViewModel
{
public List<Item> Items { get; set; }
public int CompanyID { get; set; }
public Company Company { get; set; }
public HttpPostedFileBase upload { get; set; }
public UploadJournalsViewModel()
{
Items = new List<Item>();
}
}
Controller:
public ActionResult Upload(FormCollection formCollection, int CompanyID)
{
if (Request != null)
{
HttpPostedFileBase file = Request.Files["UploadedFile"];
if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName))
{
string fileName = file.FileName;
string fileContentType = file.ContentType;
byte[] fileBytes = new byte[file.ContentLength];
var data = file.InputStream.Read(fileBytes, 0, Convert.ToInt32(file.ContentLength));
}
}
UploadItemsViewModel itmViewModel = new UploadItemsViewModel { Company = db.Companies.Find(CompanyID), CompanyID = CompanyID };
return View(itmViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(UploadItemsViewModel itmViewModel, string Preview, string Upload)
{
if (ModelState.IsValid)
{
if (itmViewModel.upload != null && itmViewModel.upload.ContentLength >0)
{
try
{
itmlViewModel.Items = App.Services.ItemsMassUploadFileRead.ReadExcelFile(itmViewModel.upload, db.Companies.Find(itmViewModel.CompanyID));
if (string.IsNullOrEmpty(Preview))
{
foreach (var itm in itmViewModel.Items)
{
itm.StartDate = DateTime.Today;
itm.CompanyID = itmViewModel.CompanyID;
itm.User = null;
itm.Items.Add(itm);
db.SaveChanges();
}
return View();
}
else
{
return View(itmViewModel);
}
} }
catch (Exception ex)
{
ModelState.AddModelError("File", ex.Message.ToString());
return View(itmViewModel);
}
}
else
{
ModelState.AddModelError("File", "Please Upload Your file");
}
}
return View(itmViewModel);
}
View:
#using (Html.BeginForm("Upload", "ItemsUpload", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.CompanyID)
<div class="form-group">
<div class="input-group">
<label class="input-group-btn">
<span class="btn btn-default">
Browse… <input type="file" style="display: none;" accept=".xlsx" name="upload">
</span>
</label>
<input type="text" class="form-control " readonly>
</div>
<span class="help-block">
Please use a provided Excel template
</span>
</div>
<div class="form-group">
<input type="submit" value="Preview" name ="Preview" class="btn btn-default" disabled style="display: none" id="submit"/>
</div>
<div class="form-group">
<input type="submit" value="Upload" name="Upload" class="btn btn-default" id="Upload" />
</div>
<div class="help-block" id="previewHelp" style="display: none">
Preview results and scroll down to upload data to the database.
</div>
if (Model.Journals.Count != 0)
{
table here to preview the upload
}
After clicking the Upload button model comes back without the "items" collection.
The Items list will be always null in the controller, because you don't rendered any input on the View with the name Items

List of uploaded files with ASP.MVC 5 is empty

I have a webform where I want to select a list of files, enter some additional informations and submit the whole bundle. The controller should than process the list of files according to the additionally entered datas. Therefore, I want to bundle all in one Model:
public class MyModel
{
public string AdditionalInformations { get; set; }
public int AdditionalInformationsId { get; set; }
public IEnumerable<HttpPostedFile> Files { get; set; }
}
public class MyController: Controller
{
[HttpPost]
public ActionResult UploadFile(MyModel Model)
{
switch(Model.AdditionalInformationsId)
{
case 1:
// do something with Model.Files
case 2:
// do something else with Model.Files
...
}
RedirectToAction("Index");
}
}
My view looks like
#model MyProgram.Models.MyModel
#using MyProgram.Models
#using (Html.BeginForm("UploadFile", "MyController", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<div class="row">
<div class="col-sm-6">
<input type="file" name="Files" multiple />
</div>
<div class="col-sm-6"></div>
</div>
<div class="row">
<div class="col-sm-3">
#Html.DropDownListFor(model => model.AdditionalInformationsId,
((MyDropDownList)Session["DDLists"]).companies,
Model.AdditionalInformation,
new { #class = "form-control", id = "ReceivingCompany" })
</div>
<div class="col-sm-3">
<br />
<button class="btn btn-default" type="submit">Upload</button>
</div>
<div class="col-sm-6"></div>
</div>
}
If I now use the submit-Button, the model is sent to the controller. E.g. AdditionalInformationsId has the value entered in the form. But IEnumerable Files is allways empty, except if I submit the form without choosing any files for upload, in that case the list contains a null-object. Also adding the attribute id="Files" to the multiple-file input-tag does not work.
I can't find the error. Is there maybe a setting I have to set in the web.config?
Change your property type to IEnumerable of HttpPostedFileBase
public IEnumerable<HttpPostedFileBase> Files { get; set; }
Now the posted files will be mapped to the Files property in your HttpPost action.

Passing Values from the SelectList Items Using ViewModel

I'd like to get the values of the selected items in dropdownlists. I am saving the files into the database with the following code:
public ActionResult UploadDoc(IEnumerable<HttpPostedFileBase> files)
{
foreach (var file in files)
{
if (file != null && file.ContentLength > 0)
{
byte[] data = new byte[file.ContentLength];
file.InputStream.Read(data, 0, file.ContentLength);
Document doc = new Document
{
UploadedOn = DateTime.Now,
MimeType = file.ContentType,
UserName = User.Identity.Name,
Data = data,
FromLanguage = 1,
ToLanguage = 2
};
dbContext = new MedicalDb();
dbContext.Documents.Add(doc);
dbContext.SaveChanges();
}
}
return RedirectToAction("Index");
}
but, I'd also like to get the selected values from the dropdownlists so that I can populate the FromLanguage and ToLanguage properties of the documents. I guess I'd need a viewmodel, but don't know how to do it. New rows for document upload are added using jQuery and names of the ddls are "ddlFromLanguage1", "ddlFromLanguage2", "ddFromLanguage3", and "ddlToLanguage1", "ddlToLanguage2", "ddlToLanguage3", etc. Thanks in advance for any help.
<form action="UploadDoc" method="post" enctype="multipart/form-data">
<table id="tblUploadDocs">
<tr id="row1">
<td><input type="file" name="files" id="file1" /></td>
<td>Bu dilden</td>
<td>#Html.DropDownList("ddlFromLanguage1", ViewBag.Languages as SelectList)</td>
<td>şu dile çevrilecek</td>
<td>#Html.DropDownList("ddlToLanguage1", ViewBag.Languages as SelectList)</td>
</tr>
</table>
<br />
Yeni dosya ekleyin
<input type="submit" />
</form>
Any form that is posted back returns a FormCollection to the controller in addition to model related values.
For example
//In your view
#using (Html.BeginForm("CountrySelect", "Country", FormMethod.Post))
{
#Html.AntiForgeryToken()
<select name="country" id="country-select">
<option value="selector">Pick a Country</option>
<option value="England">England</option>
<option value="England">England</option>
</select>
}
//In controller
//This will get you the name of the selected country from your form
[HttpPost]
Public ActionResult CountrySelect(FormCollection formData)
{
string country = formData["country"].toString();
}
I think you need to look at good example and do the same or very similar to them.
Take a look at these:
ASP.NET MVC 3 Viewmodel Pattern
Implementing Dropdownlist on Asp.net MVC 3 from viewModel
These should get you going.
Please let me know if you don't succeed or if what I gave you was actually helpful.
Thanks
The solution:
The viewmodel:
public class CustomerDocUploadViewModel
{
public HttpPostedFileBase File { get; set; }
public int FromLanguage { get; set; }
public int ToLanguage { get; set; }
}
The view:
#model IList<Models.ViewModels.CustomerDocUploadViewModel>
...
<form action="UploadDoc" method="post" enctype="multipart/form-data">
<table id="tblUploadDocs">
<tr id="row1">
<td><input type="file" name="[0].File" /></td>
<td>Bu dilden</td>
<td>#Html.DropDownList("[0].FromLanguage", ViewBag.Languages as SelectList)</td>
<td>şu dile çevrilecek</td>
<td>#Html.DropDownList("[0].ToLanguage", ViewBag.Languages as SelectList)</td>
</tr>
</table>
<br />
<a id="lnkAdd" href="javascript:addRow();" style="margin:10px 0;">Yeni dosya ekleyin</a>
<input type="submit" />
</form>
and finally the action method in the controller:
[HttpPost]
public ActionResult UploadDoc(IList<CustomerDocUploadViewModel> docInfos)
{
for (int i = 0; i < docInfos.Count; i++)
{
if (docInfos.ElementAt(i).File != null && docInfos.ElementAt(i).File.ContentLength > 0)
{
byte[] data = new byte[docInfos.ElementAt(i).File.ContentLength];
docInfos.ElementAt(i).File.InputStream.Read(data, 0, docInfos.ElementAt(i).File.ContentLength);
// Save the file into the database
Document doc = new Document
{
UploadedOn = DateTime.Now,
MimeType = docInfos.ElementAt(i).File.ContentType,
UserName = User.Identity.Name,
Data = data,
FromLanguage = docInfos.ElementAt(i).FromLanguage,
ToLanguage = docInfos.ElementAt(i).ToLanguage
};
dbContext = new MedicalDb();
dbContext.Documents.Add(doc);
dbContext.SaveChanges();
}
}
return RedirectToAction("Index");
}

Resources