Home > Mobile >  Upload files using .Net 6 MVC model biding serialization by jQuery Ajax/JSON
Upload files using .Net 6 MVC model biding serialization by jQuery Ajax/JSON

Time:03-21

Need to upload files using MVC model biding by AJAX jQuery/JSON.

I was uploading with a normal submit form, but now I need to change to AJAX. How can I do this? I mean, biding using MVC and AJAX, serializing my form or something like that.

Now, my imagemPro and imagemPre, on Controller, are always 'null'.

At my View:

    @model Ri.Models.Produto

    <form  id="frmAdd" enctype="multipart/form-data">
       <label for="setting-input-1" >Título</label>
       <input asp-for="@Model.TituloProduto" type="text"  required>
       <input asp-for="@Model.ImagemProduto" type="file"  required>

       <label for="setting-input-1" >Premio</label>
       <input asp-for="@Model.TituloPremio" type="text"  required>
       <input asp-for="@Model.ImagemPremio" type="file"  required>
                            
       <input type="button" value="Criar"  id="btnAdd">
    </form>     
            
    @section scripts{
        <script src="~/admin/js/produtoAdd.js"></script>
    }

At my Controller:

[HttpPost("/api/ProdutoAdd")]
public async Task<IActionResult> ProdutoAdd([Bind("TituloProduto,ImagemProduto,TituloPremio,ImagemPremio")] Produto produto, IFormFile imagemPro, IFormFile imagemPre)
{
    if (!ModelState.IsValid)
    {
        return Json(new { success = false, msg = "1" });
    }
   
    if (imagemPro != null)
    {
        var name = Path.Combine(_enviroment.WebRootPath   "/imgs", System.IO.Path.GetFileName(imagemPro.FileName));
        await imagemPro.CopyToAsync(new FileStream(name, FileMode.Create));
        produto.ImagemProduto = imagemPro.FileName;
     }

     if (imagemPro != null)
     {
        var name = Path.Combine(_enviroment.WebRootPath   "/imgs", System.IO.Path.GetFileName(imagemPre.FileName));
        await imagemPro.CopyToAsync(new FileStream(name, FileMode.Create));
        produto.ImagemPremio = imagemPre.FileName;
     }

     _context.Add(produto);
     await _context.SaveChangesAsync();
   
     return Json(new { success = true });
}

My script:

$(function () {
    $("#btnAdd").click(function (e) {
        e.preventDefault();
        var _this = $(this);
        var _form = _this.closest("form");

        var isvalid = _form.valid();

        if (isvalid) {
            Create();
        }
        else {
            //alert('false');
        }
    });

    Create = function () {
        var options = {};
        options.type = "POST";
        options.url = "/api/ProdutoAdd";
        options.dataType = "JSON";
        options.cache = true;
        options.async = true;
        contentType = "application/json; charset=utf-8",
        options.data = $('#frmAdd').serialize();

        options.beforeSend = function (xhr) {
            xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
        };

        options.success = function (data) {
        };

        options.error = function (res) {

        };
        $.ajax(options);
    };
});

CodePudding user response:

Your payload and your content type don't match. jQuery.serialize encodes your form data as application/x-www-form-urlencoded, but you're telling the server to expect a content type of application/json. Easiest solution is to change the content type.

Also, you might want to use the form submit event of the form, rather than a 'click' event on a button. The reason for this is that browsers will submit forms in other ways besides clicking the button, (e.g. pressing "enter" key while in a text input). Submit will handle all of these methods.

Another side note: your method of creating your options object will work, but that syntax is a little awkward. The most common "best practice" is to declare the properties inline with the object:

var options = {
  type: 'POST',
  url: '/api/ProdutoAdd',
  // etc ...
  success: function (data) {
  },
  // etc ...
};

That keeps you from having to type options. before every property.

CodePudding user response:

I recommend you to create a viewModel

public class ProdutoViewModel
{
public Produto Produto  {get; set;} 
public IFormFile ImagemPro {get; set;}
public IFormFile ImagemPre {get; set;}
}

action ( remove Bind attribute too)

[HttpPost("/api/ProdutoAdd")]
public async Task<IActionResult> ProdutoAdd(ProdutoViewModel model )

I recommend you to use a submit button instead of ajax, it would be much easier for you

@model Ri.Models.Produto

    <form  id="frmAdd" enctype="multipart/form-data">
       ....
           
       <input type="submit" value="Criar" >
    </form>     
  • Related