Ajax.BeginForm is not working as expected - asp.net

I have a very strange problem with Aajx.BeginForm. I have this code :
In view :
#using (Ajax.BeginForm("Upload", "Profile", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<input type="file" name="files"><br>
<input type="submit" value="Upload File to Server">
}
In controller :
[HttpPost]
[ValidateAntiForgeryToken]
public void Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files != null)
{
foreach (var file in files)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// TODO: need to define destination
var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
file.SaveAs(path);
}
}
}
}
The problem is that I get null file when the form is submit. I read many question that is the same of my question, but most of the answers was that the name of input type="file" is not as the same name of the parameter name in the controller. I found some examples, I try this one which is almost the same of my code except for the jquery files, so I tried to replace the jquery files with these files :
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
And here is the surprise !!. When the form is submit, I get the file but the form is post back. It is work as there is no ajax. I search in google for Ajax.BeginFrom that is post back and found many solutions in stackoverflow and most of of the answers was that jquery.unobtrusive-ajax file must be included in the page. It like a circle of problems, once you solve one you get another. Does I miss something ?

You cannot submit files with Ajax.BeginForm(). The helper uses the jquery.unobtrusive-ajax.js file to submit the data using ajax functions which do not allow multipart/form-data enctype.
One option is to use FormData (but not supported in older browsers). Change the Ajax.BeginForm() to Html.BeginForm() and then handle the forms submit event
$('form').submit(function() {
var formdata = new FormData($('form').get(0));
$.ajax({
url: '#Url.Action("YourActionName", "YourControllerName")',
type: 'POST',
data: formdata,
processData: false,
contentType: false,
success: function() {
.... // do something?
}
});
});
In addition there are numerous jquery plugins that you can use for uploading files (14 of them are listed here)
Side note: Your file input allows selection of only one file, so your method parameter should be HttpPostedFileBase files (not IEnumerable<HttpPostedFileBase> files) or alternatively, include the multiple attribute in the file input.

You need to specify the encoding type in your form.
#using (Ajax.BeginForm("Upload", "ControllerName", new AjaxOptions { HttpMethod = "POST"}, new { enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<input type="file" name="files"><br>
<input type="submit" value="Upload File to Server">
}

Related

Calling method from razor page

I have a asp.net core mvc project.
In my layout file, I want to display the name of the currently logged in user, such that the username is displayed in the header. For this, I want to be able to call a function in my homecontroller that does this.
So, I made a simple function taht looks like this in the home controller:
public String GetLoggedInuser()
{
return "garse garsebro";
}
And then I have tried every method I have been able to find. The first couple of methods here are just function suggested around the web, that are simply not available to me:
#HtmlHelper.Action("GetLoggedInuser");
#Html.RenderAction("GetLoggedInuser");
To name a few. Then there is this one, which I can find:
#Html.ActionLink("GetLoggedInuser")
But for this one, my function "GetLoggedInuser" can't be found anywhere.
How do you, in a razor page call a controller function that you can get returned a string from that function and display it?
If you are using Microsoft.AspNet.Identity then below line will do the work post login.
#Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
You can try to use ajax to call action to get the username,and add it to html:
<div id="username">
</div>
#section scripts
{
<script>
$(function () {
$.ajax({
type: "GET",
url: 'GetLoggedInuser',
}).done(function (result) {
$("#username").html(result);
});
})
</script>
}

src vs srctarget vs srcwait

I continue to work on a project that I do not fully understand yet. I encountered the following line of code:
<iframe id="AddDialog" style ="overflow: hidden; width:1150px; height:450px;" class="Dialogframe" scrolling="no" srcwait=#Html.Raw("'" + Url.Action("Index", "FieldChooser") + "'") srctarget=#Html.Raw("\"" + Url.Action("Index", "FieldChooser", new { ColumnFormat = false, resultmodel = Guid.Empty, datatype = "", multiselect=false }) + "\"") src=#Html.Raw("\"" + Url.Action("Loading", "FieldChooser") + "\"")></iframe>
Visual Studio tells me that srcwait and srctarget are not valid HTML5-elements, but it seems to work. The Loading View is shown for a few seconds and then the Index() method is executed (the one called in srctarget).
I am also not able to find anything on the internet about the attributes srctarget and srcwait. So what are the differences between src, srctarget and srcwait? Do they even exist or is that some invention of the person that worked on it before me?
I have a function in the FieldChooserController
[HttpPost]
public ActionResult Index(string id)
{
...
}
I want this to be called when I click on the OK button. I assumed that the srcwait part is meant for that because the call looks like that, but the function is never called.
Please bear with me and tell me if you need to see more code, at this point I have no idea what is important.
buttons: {
OK: function() {
//Save selected Value
$( this ).dialog( "close" );
if (GlobalName !=''){
addwhere(GlobalName,opts.sourceel,GlobalDefVal,GlobalDataType,GlobalValue);
}
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
},
Cancel: function() {
$( this ).dialog( "close" );
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
}
}
There most probably is a piece of JavaScript running, which sets the src to srcwait when an operation is performed where the user will be waiting for a wile, for example to show a loading screen.
As for your code, if you have a HttpPost annotated Index() method you wish to call upon a button click, you must create a form and let it post there:
#using (Html.BeginForm("Index", "FieldChooser", FormMethod.Post)
{
<input value="OK" type="submit" />
}

In ASP.NET, a POST/Redirect/GET sequence with AJAX hits the redirected-to action twice

Inside a view, I have the following:
#using (Html.BeginForm())
{
<input type="submit" id="savebtn" value="Save" onclick="saveLayout()"/>
}
<script type="text/javascript">
function saveLayout() {
$.ajax({
url: '/Page/SaveFaces/',
data: {
/* layout data of the page, irrelevant */
},
type: 'post',
success: function () {
}
});
return false;
}
</script>
The above hits the following action, which simply redirects the user back to the URL they came from (it's also supposed to save the data, but I've removed that part for simplicity, as it doesn't affect the problem):
[HttpPost]
public ActionResult SaveFaces(string items)
{
return Redirect(Request.UrlReferrer.AbsoluteUri);
}
Then, due to the redirect, we go back to this pretty standard model-fetching action:
public ActionResult Index(int id = 0)
{
var page = db.Pages.Find(id);
if (page == null) return HttpNotFound();
return View(page);
}
The problem is that this last action is called twice.
I have tried removing the AJAX call and doing a normal POST operation and the problem goes away. However, the data I'm trying to send is obtainable only through the a jQuery script and I can't put them in a form. I'm constrained to work with the AJAX method.
Is there anything I can do to prevent the action from being hit twice?
I see you are using jQuery. Can you try this instead? (Note you may have to bind the the form submit event rather than the input button, or both)
#using (Html.BeginForm())
{
<input type="submit" id="savebtn" value="Save" >
}
<script type="text/javascript">
$("#savebtn").submit(function saveLayout(event) {
// The magic that prevents post.
event.preventDefault();
$.ajax({
url: '/Page/SaveFaces/',
data: {
/* layout data of the page, irrelevant */
},
type: 'post',
success: function () {
}
});
return false;
}
</script>
Also if you have access to form element, another way:
<form onsubmit="javascript: return false;">
Though it might be a bit specific to my scenario, I just found an acceptable solution. Since all the data is provided through jQuery, I removed the form completely and replaced the submit button with a simple link.
So, this goes away:
#using (Html.BeginForm())
{
<input type="submit" id="savebtn" value="Save" />
}
And this is put in place instead:
<a onclick="saveLayout()" id="saveLink">Click to save.</a>
Now the [HttpPost] action is hit, the data is saved and the redirected-to action is also hit, once.

asp.net mvc jquery form plugin upload(file not recieved by the controller)

i am using jquery form plugin for file upload . i am not able to get file in the controller . what could be wrong.
public string CreateOrganizationMeta()
{
foreach (string file in Request.Files)
{
HttpPostedFileBase postedFile = Request.Files[file];
}
}
$(document).ready(function () {
$('#MyForm').ajaxForm({
});
});
<% using (Html.BeginForm("Organization", "CreateOrganizationMeta", FormMethod.Post, new { id = "MyForm", enctype = "multipart/form-data", onsubmit = "return submitForm2(this)" }))
{ %>
<input type="file" name="Logo2" id="Logo2" />
I don't think you can upload files using ajax. There are some workarounds for this though.
Try googling for file uploads with ajax
The documentation for this plugin states that it supports file uploads.
I've used Andrew Valums' Ajax Upload on several projects and it works great. May be an alternative to consider.

asp.net mvc json open dialog box problem

function postForm()
{
$.ajax({
type: "POST",
data: $("#myForm").serialize(),
dataType: "json",
url: '<%= Url.Action("JSONRequest","Home") %>',
success: function(result)
{
window.alert(result.name);
},
error : function()
{
window.alert('error');
}
});
}
Html.BeginForm("JSONRequest", "Home", FormMethod.Post, new { id = "myForm" });
Html.TextBox("mazhar")
<input type="submit" onclick="postForm" />
Html.EndForm();
public ActionResult JSONRequest(FormCollection form)
{
string a = form["mazhar"];
var data = new { name = "aaaa", Success = "Record is Succesfully Saved", ErrorMessages = "abc" };
return Json(data);
}
Ok the problem is that the dialog box is opening after running this code which is asking to save file.
Can someone tell me how to resolve this issue? Why does this box comes afterall?
You need to cancel the default form submission by returning false inside the button onclick handler:
<input type="submit" onclick="postForm(); return false;" />
That being said, I would suggest you a better solution. Use the jquery.form plugin which enables you to ajaxify an HTML form. This way much of the duplication in your code could be simplified:
Html.BeginForm("JSONRequest", "Home", FormMethod.Post, new { id = "myForm" });
Html.TextBox("mazhar")
<input type="submit" value="OK" />
Html.EndForm();
And in javascript:
$(function() {
$('#myForm').ajaxForm({
success: function(result) {
window.alert(result.name);
},
error : function() {
window.alert('error');
}
});
});
This way you no longer need to specify url, method, manually serialize form fields, etc... You also don't need to pollute your HTML markup with javascript functions. This is unobtrusive javascript. Another advantage of this approach is that now you will be able to externalize this javascript into a separate static .js file as it no longer relies on server side code (<%= Url.Action("JSONRequest","Home") %>) and this you will benefit from reducing the bandwidth and caching static resources.
I think you are posting the form twice. You should use Ajax.BeginForm instead of normal form. And remove the jQuery Ajax call.
Here is a very good example of using Ajax Form.
http://davidhayden.com/blog/dave/archive/2009/05/19/ASPNETMVCAjaxBeginForm.aspx
Or you can also try by replacing
<input type="submit" onclick="postForm" />
with
<input type="button" onclick="postForm" />

Resources