mike_pl
mike_pl

Reputation: 121

ASP.NET MVC upload photo - httpPostedFileBase is null

EDIT:

Photo has null value in controller post method despite that i uploaded it..

My model class is :

class ProductVM{
    public string Name { get; set;}
    public string Color {get; set;}
    public HttpPostedFileBase Photo1 { get; set; }
    }

Here is how I implemented view with Razor:

    @model Project.Models.ProductVM

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


           @Html.AntiForgeryToken()
            @Html.ValidationSummary(true, "", new {@class = "text-danger"})

            @Html.EditorFor(model => model.Name, new {htmlAttributes = new {@class"form-control"}})
            @Html.ValidationMessageFor(model => model.Name)

        // other fields editor's and dropdown's ...


            <div class="col-xs-offset-2 col-xs-8 add-item-rectangle"><input type="file" name="@Model.Photo1" id="file"/></div>
            <div class="col-xs-10 add-item-rectangle"></div>

       <input type="submit" class="btn btn-block add-item-button-text" value="Send"/>

Post Controller method's :

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult AddItem(ProductVM product)
        {            
             //**heere when debuging Photo1 is null despite fact that i uploaded photo**

            if (!ModelState.IsValid)
            {
                //... my stuffs
            }

            //..
           return RedirectToAction("Index", "Home");
        }

Upvotes: 0

Views: 1570

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239430

First and foremost, you cannot post directly to a byte array. As a result, you'll need a view model to represent the product being created/modified. On your view model, your file upload properties should be typed as HttpPostedFileBase:

public HttpPostedFileBase Image1Upload { get; set; }
public HttpPostedFileBase Image2Upload { get; set; }

Your post action will accept your view model as a param:

[HttpPost]
public ActionResult CreateProduct(ProductViewModel model)

Inside this action, you'll map over the posted values on the view model to the corresponding properties on your entity class. For your uploads:

if (model.Image1Upload != null && model.Image1Upload.ContentLength > 0)
{
    using (var ms = new MemoryStream())
    {
        model.Image1Upload.InputStream.CopyTo(ms);
        product.Image1 = ms.ToArray();
    }
}

Rinse and repeat for the other upload. You'll probably also want to add some validation to ensure that the uploaded file(s) are in fact images, but that's left as an exercise for the reader.

Finally, you'll just save your entity as normal.

UPDATE

In your updated code, you have the following:

<div class="col-xs-offset-2 col-xs-8 add-item-rectangle">
    <input type="file" name="@Model.Photo1" id="file"/>
</div>

First, @Model.Photo1 would merely output the value of Model.Photo1, which isn't even possible with a file. Instead, Razor would just call ToString on the property and you'd get a name attribute like name="System.Web.HttpPostedFileBase". That's obviously not correct. What you'd need instead is something like:

<input type="file" name="@Html.NameFor(m => m.Photo1)" id="file" />

Or, even better, use a helper to generate the whole input:

@Html.TextBoxFor(m => m.Photo1, new { type = "file" })

Upvotes: 2

Related Questions