Uploading a file in MVC when used in bootstrap modal returns null

I try to upload images to my application, but always returns null. I can not find the problem here. Can you help me? Here is my code.

Model


[Table("Slider")] public partial class Slider : BaseModel { [Required] [StringLength(200)] public string FileName { get; set; } [StringLength(200)] public string Title { get; set; } [StringLength(1000)] public string Description { get; set; } public int? Order { get; set; } } [NotMapped] public class SliderImage : Slider { public HttpPostedFileBase ImageFile { get; set; } } 

View


 @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() <div class="modal-body"> <div class="form-horizontal"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Id) <div class="form-group"> @Html.LabelFor(model => model.FileName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.FileName, new { @class = "form-control", @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.FileName, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ImageFile, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.ImageFile, new { @class = "form-control", type = "file" }) //This is Same as below //<input class="form-control" id="ImageFile" name="ImageFile" type="file" value=""> </div> </div> 

controller


  public ActionResult Edit(int id) { Slider slider = _db.Sliders.Find(id); if (slider == null) { return HttpNotFound(); } Mapper.CreateMap<Slider, SliderImage>(); SliderImage sliderImage = Mapper.Map<Slider, SliderImage>(slider); return PartialView("_Edit", sliderImage); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult EditSlider([Bind(Include = "Id,FileName,Title,Description,Order,IsActive,Name,ImageFile")] SliderImage sliderImage) { if (ModelState.IsValid) { Mapper.CreateMap<SliderImage, Slider>(); Slider slider = Mapper.Map<SliderImage, Slider>(sliderImage); _db.Entry(slider).State = EntityState.Modified; _db.SaveChanges(); return Json(new { success = true }); } return PartialView("_EditSlider"); } 

What am I doing wrong, is it?


Problem Found

I snap a partial view inside the bootstrap popup. When I boot from a popup, the boot returns zero. Instead, if I open a partial view directly in the browser, then the file is present in the model. Thus, there is no problem downloading files. The problem is modal ascent or something like that.

When using the Bootstrap Model When Using Bootstrap model

When using the Directy partial view When using partial View Directy

Check the difference found when using the violinist between Modal sending Bootstrap and using partial viewing directly on the next image, respectively

Comparison of fiddler requests

When publishing from a modal popup, the content type changes to application/x-www-form-urlencoded , where, as with the direct use of the partial view, this is multipart/form-data


Found the root of the problem.

 $('form', dialog).submit(function () { var $form = $(this); var enctype = $form.attr('id'); $.ajax({ url: this.action, type: this.method, data: $(this).serialize(), success: function (result) { if (result.success) { $('#myModal').modal('hide'); //Refresh location.reload(); } else { $('#myModalContent').html(result); bindForm(); } } }); return false; }); 

I use AJAX wiring to submit data from my form. Using $(this).serialize() causes ajax success, but the file is not returned because the content type is different. How can i change this?

+5
source share
6 answers

Ok, I think your current problem is with the default settings for the jQuery.ajax method. By default, the content type for the jQuery.ajax () method is 'application/x-www-form-urlencoded; charset=UTF-8' 'application/x-www-form-urlencoded; charset=UTF-8' . So, in the project example, I modified your javascript function to specify contentType as a parameter to the ajax: contentType: this.enctype

I think a couple more questions may arise. The next question I noticed is that when I sent, I connected to other actions, so I updated this line in the view:

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

For this:

 @using (Html.BeginForm("EditSlider", "<Your Controller Name>", FormMethod.Post, new { enctype = "multipart/form-data" })) 

Finally, when ajax is presented, I was redirected to a partial view. I believe this can be fixed by adding preventDefault to the ajax function:

 $('form', dialog).submit(function (event) { event.preventDefault(); var $form = $(this); $.ajax({ url: this.action, type: this.method, contentType: this.enctype, data: $(this).serialize(), success: function (result) { if (result.success) { $('#myModal').modal('hide'); //Refresh location.reload(); } else { $('#myModalContent').html(result); bindForm(); } } }); }); 

Here is how I was able to bring this example into a sample project; Please post the update if you have additional problems.

+1
source

Typically, modal pop-ups appear at the end of the body . I am pretty sure bootstrap does the same. This, in turn, means that the contents of the modal object are moved to a new location and derived from your form element. I would recommend reordering: move the form inside the modal window:

 <div class="modal-body"> @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() ... } </div> 

This will move the entire form (and not just the form elements) when the modal is built.

0
source

Only the downloaded file returns null? or does another text field return zero? As @Andrei notes, usually the modals are moved to a new location, and the form is missing or your partial view can be moved to do modal work.

With jqueryUI, I had a similar problem. I could not find in your question, if you use ajax to submit your data, you can use .ajax () to submit the form and see if the image is uploaded

 $.ajax({ url: "@Url.Action("Action", "Controller")", type: "POST", cache: false, data: $("#YourFormID").serialize(), success: function (result) { //your success data }, error: function (jqXHR, textStatus, errorThrown) { //your error handler }, }); return false; 

If you do not want to use $ .ajax (), you can try using .appendTo () with jquery, wrap everything inside your form in a div with an identifier, after which you have all your data try to indicate what you want add appendTo ("# YourFormID") at the click of a button or as you like. This work for me, when I use modal, I hope that it will help you. Good luck.

0
source

If I understand that you are making the form in partial view, and this partial is used in a modal popup, this is correct.

1) make a model for use in the form with all the elements for the form, 2) declare the model in the first line in a partial representation 3) pass the model of the post function as a parameter. 4) you are using a partial view, it is possible to use this view on different pages, you need to specify a control for processing the form. in code:

MODEL

 public partial class SliderModel { [Required] [StringLength(200)] public string FileName { get; set; } [StringLength(200)] public string Title { get; set; } [StringLength(1000)] public string Description { get; set; } public int? Order { get; set; } [NotMapped] public HttpPostedFileBase ImageFile { get; set; } } 

VIEW

 @model YOURNAMESPACE.Models.SliderModel <form method="post" class="form-horizontal" role="form" id="sendMail" enctype="multipart/form-data" action="/CONTROLLERNAME/EditSlider"> @Html.AntiForgeryToken() <div class="modal-body"> <div class="form-horizontal"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Id) <div class="form-group"> @Html.LabelFor(model => model.FileName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.FileName, new { @class = "form-control", @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.FileName, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ImageFile, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.ImageFile, new { @class = "form-control", type = "file" }) //This is Same as below //<input class="form-control" id="ImageFile" name="ImageFile" type="file" value=""> </div> </div> <div class="form-group"> <div class="col-md-offset-1"> <button type="submit" class="btn btn-success"><b><i class="fa fa-envelope"></i> Envoyer</b> </button> </div> </div> </form> 

CONTROLLER

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult EditSlider(SliderModel obj) { if (ModelState.IsValid) { your options } return PartialView("_EditSlider"); } 
0
source

I think I was able to identify your problem, Ajax does not support file serialization, you should use the following method in the script:

 $('form', dialog).submit(function () { var formData = new FormData($(this)[0]); $.ajax({ url: this.action, type: this.method, contentType: this.enctype, data: formData, success: function (result) { if (result.success) { $('#myModal').modal('hide'); $('#replacetarget').load(result.url); // Load data from the server and place the returned HTML into the matched element } else { $('#myModalContent').html(result); bindForm(dialog); } } }); return false; }); 
0
source

Try as follows, this worked for me:

BROWSE:

 @using (Html.BeginForm("ComplaintAndSuggestion", "RegisterComplaints", FormMethod.Post, new { enctype = "multipart/form-data", id = "ajaxUploadForm" })) { : : : <div class="row mb10"> <div class="col-sm-3 col-md-3"> <label for="file1">Upload Image 1</label> <input type="file" name="images" id="file1" accept="image/*" /> </div> <div class="col-sm-3 col-md-3"> <label for="file2">Upload Image 2</label> <input type="file" name="images" id="file2" accept="image/*" /> </div> <div class="col-sm-3 col-md-3"> <label for="file3">Upload Image 3</label> <input type="file" name="images" id="file3" accept="image/*" /> </div> <div class="col-sm-3 col-md-3"> <label for="file4">Upload Image 4</label> <input type="file" name="images" id="file4" accept="image/*" /> </div> </div> <input type="submit" value="Create" /> } 

Controller:

  [HttpPost] public ActionResult ComplaintAndSuggestion(Register register, IEnumerable<HttpPostedFileBase> images, IEnumerable<HttpPostedFileBase> videos) { foreach (var file in images) { if (file != null) { string filenameWithDateTime = AppendTimeStamp(file.FileName); file.SaveAs(Server.MapPath(Path.Combine("~/Images/", filenameWithDateTime))); fileUploadModel.FilePath = (Server.MapPath(Path.Combine("~/Images/", filenameWithDateTime))); fileUploadModel.FileName = filenameWithDateTime; fileUploadModel.FileType = "Image"; fileUploadModel.RegisterId = register.RegisterId; mediaRepository.Add(fileUploadModel); mediaRepository.Save(); } } } 

Tell me.

-1
source

Source: https://habr.com/ru/post/1205500/


All Articles