Edit and display entity images - c#

I want to be able to replace my old images with a new. I got one to many relationship between entites -> many images for one product.
If I change images, old are staying in database. They will be never used. After some time the database is able to make huge itself. How to delete these old files ?
public ActionResult Edit(int? id)
{
if (id == null)
{ return new HttpStatusCodeResult(HttpStatusCode.BadRequest); }
Product product = db.Products.Include(p => p.FilePaths).Where(i => i.ProductId == id).Single();
if (product == null)
{ return HttpNotFound(); }
return View(product);
}
[HttpPost]
public ActionResult Edit(int id, IEnumerable<HttpPostedFileBase> uploads)
{
var product = db.Products.Include(p => p.FilePaths).Where(p => p.ProductId == id).Single();
if (ModelState.IsValid)
{
try
{
product.FilePaths = new List<FilePath>();
foreach (var upload in uploads)
{
if (upload != null && upload.ContentLength > 0)
{
var photo = new FilePath
{
FileName = Path.GetFileName(upload.FileName),
FileType = FileType.Photo
};
product.FilePaths.Add(photo);
upload.SaveAs(Path.Combine(Server.MapPath("~/Content/Images"), photo.FileName));
}
}
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException)
{
ModelState.AddModelError("", "Unable to save changes. Contact with administrator.");
}
}
return View(product);
}
My view for Edit() is:
#model Domain.Entities.Product
#using (Html.BeginForm("Edit", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) {
// code ommited for brevity..
<div class="row">
#Html.Label("Images:", new { #class = "control-label col-md-2" })
<div class="col-md-1">
<input type="file" name="uploads" id="upload1" />
</div>
<div class="col-md-offset-2 col-md-1">
<input type="file" name="uploads" id="upload2" />
</div>
<div class="col-md-offset-2 col-md-1">
<input type="file" name="uploads" id="upload3" />
</div>
</div>
//code ommited for brevity..
Also if somebody could tell me how to change this properly I would be grateful.
I am getting first image of product as many times as many images a product got. I want to display all images once.
I am in trouble with a directory to images.
<div class="row">
<label class="control-label col-md-2"> Obecne zdjęcia:</label>
#foreach (var item in Model.FilePaths)
{
<div class="col-md-offset-1 col-md-1">
<img src="~/Content/Images/#Model.FilePaths.FirstOrDefault(f => f.FileType == FileType.Photo).FileName" alt="" style="width:auto; height:100px">
</div>
}
</div>
My model class for FilePath:
public class FilePath
{
public int FilePathId { get; set; }
public string FileName { get; set; }
public FileType FileType { get; set; }
public int? ProductId { get; set; }
//navigation..
public virtual Product Product { get; set; }
}
Every help much appreciated. Thanks!

Related

How to Load Image on "Edit product" using ASP.NET MVC?

I have a inventory CRUD module for products in ASP.NET MVC. When inserting new product in the database I have to load an image for each product.
This is what I have and works great:
My problem is when I want to edit an existing product in a given Id and when editing a product Text successfully loads but Image does not. The problem is I do not know how to.
This is my code:
Inserting a new product:
#using (Html.BeginForm("NuevoProducto", "Inventario", FormMethod.Post, new { enctype =
"multipart/form-data" }))
{
...
<div class="form-group">
<label for="exampleInputFile">Imagen</label>
<div class="input-group">
<div class="custom-file">
<input type="file" id="file" name="Image" class="custom-file-input" multiple onchange="GetFileSize()" />
<label class="custom-file-label" for="exampleInputFile">Elija Imagen</label>
</div>
</div>
#Html.ValidationMessageFor(m => m.Image, "", new { #class = "text-danger" })
<div class="col-2">
<p>Tamaño de Imagen</p>
</div>
</div>
}
[HttpPost]
public ActionResult NuevoProducto(ProductoViewModel viewModel)
{
string path = "";
HttpPostedFileBase archivo = Request.Files["Image"];
if (ModelState.IsValid)
{
if (archivo != null && archivo.ContentLength > 0)
{
path = Path.Combine(Server.MapPath("~/Images"), Path.GetFileName(archivo.FileName));
archivo.SaveAs(path);
}
if (ModelState.IsValid)
{
var producto = viewModel.Producto;
producto.FechaCreacion = DateTime.Now;
producto.Estado = true;
producto.Imagen = viewModel.Image.FileName;
_productosRepository.Add(producto);
TempData["Message"] = "¡El Producto se ha INSERTADO con éxito!";
return RedirectToAction("Productos");
}
}
viewModel.Iniciar(_productosRepository);
return View(viewModel);
}
public class ProductoViewModel
{
public Producto Producto { get; set; } = new Producto();
[Required(ErrorMessage = "*Se necesita una imagen.")]
public HttpPostedFileBase Image { get; set; }
}
This is my code for editing a product but image doesn't load:
public ActionResult ModificarProducto(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var producto = _productosRepository.Get((int)id, incluideRelatedEntities: false);
if (producto == null)
{
return HttpNotFound();
}
//necesito capturar los datos y almacenarlos en viewmodel
var viewModel = new ProductoEditViewModel()
{
Producto = producto
};
viewModel.Iniciar(_productosRepository);
return View(viewModel);
}
[HttpPost]
public ActionResult ModificarProducto(ProductoEditViewModel viewModel)
{
if (ModelState.IsValid)
{
var producto = viewModel.Producto;
_productosRepository.ModificarProducto(producto);
TempData["Message"] = "¡El Producto se ha MODIFICADO con éxito!";
return RedirectToAction("DetallesProducto", "Inventario", new {viewModel.Id});
}
viewModel.Iniciar(_productosRepository);
return View(viewModel);
}
I save database the path of the image stored in Images Folder and show images in the list by using a
<img src="~/Images/#producto.Imagen" height="100" />. I do not know how to load Image in the edit view and make it easy for my client because saving in the edit view image goes empty.
After click on edit button, store image name and path in tempdata and during update get it back from tempdata.
Adding a preview div on your edit form. example below:
<div class="custom-file">
<div class="preview-image-section">
<img src='#Model.Image' class="preview-image" />
</div>
<input type="file" id="file" name="Image" class="custom-file-input" multiple onchange="GetFileSize()" />
<label class="custom-file-label" for="exampleInputFile">Elija Imagen</label>
</div>
and in your javascript code, if you wanna dislay the selected image by choosing button:
function GetFileSize() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.addEventListener("load", function (e) {
$(".preview-image").attr('src', e.target.result);
});
FR.readAsDataURL(this.files[0]);
}
//your code here
}

How to display an image from the database in ASP.NET Core MVC?

I am quite new with MVC Core and trying to add an image to my SQL Server-database through Entity Framework. I have accomplished the database itself and the view. What I cannot really get working is the controller. Can someone help me get the controller in place. Please!
Here is the model:
public class Product
{
[Key]
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter an product name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please specify a category")]
public string Category { get; set; }
public string SubCategory { get; set; }
[Required(ErrorMessage = "Please enter a description")]
public string Description { get; set; }
[Required(ErrorMessage = "Please enter a positive price")]
public decimal Price { get; set; }
public byte[] Image { get; set; }
public string ImageSourceFileName { get; set; }
public string ImageContentType { get; set; }
}
Here is the database:
Product ID int False
Category nvarchar(MAX) False
Description nvarchar(MAX) False
Name nvarchar(MAX) False
Price decimal(18,2) False
SubCategory nvarchar(MAX) True
Image varbinary(MAX) True
ImageContentType nvarchar(MAX) True
ImageSourceFileName nvarchar(MAX) True
Here is the view:
<div class="col-md-4">
<form asp-action="Create" method="post" enctype="multipart/
form-data" asp-controller="Products">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Image" class="control-label">File
input</label>
<input asp-for="Image" type="file"
aria-describedby="fileHelp" class="form-control-file" />
<span asp-validation-for="Image" class="text-danger"></span>
<small id="fileHelp" class="form-text text-muted">This is
some placeholder block-level help text for the above input. It's a bit
lighter and easily wraps to a new line.</small>
</div>
<div class="form-group">
<label asp-for="ImageSourceFileName"
class= "control-label"></label>
<input asp-for="ImageSourceFileName" class="form-control" />
<span asp-validation-for="ImageSourceFileName"
class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImageContentType" class="control-label"></label>
<input asp-for="ImageContentType" class="form-control" />
<span asp-validation-for="ImageContentType"
class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
Here is the controller:
public class ProductsController : Controller
{
private readonly ApplicationDbContext _context;
public ProductsController(ApplicationDbContext context)
{
_context = context;
}
// GET: Products
public async Task<IActionResult> Index()
{
return View(await _context.Products.ToListAsync());
}
// GET: Products/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var product = await _context.Products
.SingleOrDefaultAsync(m => m.ProductID == id);
if (product == null)
{
return NotFound();
}
return View(product);
}
// GET: Products/Create
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create
([Bind("ProductID,Name,Category,SubCategory,
Description,Price,Image,ImageSourceFileName,ImageContentType")]
Product product)
{
if (ModelState.IsValid)
{
_context.Add(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(product);
}
// GET: Products/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var product = await _context.Products.SingleOrDefaultAsync(m =>
m.ProductID == id);
if (product == null)
{
return NotFound();
}
return View(product);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Edit(int id,
[Bind
("ProductID,Name,Category,SubCategory,Description,Price,
Image,ImageSourceFileName,ImageContentType")]
Product product)
{
if (id != product.ProductID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(product);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(product.ProductID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(product);
}
// GET: Products/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var product = await _context.Products
.SingleOrDefaultAsync(m => m.ProductID == id);
if (product == null)
{
return NotFound();
}
return View(product);
}
// POST: Products/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var product = await _context.Products.SingleOrDefaultAsync(m =>
m.ProductID == id);
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool ProductExists(int id)
{
return _context.Products.Any(e => e.ProductID == id);
}
}
I like to store the image in the database. Now all text info goes into the database nice and neat, but no image/bytes...
The space is empty in the index-view where the image is supposed to be.
In asp.net core, to send a file from your browser to your action method, you should use the IFormFile type.
If you do not prefer to create a view model (I strongly advise you to create a view model and use that), you can add a new parameter to your httppost action method of IFormFile type and convert that to a byte array and store that in the Image property on your Product entity.
Also there is no need to have input elements for ImageContentType and ImageSourceFileName properties/columns. You can read this meta information from the uploaded file.
[HttpPost]
public IActionResult Create(Product model, IFormFile img)
{
if (img != null)
{
model.Image = GetByteArrayFromImage(img);
model.ImageSourceFileName = System.IO.Path.GetFileName(img.FileName);
model.ImageContentType = img.ContentType;
}
_context.Products.Add(model);
_context.SaveChanges();
return RedirectToAction("Index");
}
private byte[] GetByteArrayFromImage(IFormFile file)
{
using (var target = new MemoryStream())
{
file.CopyTo(target);
return target.ToArray();
}
}
Now make sure you are using a file input element with same name as the new method parameter we added (img) in your form.
<form asp-action="Create" method="post"
enctype="multipart/form-data" asp-controller="Product">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input asp-for="Name" />
<input asp-for="Category" />
<input asp-for="Price" />
<input type="file" name="img" />
<input type="submit" value="Create" class="btn" />
</form>
As i mentioned earlier, It is a good idea to use a view model for your create view and use that. This example uses a view model to transfer the uploaded file from the browser to the action method.
How to upload files in asp.net core?
At the view, you should assign the image input tag with name like following:
name="#Model.Image"
And at the Controller, add a parameter for image upload and use MemoryStream class to convert it into bytes:
public virtual ActionResult yourController(Product prod, HttpPostedFileBase imgUpload)
{
Product prod = new Product();
var imgT = new MemoryStream();
if(imgUpload!=null){
imgUpload.InputStream.CopyTo(imgT);
prod.Image = imgT.ToArray();
}
}
Hope it helps!
This way let you to save the file in a folder and to save the path the DB
following code for the Entity Dto
public string ImagePath { get; set; }
public IFormFile ImageFile { get; set; }
following code for the controller
var file = EntityDto.ImageFile;
if (file != null && file.Length > 0)
EntityDto.ImagePath = $"\\images\\folderName\\{EntityDto.Code}{Path.GetExtension(file.FileName)}";
if (AddAsync(EntityDto, $"{nameof(EntityDto)}."))
{
if (file != null && file.Length > 0)
{
var uploads = Path.Combine(_environment.WebRootPath, #"images\employees");
var filePath = Path.Combine(uploads, $"{EntityDto.Code}{Path.GetExtension(file.FileName)}");
using var fileStream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(fileStream);
}
following code for the UI
<form asp-action="New" method="post" enctype="multipart/form-data">
<input asp-for="#Model.EntityDto.ImageFile" type="file" />
</form>

ASP.NET MVC Create, Edit and Delete using ViewModel

For whatever reason I'm unable to Create and Edit using the ViewModel called CreateEmployeeViewModel that I created. I can however Create and Edit fine without using the CreateEmployeeViewModel but was told it was bad practive to use the main Models for CRUD. I am however able to retrieve values to my 2 DropDownList tags fine using the CreateEmployeeViewModel, just not Create or Edit. Below are my current Models, ViewModels, Controllers and Views.
I just figure out why I cannot Create using the public IActionResult Create(Employee employee) Active Method.
Employee Model: (located in Models folder)
public class Employee
{
[Key]
public int EmpId { get; set; }
[Required]
public string EmpFirstName { get; set; }
[Required]
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public Department Department { get; set; }
public int BldgId { get; set; }
public Building Building { get; set; }
}
EmployeeController: (located in Controllers folder)
public class EmployeeController : Controller
{
private DataEntryContext _context;
public EmployeeController(DataEntryContext context)
{
_context = context;
}
public IActionResult Index()
{
return View(_context.Employees.ToList());
}
// Populate Department values to DropDownList
private IEnumerable<SelectListItem> GetDeptList()
{
var dept = _context.Departments
.Select(s => new SelectListItem
{
Value = s.DeptId.ToString(),
Text = s.DeptTitle
})
.ToList();
return (dept);
}
// Populate Building values to DropDownList
private IEnumerable<SelectListItem> GetBldgList()
{
var bldg = _context.Buildings
.Select(b => new SelectListItem
{
Value = b.BldgId.ToString(),
Text = b.BldgName
})
.ToList();
return (bldg);
}
public IActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
model.DeptList = GetDeptList();
model.BldgList = GetBldgList();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Add(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
public IActionResult Edit(int? id)
{
if (id == null)
{
return View("Error");
//return NotFound();
}
var employee = _context.Employees
.Where(e => e.EmpId == id)
.Single();
if (employee == null)
{
return View("Error");
//return NotFound();
}
return View(employee);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Update(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
}
CreateEmployeeViewModel: (located in ViewModels Folder)
public class CreateEmployeeViewModel
{
public int EmpId { get; set; }
public string EmpFirstName { get; set; }
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public IEnumerable<SelectListItem> DeptList { get; set; }
public int BldgId { get; set; }
public IEnumerable<SelectListItem> BldgList { get; set; }
}
Employee Create View:
<form asp-controller="employee" asp-action="Create" method="post" class="form-horizontal" role="form">
<div class="form-horizontal">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmpFirstName" class="col-md-2 control-label">First Name</label>
<div class="col-md-10">
<input asp-for="EmpFirstName" class="form-control" />
<span asp-validation-for="EmpFirstName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="EmpLastName" class="col-md-2 control-label">Last Name</label>
<div class="col-md-10">
<input asp-for="EmpLastName" class="form-control" />
<span asp-validation-for="EmpLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="DeptId" class="col-md-2 control-label">Department</label>
<div class="col-md-10">
<select asp-for="DeptId" asp-items="#Model.DeptList" class="form-control">
<option>Select Department</option>
</select>
<span asp-validation-for="DeptId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="BldgId" class="col-md-2 control-label">Building Location</label>
<div class="col-md-10">
<select asp-for="BldgId" asp-items="#Model.BldgList" class="form-control">
<option>Select Building</option>
</select>
<span asp-validation-for="BldgId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
In your Create method, you are sending to the view the CreateEmployeeViewModel but in your HttpPost Create method you are accepting back the Employee model instead of the CreateEmployeeViewModel. So once you change the post methods signature to accept the correct CreateEmployeeViewModel, you can simply map it back to the Employee model.
Get Action Method:
public IActionResult Create(Employee employee)
{
return View(employee);
}
Just change in your Post Action Method:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreateEmployeeViewModel vm)
{
if (ModelState.IsValid)
{
var model = new Employee{
//your logic here for example
employeename = vm.employeename,
employeepassword = vm.employeepassword
}
_context.Employees.Add(model);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
and don´t forget to cal View Model in your .cshtml

The model item passed into the dictionary is of type List`1 but this dictionary requires a model item of type IEnumerable

thanks in advance for helping.
New to MVC so is probably easy to answer. I'm getting this error and have no idea what any of it means. This is my code:
My view:
#model carBayWebsite.Models.WishList
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create",
"WishLists",
FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Add to WishList?</h4>
<hr />
<p>Are you sure you want to add this to your Wish List?</p>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
#Html.HiddenFor(m => m.AdvertId)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
#Html.HiddenFor(m => m.AdvertId)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Add" class="btn btn-default"/>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My Controller
public class WishListsController : Controller
{
private Entities2 db = new Entities2();
public ActionResult Index()
{
string userName = User.Identity.GetUserName();
var wishlist = from ads in db.Adverts
join wish in db.WishLists
on ads.AdvertId equals wish.AdvertId
where wish.UserId.Contains(userName)
select wish;
return View(wishlist.ToList());
}
// GET: WishLists/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
WishList wishList = db.WishLists.Find(id);
if (wishList == null)
{
return HttpNotFound();
}
return View(wishList);
}
public ActionResult Create(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
else
{
string usID = User.Identity.GetUserId().ToString();
int adID = Convert.ToInt32(id);
WishList wishList = db.WishLists.Find(id);
ViewBag.userId = usID;
ViewBag.advertId = adID;
return View(wishList);
}
}
// POST: WishLists/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(WishList wishList)
{
if (ModelState.IsValid)
{
db.WishLists.Add(new WishList
{
UserId = ViewBag.userId,
AdvertId = Convert.ToInt32(ViewBag.advertID),
});
try {
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}",
validationError.PropertyName,
validationError.ErrorMessage);
}
}
}
return RedirectToAction("Index");
}
return View(wishList);
}
Could anyone figure out what's gone wrong? From looking around, I feel like its something really simple like the first like of the View but I can't pin it down! :)
Error details
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[carBayWebsite.Models.Advert]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[carBayWebsite.Models.WishList]'
The view you showed us is Create I think.(Because header is 'Create')
You are passing to Create view whishList which is type of WhisList return View(wishList);
But your view waits for Advert at the start of your view: #model carBayWebsite.Models.Advert
I think this is the problem. Let me know if it isn't.

HttpPostedFileBase ImageUpload is always null in asp.net mvc 5

I try to create a project in aps.net mvc 5, but I can't save an image in my local directory... The attribute: (HttpPostedFileBase ImageUpload) of my entity (Perfil), is always null translating to English: Profile = Perfil
Can someone help me please?
. My Entity:
[Table("Perfil")]
public class Perfil
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int idPerfil { get; set; }
[Required]
[ForeignKey("Usuario")]
public int idUsuario { get; set; }
[Required]
[ForeignKey("Genero")]
public int idGenero { get; set; }
[DisplayName("Descrição:")]
public string descricao { get; set; }
public string linkMultimidia { get; set; }
[DataType(DataType.ImageUrl)]
public string ImageUrl { get; set; }
[DataType(DataType.Upload)]
[NotMapped]
public HttpPostedFileBase ImageUpload { get; set; }
public virtual Usuario Usuario { get; set; }
public virtual Genero Genero { get; set; }
}
}
My Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "idPerfil,idUsuario,idGenero,descricao,linkMultimidia,fotoPerfil")] Perfil perfil)
{
var validImageTypes = new string[]
{
"image/gif",
"image/jpeg",
"image/pjpeg",
"image/png"
};
if (perfil.ImageUpload == null || perfil.ImageUpload.ContentLength == 0)
{
ModelState.AddModelError("ImageUpload", "This field is required");
}
else if (!validImageTypes.Contains(perfil.ImageUpload.ContentType))
{
ModelState.AddModelError("ImageUpload", "Please choose either a GIF, JPG or PNG image.");
}
if (ModelState.IsValid)
{
if (perfil.ImageUpload != null && perfil.ImageUpload.ContentLength > 0)
{
var uploadDir = "~/Imagens";
var imagePath = Path.Combine(Server.MapPath(uploadDir), perfil.ImageUpload.FileName);
var imageUrl = Path.Combine(uploadDir, perfil.ImageUpload.FileName);
perfil.ImageUpload.SaveAs(imagePath);
perfil.ImageUrl = imageUrl;
}
rep.IncluirPerfil(perfil);
return RedirectToAction("Index");
}
ViewBag.idGenero = new SelectList(db.Generos, "idGenero", "nomeGenero", perfil.idGenero);
ViewBag.idUsuario = new SelectList(db.Usuarios, "idUsuario", "nome", perfil.idUsuario);
return View(perfil);
}
My Create View:
<div class="form-group">
#using (Html.BeginForm("Create", "PerfilController", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-10">
#Html.LabelFor(model => model.ImageUpload)
</div>
#Html.TextBoxFor(model => model.ImageUpload, new { type = "file" })
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
I tried other solutions, but continued null...
The submit button must be inside using block:
<div class="form-group">
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new {enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<div class="col-md-10">
#Html.LabelFor(model => model.ImageUpload)
</div>
#Html.TextBoxFor(model => model.ImageUpload, new {type = "file"})
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default"/>
</div>
</div>
}
</div>
Also add ImageUpload to Bind list:
public ActionResult Create([Bind(Include = "idPerfil,idUsuario,idGenero,descricao,linkMultimidia,fotoPerfil, ImageUpload")] Perfil perfil)
One more thing, You can use Exclude instead of Include in your case.
I solved!
Entity:
public string photoPath{ get; set; }
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "idPerfil,idUsuario,idGenero,descricao,linkMultimidia,photoPath")] Perfil perfil)
{
string filename = perfil.photoPath;
var uploadDir = "~/Imagens";
var imagePath = Path.Combine(Server.MapPath(uploadDir), filename);
var imageUrl = Path.Combine(uploadDir, filename);
perfil.photoPath = imageUrl;
if (ModelState.IsValid)
{
rep.IncluirPerfil(perfil);
return RedirectToAction("Index");
}
ViewBag.idGenero = new SelectList(db.Generos, "idGenero", "nomeGenero", perfil.idGenero);
ViewBag.idUsuario = new SelectList(db.Usuarios, "idUsuario", "nome", perfil.idUsuario);
return View(perfil);
}
Create View:
<div class="form-group">
#Html.LabelFor(model => model.photoPath, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.photoPath, new { type = "file" })
#Html.ValidationMessageFor(model => model.photoPath)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>

Categories