0

I am uploading files to my web APi (in c#, ASP. NET) using ajax and a html file selector. I have a viewmodel and I want to pass the file to my controller, using my viewmodel.

This is my code: My viewmodel

public class CursoViewModel
{
    public Guid CursoId { get; set; }
    [MaxLength(125)]
    public string Titulo { get; set; }
    public string Descripcion { get; set; }
    [Required(ErrorMessage ="select image file for course")]
    [DataType(DataType.Upload)]
    public HttpPostedFileBase Imagen { get; set; } //note this is the image
}

My view,

<form id="Editcurso" method="post" action="#" enctype="multipart/form-data">
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "Please fix the following errors.")
<div class="container">
    <div class="form-group">
        @Html.LabelFor(c=>c.Titulo)
        @Html.TextBoxFor(c => c.Titulo, new { @class="form-control"})           
        @Html.ValidationMessageFor(m => m.Titulo)
    </div>
    <div class="form-group">
        @Html.LabelFor(c => c.Descripcion)
        @Html.TextAreaFor(c => c.Descripcion, new { @class = "form-control" })
        @Html.ValidationMessageFor(m => m.Descripcion)
    </div>       
    <div class="form-group">
        @Html.LabelFor(m => m.Imagen)
        @Html.TextBoxFor(m => m.Imagen, new {type = "file"})
        @Html.ValidationMessageFor(m => m.Imagen)
    </div>
    <button id="submiter" type="submit" class="btn btn-primary">Listo!</button>
</div>

My javascript:

$('#Editcurso').submit(function(e) {
            e.preventDefault(); // prevent the default submit
            if (!$(this).valid()) {
                return; // exit the function and display the errors
            }

            jQuery.support.cors = true;

            var data = new FormData();
            var files = $("#Imagen").get(0).files;

            // Add the uploaded image content to the form data collection
            if (files.length > 0) {
                data.append("UploadedImage", files[0]);
                console.log("files uploaded");
            }

            var viewmodel = new Object();
            viewmodel.Titulo = "Sourav";
            viewmodel.Descripcion = "Kayal";
            viewmodel.CursoId = "some guid";
            viewmodel.Imagen = files; /*<<==I pass the file here*/

            $.ajax({
                url: '/api/ProfesorCurso/test',
                type: 'PUT',
                dataType: 'json',
                data: viewmodel,
                success: function (data) {
                    console.log(data);
                    return false;
                },
                error: function (x, y, z) {
                    alert('error al postear');
                    return false;
                }
            });

            e.preventDefault(); // avoid to execute the actual submit of the form.
        });

My api

[HttpPut]

    public IHttpActionResult UpdateCursoProfesor([FromBody] CursoViewModel viewmodel)
    {
        if (!ModelState.IsValid) return BadRequest();
        try
        {
            //do something, upload the file inside the viewmodel
            return Ok(result);

        }
        catch (DbEntityValidationException e)
        { //do something}

When I execute my program, I get this error message: "Uncaught TypeError: Illegal invocation". What am I doing wrong? thanks js error

ev vk
  • 345
  • 1
  • 4
  • 18
  • Change HttpPostedFileBase to byte array or base64 string – Melih Altıntaş Sep 17 '17 at 18:59
  • hello, can you add me an example of the code? and how I would recover the file?thanks – ev vk Sep 17 '17 at 19:13
  • You need to set the correct ajax options, but you can also simplify this by using just `var formdata = new FormData($('form').get(0));` - refer [this answer](https://stackoverflow.com/questions/29293637/how-to-append-whole-set-of-model-to-formdata-and-obtain-it-in-mvc/29293681#29293681) –  Sep 17 '17 at 21:40
  • @StephenMuecke I tried it but the formdata, when passed to the api action, comes empty. I tried also doing this var formdata = new FormData($('#MyForm').get(0)); – ev vk Sep 18 '17 at 01:17
  • Then I can only assume you did not set the correct ajax options. –  Sep 18 '17 at 01:21
  • when I inspect the formdata object, it is an empty one. – ev vk Sep 18 '17 at 01:37

1 Answers1

0

When calling the $.ajax method to send files via FormData, you need to specify processData and contentType property values to false.

var url ='/api/ProfesorCurso/test';
$.ajax({
    url: url,
    type: 'PUT',
    data: viewmodel,
    processData: false,
    contentType: false,
    success: function (data) {
        console.log(data);
        return false;
    },
    error: function (x, y, z) {
        alert('error al postear');
        return false;
    }
});
Shyju
  • 214,206
  • 104
  • 411
  • 497