Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 275 Vote(s) - 3.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to do a ASP.NET MVC Ajax form post with multipart/form-data?

#1
I am working on a ASP.NET MVC web site which has a form that allows for the upload of files using the multipart/form data enctype option on the form tag like so

<form enctype="multipart/form-data" method="post" action='<%= Url.Action("Post","Entries",new {id=ViewData.Model.MemberDetermination.DeterminationMemberID}) %>'>

How would I write this to do an ASP.NET MVC Ajax form post instead?
Reply

#2
The [jquery forms plugin][2] supports [file uploads][1] in this way.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#3
I actually answered the question myself...

<% using (Ajax.BeginForm("Post", "Entries", new { id = ViewData.Model.MemberDetermination.DeterminationMemberID }, new AjaxOptions { UpdateTargetId = "dc_goal_placeholder" }, new { enctype = "multipart/form-data" }))
Reply

#4
***For those who still have problems using `@Ajax.BeginForm` for multipart enctypes / file uploads in MVC***
# Diagnosis and proposed solution #
Running the “Inspect element” tool on a form element generated by the `@Ajax.BeginForm` helper reveals that the helper, rather inexplicably, overrides the controller parameter specified. This is the case if you implemented a separate controller for your partial postback.

A quick-fix for the problem is to explicitly specify your html action attribute value as `/<yourcontrollername>/<youractionname>`.
<br/>

## Example ##

@using (Ajax.BeginForm("", "", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "<TargetElementId>", InsertionMode = InsertionMode.Replace }, new { enctype = "multipart/form-data", action = "/<Controller>/<Action>" }))
Reply

#5
1. You can use some additional uploaders (e.g. [jQuery multiple file uploader][1]) (I prefer this way and I prefer not to use MS Ajax)
2. Use:

AjaxHelper.BeginForm("Post", "Entries", new {id=ViewData.Model.MemberDetermination.DeterminationMemberID}, new AjaxOptions(){/*some options*/}, new {enctype="multipart/form-data"})

But in second case I'm not sure that it will work.


[1]:

[To see links please register here]

Reply

#6
It is possible but it's a long way.
Step 1: write your form

ex:

@using (Ajax.BeginForm(YourMethod, YourController, new { id= Model.Id }, new AjaxOptions {//needed options }, new { enctype = "multipart/form-data" }))
{
<input type="file" id="image" name="image" />
<input type="submit" value="Modify" />
}

Step 2: intercept the request and send it to the server

<script type="text/javascript">
$(function() {
$("#form0").submit(function(event) {
var dataString;
event.preventDefault();
var action = $("#form0").attr("action");
if ($("#form0").attr("enctype") == "multipart/form-data") {
//this only works in some browsers.
//purpose? to submit files over ajax. because screw iframes.
//also, we need to call .get(0) on the jQuery element to turn it into a regular DOM element so that FormData can use it.
dataString = new FormData($("#form0").get(0));
contentType = false;
processData = false;
} else {
// regular form, do your own thing if you need it
}
$.ajax({
type: "POST",
url: action,
data: dataString,
dataType: "json", //change to your own, else read my note above on enabling the JsonValueProviderFactory in MVC
contentType: contentType,
processData: processData,
success: function(data) {
//BTW, data is one of the worst names you can make for a variable
//handleSuccessFunctionHERE(data);
},
error: function(jqXHR, textStatus, errorThrown) {
//do your own thing
alert("fail");
}
});
}); //end .submit()
});
</script>

Step 3: Because you make an ajax call you probably want to replace some image or something of `multipart/form-data`

ex:

handleSuccessFunctionHERE(data)
{
$.ajax({
type: "GET",
url: "/Profile/GetImageModified",
data: {},
dataType: "text",
success: function (MSG) {
$("#imageUploaded").attr("src", "data:image/gif;base64,"+msg);
},
error: function (msg) {
alert(msg);
}
});
}

The MSG variable is an base64 encrypted string. In my case it's the source of the image.

In this way I managed to change a profile picture and after that the picture is immediately updated.
Also make sure you add in *Application_Start (global.asax)*
`ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());`
Pretty nice no?

P.S.: This Solution works so don't hesitate to ask more details.
Reply

#7
I came across this little hack, which resolves it nicely

window.addEventListener("submit", function (e) {
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
if (form.dataset.ajaxUpdate) {
var updateTarget = document.querySelector(form.dataset.ajaxUpdate);
if (updateTarget) {
updateTarget.innerHTML = xhr.responseText;
}
}
}
};
xhr.send(new FormData(form));
}
}
}, true);

Reply

#8
Ajax.BegineForm() works with multipart form data and here's the working code example for the same:

**View:**

@using(Ajax.BeginForm("UploadFile","MyPOC",
new AjaxOptions {
HttpMethod = "POST"
},
new
{
enctype = "multipart/form-data"
}))
{
<input type="file" name="files" id="fileUploaderControl" />
<input type="submit" value="Upload" id="btnFileUpload" />
}

**Controller Action Method:**

public void UploadFile(IEnumerable<HttpPostedFileBase> files)
{
HttpPostedFileBase file = files.FirstOrDefault(); //Attach a debugger here and check whether you are getting your file on server side or null.
if (file != null && file.ContentLength > 0)
{
//Do other validations before saving the file

//Save File
file.SaveAs(path);
}
}


P.S. Make sure the "name" attribute of the file uploader control and the name of the parameter passed to Action method UploadFile() has to be same (i.e. "files" in this case).
Reply

#9
From my little investigation. All the answers above seems to be correct depending on the problem one is having with the Ajax.BeginForm. However, I have just observe that the problem is with the ~/Scripts/jquery.unobtrusive-ajax.min.js javascript library in some case. So in my case I just removed it from the view model and sort of decided to use JQuery Form plugin for my required need along with the HTML Form instead. This has been suggested above.
Reply

#10
Code which I used and it works !! It's a copy of @James 'Fluffy' Burton solution. I just improvising his answer so that people who is new to MVC will be able to quickly understand the consequences.

Following are my View:

@using (Ajax.BeginForm("FileUploader", null, new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "AjaxUpdatePanel" }, new { enctype = "multipart/form-data", id = "frmUploader" })){
<div id="AjaxUpdatePanel">
<div class="form-group">
<input type="file" id="dataFile" name="upload" />
</div>

<div class="form-group">
<input type="submit" value="Upload" class="btn btn-default" id="btnUpload"/>
</div>

</div>}

<script>
window.addEventListener("submit", function (e) {
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
if (form.dataset.ajaxUpdate) {
var updateTarget = document.querySelector(form.dataset.ajaxUpdate);
if (updateTarget) {
updateTarget.innerHTML = xhr.responseText;
}
}
}
};
xhr.send(new FormData(form));
}
}
}, true);
</script>

Following are my controller:

[HttpPost]
public JsonResult FileUploader(HttpPostedFileBase upload)
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{

if (upload.FileName.EndsWith(".csv"))
{
Stream stream = upload.InputStream;
DataTable csvTable = new DataTable();
using (CsvReader csvReader = new CsvReader(new StreamReader(stream), true))
{
csvTable.Load(csvReader);
}
}
else
{
return Json(new { dataerror = true, errormsg = "This file format is not supported" });
}
}
else
{
return Json(new { dataerror = true, errormsg = "Please Upload Your file" });
}
}
return Json(new { result = true });
}

Following is the quick Note of above code:
Through Ajax, I have posted my excel (*.csv) file to Server and read it to an DataTable using a Nuget package (LumenWorksCsvReader).

Hurray! It works. Thanks @James
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through