📜 ⬆️ ⬇️

Modifying ajax js for ajax Asp .net mvc

Many novice C # ASP .NET MVC programmers (hereinafter referred to as mvc) are faced with the task of sending data using Ajax. That's just in practice, this task is not so easy.

In my work, I try to adhere to certain principles of software development. One of them is minimization of writing code and creating universal classes and functions. This principle assumed the use of jquery.unobtrusive-ajax.js and the Ajax class for mvc .

In this article, we are directly interested in Ajax.BeginForm.

Example:
')
@using (Ajax.BeginForm("UploadAvatarImage", "Dashboard", null, new AjaxOptions {HttpMethod = "POST", OnSuccess = "UpdateAvatars()", OnFailure = "document.refresh()" }, new {Id = "UploadAvatartForm", enctype = "multipart/form-data" })) { <div class="input-group pt-1 pl-1"> <input type="file" name="avatarFile" class="form-control" id="fileUploaderControl" accept=".jpg"/> </div> <button class="btn btn-sm btn-primary btn-block m-1" type="submit" ></button> } 

Faced with the fact that Ajax.BeginForm does not pass input [type = file], I conducted a global search to find a solution to this problem. The old favorite stackoverflow on each solution offered the same thing. Do not use Ajax.BeginForm, use FormData, make a php handler and more clouds of tips for increasing code.

As I said earlier, in my products I adhere to the principles and since the answer that would satisfy my requirements was not found, I had to do everything myself.

The first thing that was needed is to determine which function in jquery.unobtrusive-ajax.js is responsible for generating the data.

 $(document).on("submit", "form[data-ajax=true]", function (evt) { var clickInfo = $(this).data(data_click) || [], clickTarget = $(this).data(data_target), isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); evt.preventDefault(); if (!isCancel && !validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET", //     data: clickInfo.concat($(this).serializeArray()) }); }); 

We are interested in the function $ (this) .serializeArray () . In the $ (this) variable, our form <form /> comes in and then it is sold to an array. Having tested it in the console, as well as its analogue serialize (), it was determined that these functions do not load files in principle. Hence the decision to rewrite it.

But first you need to solve the problem with downloading the file, for this we use the FileReader class.

 $(document).on("change", "form[data-ajax=true] input[type=file]", function (evt) { var form = $($(evt.target).parents("form")[0]); if (evt.target.files.length > 0) { var fileObj = evt.target.files[0]; var reader = new FileReader(); reader.onload = function () { evt.target.setAttribute("data-ajax-image-data", reader.result); form.find("button[type=submit]")[0].classList.remove("disabled"); } reader.onerror = function () { console.log("Error while loading"); form.find("button[type=submit]")[0].classList.remove("disabled"); } form.find("button[type=submit]")[0].classList.add("disabled"); reader.readAsDataURL(fileObj); } }); 

A little about the code.

First, we tie the event change input, the choice fell on «change».

Then we check if the file is selected.

If the file is selected then we start downloading it. The problem was that the data should be stored somewhere, in the example we will write the data in the attribute of the object itself.

Lock the confirmation button until the file is downloaded.

In case of errors, write it to the console. This is not the final version of the function, everyone can upgrade it to fit their needs.

Once we have created the file data download, go to the serialization upgrade.

 function selfFormSerializeArray(form) { var array = form.serializeArray(); for (var i = 0; i < form[0].length; i++) { if (form[0][i].type === "file") { var fileObj = form[0][i]; var data = fileObj.getAttribute("data-ajax-image-data") || ""; if (data !== "") { array.push({ name: fileObj.name, value: data }); // console.log("SUCCESS"); } else { //console.log("ERROR"); } } } return array; } 

And we use this function in the main function.

 $(document).on("submit", "form[data-ajax=true]", function (evt) { var clickInfo = $(this).data(data_click) || [], clickTarget = $(this).data(data_target), isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); evt.preventDefault(); if (!isCancel && !validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET", data: clickInfo.concat(selfFormSerializeArray($(this))) // clickInfo.concat($(this).serializeArray()) }); }); 

Upon completion, the handler and data parser are required. In haste, it looks like this.

Handler

 public PartialViewResult UploadAvatarImage() { if (!ImageHelper.LoadAvatarImage(this.Request.Form["avatarFile"])) { return null; } return PartialView("Null"); } 

Helper

 public static bool LoadAvatarImage(string data) { try { var file = AjaxFile.Create(data); return true; } catch (Exception ex) { return false; } 

Parser

 public AjaxFile(string data) { var infos = data.Split(','); this.Type = infos[0].Split(';')[0].Split(':')[1].Split('/')[1]; this.Source = Convert.FromBase64String(infos[1]); ; } public static AjaxFile Create(string data) { return new AjaxFile(data); } 

Congratulations! Now you can upload files using standard Ajax for mvc.

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


All Articles