Eduardo Noyola
Eduardo Noyola

Reputation: 161

MVC always return me null when I try to add an image

Hi I have a problem with MVC I need to save an image into a table in my database but always give me an error "ImageFile.get return null" when I try to add the image

Here is my code

My Model

public partial class Inventario
{
    public int IdProduct { get; set; }
    [DisplayName("Product")]
    public string Name_Product { get; set; }
    public Nullable<decimal> Price{ get; set; }
    public Nullable<int> Stock{ get; set; }
    [DisplayName("Category")]
    public Nullable<int> IdCategory { get; set; }
    [DisplayName("Upload Image")]
    public string ImagePath { get; set; }


    public HttpPostedFileBase ImageFile { get; set; }
}

My View

@using (Html.BeginForm("Create", "AccionesInventarios", FormMethod.Post, new {enctype = "multipart/form-data" }))

<input type="file" name="ImageFile" required>

My Controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "IdProduct,Name_Product,Price,Stock,IdCategory,ImagePath")] Inventario inventario)
{
    string fileName = Path.GetFileNameWithoutExtension(inventario.ImageFile.FileName);
    string extension = Path.GetExtension(inventario.ImageFile.FileName);
    fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
    inventario.ImagePath = "~/Image/" + fileName;
    fileName = Path.Combine(Server.MapPath("~/Image/"), fileName);
    inventario.ImageFile.SaveAs(fileName);

    if (ModelState.IsValid)
    {
        db.Inventarios.Add(inventario);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(inventario);
}

Upvotes: 3

Views: 347

Answers (1)

Shyju
Shyju

Reputation: 218722

You are using the Bind attribute to explicitly limit the properties model binder will map from the posted form data. You did not include the ImageFile property and hence the default model binder did not map it from the posted form data.

Add it to the Bind Include list and it will work.

public ActionResult Create([Bind(Include = "IdProduct,Name_Product, Price,Stock,
                                            IdCategory,ImageFile")] Inventario inventario)
{  
    // to do : Your existing code
}

A more loosely coupled solution is to create a view model with properties needed for the view and use that. That is the best way to prevent over posting. Also using the entity classes from your data access layer in your views/view layer is not a great idea. It makes it tightly coupled to those classes.

Upvotes: 2

Related Questions