0

I'm trying to upload a file, but it does not work as expected. I have the following view:

@using (Ajax.BeginForm("RegisterBand", "NewProfile", new AjaxOptions() { HttpMethod = "Post",
            InsertionMode = InsertionMode.Replace,
        }, new { enctype = "multipart/form-data"}))
        {
            @Html.AntiForgeryToken()
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })


            <div class="form-horizontal">
                <div class="form-group">
                    <div class="col-md-10">
                        Bandname
                    </div>
                    <div class="col-md-10">
                        @Html.EditorFor(x => x.BandProfile.Name, new { htmlAttributes = new { @class = "form-control" } })
                        @Html.ValidationMessageFor(x => x.BandProfile.Name, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-md-10">
                        Genres
                    </div>
                    <div class="col-md-10">
                        @Html.DropDownListFor(x => x.BandProfile.Genres, Enumerable.Empty<SelectListItem>(), new { @class="", multiple = "multiple", style ="width: 100%;"} )
                        @Html.ValidationMessageFor(x => x.BandProfile.Genres, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-md-10">
                        Coverpicture
                    </div>

                    <div class="col-md-10">
                        <input type="file" name="file" id="CoverPicture" />

                        @Html.ValidationMessageFor(x => x.BandProfile.CoverPicture, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-md-10">
                        Description
                    </div>
                        <div class="col-md-10">
                            @Html.EditorFor(x => x.BandProfile.Description, new { htmlAttributes = new { @class = "form-control"} })
                            @Html.ValidationMessageFor(x => x.BandProfile.Description, "", new { @class = "text-danger" })
                        </div>
                    </div>

                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Spara" class="btn btn-success" />
                    </div>
                </div>
            </div>
        }

Here is my controller:

   [HttpPost]
        public ActionResult RegisterBand(ProfileViewModel model, HttpPostedFileBase file)
        {
            if (ModelState.IsValid == false)
            {
                return Json(JsonRequestBehavior.AllowGet);
            }

            var bandProfile = _profileService.CreateBandProfile(model.BandProfile, file, UserId);

            if (bandProfile != null)
            {
                userManager.AddToRole(UserId, "Band");
                return RedirectToAction("Index", "Welcome");
            }
            return View("Index");
        }

The problem I have is that file always results in null. I can't understand why. How can I find the problem?

halfer
  • 19,824
  • 17
  • 99
  • 186
Bryan
  • 3,421
  • 8
  • 37
  • 77

1 Answers1

1

The issue here is that you are using the Ajax.BeginForm() helper to create and post your form. However, files cannot be uploaded using AJAX.

You may want to consider using a jQuery-based plug-in to accomplish this, which relies on the use of an <iframe> to handle your uploading operations behind the scenes and posting them to the proper location.

Otherwise, you could consider trying a normal form using Html.BeginForm(), which should work in your scenario (if you don't explicitly need any of the AJAX functionality).

Update

Another issue here is that the constructor that you are using for your Ajax.BeginForm() call is accepting an AjaxOptions and htmlAttributes parameter, which falls in like with this constructor

However, your current use is missing the third RouteValues parameter. You could try adding null in there to see if that makes any difference :

@using(Ajax.BeginForm("RegisterBand", 
                      "NewProfile", 
                      null, 
                      new AjaxOptions() { 
                             HttpMethod = "Post", 
                             InsertionMode = InsertionMode.Replace
                      }, 
                      new { enctype = "multipart/form-data"})){ 
     <!-- Content -->
}
Rion Williams
  • 74,820
  • 37
  • 200
  • 327
  • I don't think this Is the problem because on my machine at home, this works. I got the code from TFS and then tried on a another computer, and this don't work. – Bryan Apr 06 '16 at 14:28
  • When I look into the console, I can see that the POST Is made to http://localhost:65148/NewProfile/RegisterBand?Length=10 What Is Length here? – Bryan Apr 06 '16 at 14:33
  • @Bryan Same browser on "another computer"? I have a feeling that what you are doing is not supported across all browsers. – spender Apr 06 '16 at 14:36
  • I feel like something else might be causing the conflict or issue here. [This very basic case](https://gist.github.com/Rionmonster/40890d53ad857a57afb4836635f7d898) works as expected using both the `Ajax.BeginForm()` and traditional `Html.BeginForm()` methods. As far as the `Length` attribute, [this related question](http://stackoverflow.com/q/824279/557445) seems to answer that, as it's coming from the file attempting to be serialized. – Rion Williams Apr 06 '16 at 14:40
  • It seems this may be related to the actual constructor for your `Ajax.BeginForm()` call. You might try using [this constructor](https://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxextensions.beginform(v=vs.118).aspx#M:System.Web.Mvc.Ajax.AjaxExtensions.BeginForm%28System.Web.Mvc.AjaxHelper,System.String,System.String,System.Web.Routing.RouteValueDictionary,System.Web.Mvc.Ajax.AjaxOptions,System.Collections.Generic.IDictionary{System.String,System.Object}%29) since you are passing in both `AjaxOptions` and `htmlAttributes` as well. Basically just add a third parameter as `null`. – Rion Williams Apr 06 '16 at 14:45
  • @RionWilliams: It works perfectly fine at home. But on the other computer It does not work. I also tried the regular Html.BeginForm, but the file Is still null :P – Bryan Apr 07 '16 at 06:45
  • That's quite bizarre if it isn't working with the normal `Html.BeginForm()` approach as that's a fairly straight-forward operation. Have you tried changing your name parameter to something different as well as the matching parameter to see if that works? You might also consider just using a plain `
    ` that only contains your submit button and your file upload to ensure that is working as well. Finally, you could use the Developer Tools (F12) in your browser to look at the request to check that the file contents are included in it.
    – Rion Williams Apr 07 '16 at 11:09