0

I'm trying to do a movie gallery in MVC, and I have the following algorithm:

  1. Save image to server in a specific folder. Path.Combine(Server.MapPath("~/Images"), Path.GetFileName(archivo.FileName));
  2. And Save image name to database. (not the full path, just like Hello.jpg).
  3. In the View just show them by typing <img src="/Images/@MovieGallery.Imagen"/> using a foreach loop.

(Please correct me if my algorithm is not good)

And this is my code:

Controller

        [HttpPost]
    public ActionResult Peliculas_Agregar(pelicula pelis)  {

        string path="";
        HttpPostedFileBase archivo = Request.Files["Imagen"]; // @name= file, capturo el name


            if (ModelState.IsValid) { // Validar si son validos los campos segun DBSET
                    try
                    {

                        if (archivo != null && archivo.ContentLength > 0) { //El nombre del archivo debe ser mayor que 0 y no debe ser nulo
                            try
                            {
                                path = Path.Combine(Server.MapPath("~/Images"), Path.GetFileName(archivo.FileName));
                                archivo.SaveAs(path);

                    }
                    catch (Exception ex) {
                                ViewBag.ErrorArchivo = ex;
                            }
                        }

                        Cine.peliculas.Add(pelis);
                        Cine.SaveChanges();
                    }
                catch (Exception ex){
                        ViewBag.Error = ex;
                    }

            }
        return View(pelis);
    }

Model (Generated by Entity Framework)

 public int id_peli { get; set; }
    public string titulo { get; set; }
    public string director { get; set; }
    public string cast { get; set; }
    public string descripcion { get; set; }
    public Nullable<int> duracion { get; set; }
    public string categoria { get; set; }
    [DataType(DataType.Upload)]
    [Display(Name = "Cargar imagen")]
    //[Required(ErrorMessage = "Por favor carga una imagen")]
    public string imagen { get; set; } // here is where i want to save files name, not the path.

View

@using (Html.BeginForm("Peliculas_Agregar", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    <div class="Formas">
        <div class="form-group">
            @Html.LabelFor(m => m.titulo, new { htmlAttributes = new { @for = "exampleTittle" } })
            @Html.EditorFor(m => m.titulo, new { htmlAttributes = new { @placeholder = "Título", @class = "form-control"} })
        </div>
        <div class="form-group">
            <input type="file" name="Imagen" />
        </div>
    </div>
    <input type="submit" value="Agregar Película" class="btn btn-outline-primary" />
}

My code works OK, but the main problem that I am facing is that I can't or I don't know how to save the image name to database because I'm not getting the string name of the image that is coming into the parameter. I'm just getting a string or type called like System.Web.HttpPostedFileWrapper : System.Web.HttpPostedFileWrapper

I think this is because I am using HttpPostedFileBase to save the image into the server but I can't edit this and save just the image name into the server. Can't do both things. How could I solve this?

Reyneer Leon
  • 356
  • 2
  • 14
  • You need to reassign the field a value `pelis.imagen = archivo.FileName`. See also the answer here https://stackoverflow.com/a/20446628/2030565. – Jasen May 09 '19 at 18:19
  • Glad you solved my problem. Wow so simple. Maybe I was so stressed and didn't think of this. Now I feel like a bad programmer. Gosh! Now I must ask this..., is my algorithm good? – Reyneer Leon May 09 '19 at 18:34
  • The general steps may be ok. But using the Entity model directly in the view is a bad practice and contributed to your original problem. See the linked answer and [What is a ViewModel in MVC](https://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). – Jasen May 09 '19 at 18:49
  • Should I create a separate ModelView and define each property, right? If this is right, Then why Entity framework generates automatic properties? I thought you could use them instead of defining new one. – Reyneer Leon May 09 '19 at 19:06
  • The entity serves the database's needs; the VM serves your view's needs. The two don't always align as your file example illustrates. – Jasen May 09 '19 at 19:12

1 Answers1

0

Following the two liked answers we use a View Model to post the form and file. Then we map the VM fields to the Entity's fields before performing the database actions.

Entity Model

public class Movie
{
    public string Title { get; set; }
    public string FileName { get; set; }
}

Create a View Model to capture your form values

public class MovieVM
{
    public string Title { get; set; }

    [Display(Name = "Upload Image")]
    public HttpPostedFileBase Image { get; set; }
}

The action accepts the MovieVM instead of the Entity

[HttpPost]
public ActionResult UploadMovie(MovieVM model)
{
    if (ModelState.IsValid)
    {
        // save file
        // ...

        // Map to Entity to save to db
        Movie movie = new Movie
        {
            Title = model.Title,
            FileName = model.Image.FileName
        };

        db.Movies.Add(movie);
        db.SaveChanges();

        return RedirectToAction("Success");
    }
    return View(model);
}
  1. Upload image included in MVC model
  2. What is ViewModel in MVC?
Jasen
  • 14,030
  • 3
  • 51
  • 68
  • Properties declared from MovieVM shoud be the same as Movie? I think this is because they should match together? Or Should I need some extra code to make the match? – Reyneer Leon May 10 '19 at 16:12
  • You map the fields you need, ignore the fields you don't, and transform the fields that are different. Here, the image fields need transformation. You may have audit fields on the database record that should not be sent to or from the view -- so you can ignore those in a VM. The title field has a perfect match so it's just mapped directly. Matching names makes it easier for the developer mapping the fields. – Jasen May 10 '19 at 17:35