2012-06-17 17 views
6

Estoy intentando crear un controlador para cargar fotos en mi aplicación MVC4. Pero sigo recibiendo este error. La entrada no es una cadena válida de base 64, ya que contiene un carácter no base de 64 caracteres, más de dos caracteres de relleno o un carácter de espacio no blanco entre los caracteres de relleno.Subir foto a MVC 4 Aplicaciones

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(); 
     } 
    } 

Respuesta

15

El problema es que usted tiene una propiedad en su modelo de vista llamada File que es de tipo byte[] y también está usando un parámetro de acción denominado file de tipo HttpPostedFileBase. El problema es que cuando el archivador de modelo encuentra una propiedad en su modelo de tipo byte[], intenta vincular su valor desde el valor de solicitud utilizando base64. Excepto que dentro de la solicitud tiene un valor codificado multipart/form-data del archivo cargado y obtiene una excepción.

La forma correcta de solucionar este problema es el uso de modelos de vista en lugar de pasar sus modelos de dominio a los puntos de vista:

public class PhotoViewModel 
{ 
    public HttpPostedFileBase File { get; set; } 

    ... other properties 
} 

y la acción del controlador se convertirá ahora en:

[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); 
} 

La forma más pobres y no lo recomiendo por completo es cambiar el nombre de su entrada de archivo para engañar a la carpeta del modelo:

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

y su acción de controlador:

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

Gracias parece que funciona, excepto cuando se intenta utilizar el automapper. Lanza 'Automapper: falta la configuración de TypeMap o mapeo no compatible'. El código se actualiza arriba –