Upload Photos to MVC 4 Applications

I am trying to create a controller to upload photos in my MVC4 application. But I keep getting this error. Input is not a valid Base-64 string because it contains a non-base 64 character, more than two indentation, or a white space among padding characters.

PhotosController.cs

public class PhotoController : Controller { public ActionResult Index() { using (var ctx = new BlogContext()) { return View(ctx.Photos.AsEnumerable()); } } public ActionResult Upload() { return View(new Photo()); } [HttpPost] public ActionResult Upload(PhotoViewModel model) { var photo = Mapper.Map<PhotoViewModel, Photo>(model); if (ModelState.IsValid) { PhotoRepository.Save(photo); return RedirectToAction("Index"); } return View(photo); } } 

Photo.cs

 public class Photo { public int Id { get; set; } public Byte[] File { get; set; } public string Name { get; set; } public string Description { get; set; } public string AlternateText { get; set; } } 

PhotoViewModel.cs

 public class PhotoViewModel { public int Id { get; set; } public HttpPostedFileBase File { get; set; } public string Name { get; set; } public string Description { get; set; } public string AlternateText { get; set; } } 

/Photos/Upload.cshtml

  @model Rubish.Models.Photo @{ ViewBag.Title = "Upload"; } <h2>Upload</h2> @using (Html.BeginForm("Upload","Photo",FormMethod.Post,new {enctype="multipart/form-data"})) { @Html.ValidationSummary(true) <fieldset> <legend>Photo</legend> <div class="editor-label"> @Html.LabelFor(model => model.Name) </div> <div class="editor-field"> @Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name) </div> <div class="editor-label"> @Html.LabelFor(model => model.Description) </div> <div class="editor-field"> @Html.EditorFor(model => model.Description) @Html.ValidationMessageFor(model => model.Description) </div> <div class="editor-label"> <label for="file">FileName:</label> </div> <div class="editor-field"> <input name="File" id="File" type="file"/> </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div> @Scripts.Render("~/bundles/jqueryval") 

PhotoRepository

 public class PhotoRepository { private static BlogContext _ctx; public PhotoRepository() { _ctx = new BlogContext(); } public static void Save(Photo p) { _ctx.Photos.Add(p); _ctx.SaveChanges(); } } 
+6
source share
1 answer

The problem is that you have a property in your model called File that is of type byte[] , and you are also using the File action parameter of type HttpPostedFileBase . The problem is that when the model binder detects a property in your model of type byte[] , it tries to associate its value with the request value using base64. Except that inside the request you have multipart/form-data encoded value of the downloaded file, and you get an exception.

The correct way to fix this is to use view models instead of passing your domain models to views:

 public class PhotoViewModel { public HttpPostedFileBase File { get; set; } ... other properties } 

and the controller action will now be as follows:

 [HttpPost] public ActionResult Upload(PhotoViewModel model) { if (ModelState.IsValid) { // map the domain model from the view model that the action // now takes as parameter // I would recommend you AutoMapper for that purpose Photo photo = ... // Pass the domain model to a DAL layer for processing Repository.Save(photo); return RedirectToAction("Index"); } return View(photo); } 

A bad way and not completely recommended by me is to rename your file in order to trick the connecting device:

 <input name="PhotoFile" id="File" type="file"/> 

and your controller actions:

 [HttpPost] public ActionResult Upload(Photo photo, HttpPostedFileBase photoFile) { ... } 
+15
source

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


All Articles