Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC 5 image upload to folder

I have a very simple MVC5 application that has a product page for the client that I also am utilizing the basic CRUD operations that have been scaffolded out in MVC 5.

I have a Model called Cakes.cs because the client sells cakes. Pretty simple. Here is the code for that model:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    namespace TastyCakes.Models
    {
        public class Cakes
        {
            public int CakesID { get; set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public decimal Price { get; set; }

            public string CakeImage
            {
                get { return Name.Replace(" ", string.Empty) + ".jpg"; }
            }
        }
    }

As you can see I am using a calculated property to create an image name for each cake. I only need 1 image for each cake. Now when I go to Edit a cake on my CRUD pages. I would like to add a simple Image upload that will upload an image (No need for resizing or thumbnails) But I would like to impose the calculated property name. In other words: no matter what the user has named their photo, my upload code will rename it to whatever the Cakes.Name is (minus any spaces) +".jpg" and save it to "~Images/Cakes".

I am only requiring the upload to be on the actual Edit page, so the cake will already have been created at this point. All of the information needed for renaming the file should be available and easy to utilize from the Edit page. Below is my Edit page code:

Edit Page:

@model TastyCakes.Models.Cakes

<div class="row">
    <div class="large-12 columns">
    <hgroup class="title">
        <h1>Edit Cakes</h1>
    </hgroup>

    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
            <hr />
            @Html.ValidationSummary(true)
            @Html.HiddenFor(model => model.CakesID)

            <div class="medium-12 column">
                @Html.LabelFor(model => model.Name)
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>

            <div class="medium-12 column">
                @Html.LabelFor(model => model.Description)
                @Html.EditorFor(model => model.Description)
                @Html.ValidationMessageFor(model => model.Description)
            </div>

            <div class="medium-12 column">
                @Html.LabelFor(model => model.Price)
                @Html.EditorFor(model => model.Price)
                @Html.ValidationMessageFor(model => model.Price)
            </div>

            <div class="medium-12 column">
                <input type="submit" value="Save" class="tiny button" /> 
                @Html.ActionLink("Back to List", "Index", null, new { @class = "tiny button" })
            </div>
        </div>
    }

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    </div>
</div>

I have reviewed a few html5 & ASP.Net 4 solutions, but this is too much. What I want is very simple. Any ideas or a kick in the right direction would be very much appreciated. I am using this code not only for a clients website but to include in a fictional website used to teach very basic MVC concepts.

like image 999
Eric Bishard Avatar asked Mar 25 '14 01:03

Eric Bishard


People also ask

What is HttpPostedFileBase in MVC?

The HttpPostedFileBase class is an abstract class that contains the same members as the HttpPostedFile class. The HttpPostedFileBase class lets you create derived classes that are like the HttpPostedFile class, but that you can customize and that work outside the ASP.NET pipeline.


2 Answers

You'll need to:

  • add an input of type file to your form,
  • have the attribute on your form element enctype = "multipart/form-data"

Then add an HttpPostedFileBase to your model with the same name as the name of the input. Then the HttpPostedFileModelBinder will populate the model property from the uploaded file before the action is invoked. Note, I think you should probably add in the model id somewhere, perhaps as a path element, to guaranteed uniqueness in the image path so that images don't accidentally get overwritten.

There's a reasonably complete discussion of this at http://www.prideparrot.com/blog/archive/2012/8/uploading_and_returning_files

public class Cakes
{
    ...

    public HttpPostedFileBase UploadedFile { get; set; }

}

[HttpPost]
public ActionResult Edit(Cakes cake) // I'd probably use a view model here, not the domain model
{
      if (ModelState.IsValid)
      {
           if (cakes.UploadedFile != null)
           {
               cakes.UploadedFile.SaveAs(Path.Combine("path-to-images-for-this-cake", cakes.CakeImage));
           }

           ....
      }
}
like image 135
tvanfosson Avatar answered Oct 06 '22 17:10

tvanfosson


The code that was supplied here eventually went into building this small demo that allows you to upload images to the file system and use them dynamically without storing any values to the database; however you will have the string to the images file location as part of your Model class which uses a convention and naming of the uploaded file to display.

I would like to upload this to github and see if I can't get some others to help me work out a better solution that uses this idea. Thinking of making it work with MongoDB too.

ASP.NET MVC 5 Image Upload & Delete w/ Calculated Property

like image 36
Eric Bishard Avatar answered Oct 06 '22 16:10

Eric Bishard