I want to submit a form using ajax. For this i am using Jquery AjaxForm plugin. Form containing file and some data which needs to be submit using AJAX to struts2 action. First time form is submitting properly and i am getting error message which expected as i and doing some server side validation. But when i submitting form second time form with correct information the form not submitting to the action.
I have search for the issue, and i came to know it is due to token i am using, as second time token value was miss matched.
How would i can resolved this issue or some hit by which i can update form token value.
Code Sample:
<s:form id="uploadForm" name="uploadForm" action="usrUploadFormat" method="post" validate="true" enctype="multipart/form-data" autocomplete="off">
<div class="fields-format-wraper ulb-upload-wrapper">
<div class="error-wrapper">
<s:fielderror/>
<s:actionerror/>
<ul class='errorMessage passwdError' id="errors">
</ul>
</div>
<div class="fields-row" style="display: none;">
<div class="doc-check-wrapper">
<s:token/>
</div>
</div>
<div class="fields-row" id="doc-field">
<span><s:label cssClass="label" value="Upload*"/></span>
<span><s:file cssClass="inputFields inputs format file" id="formatToUpload" name="formatToUpload" accept="application/ms-excel,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"></s:file> </span>
</div>
<div class="fields-row formats-row btn-upload-wrapper">
<span style="float:left;margin-left: 175px;"><input type="button" class="btn-submit" value="Upload" name="auth" id="upload-now"/></span>
</div>
</div>
</s:form>
Ajax Calling for the form:
var options = {
success: function(msg)
{
var msgs = msg.split(":");
if(msgs.length>0){
if(msgs[0] == "Error"){
$('.errorMessage.passwdError').empty();
var counter = 0;
$.each( msgs, function( key, value ) {
counter++;
if(counter == 1)
return;
$('.errorMessage.passwdError').append("<li>"+value+"</li>");
});
window.parent.jQuery.fancybox.hideLoading();
} else{
alert(msgs[0]);
}
}
},
error: function(err)
{
jAlert("unable to upload file.",
'Upload Report Format Error.',
function (r) {
if(r == true){
window.parent.location.reload();
window.parent.jQuery.fancybox.close();
}
});
},
beforeSubmit: function(arr, $form, options) {
window.parent.jQuery.fancybox.showLoading();
}
};
$("#uploadReportFormatsForm").ajaxForm(options);
struts.xml
<interceptor-stack name="pmidcCSRFStack">
<interceptor-ref name="tokenSession">
<param name="includeMethods">*</param>
</interceptor-ref>
<interceptor-ref name="dataSourceCheck"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<action name="usrUploadFormat" class="com.org.pmidc.action.ULB_UploadReport">
<interceptor-ref name="pmidcCSRFStack"/>
<result name="invalid.token" type="tiles">csrfError</result>
<interceptor-ref name="i18n"/>
<interceptor-ref name="fileUpload">
<param name="allowedTypes">application/pdf,application/ms-excel,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document</param>
<param name="maximumSize">1048576000000</param>
</interceptor-ref>
</action>
When i submitting form with server side error like choose wrong format pdf, or file size is greater then allowed, then i get error size or file format is not allowed. Once i correct all the error and submit form again the then request not go to the action execute, instead response is return from token interceptor. I came to know this because of log when warning show that token mis matched.
It means it is clear that form is not submitting due error with token. So the solution would be update token value, here i stuck. How to update or refresh token value for next time i submit form.
Related
I got an URL. There is a form in that URL and I know it's name and the form action.
E.g:
url:
www.abc.com/123.html
form:
<form action="POST.php" method="post" name="form">
<input id="id" name="name" type="text">
</form>
My question is how do I post this form and get the response? It seems some functions in PHP like fget and fputs have a security violation and i don't want to use them. I have tried several answers but they didn't work well. Any programming language is fine.
POST is, to the contrary GET, the more secure way to get data to the Server. If you want the "answer" from the server displayed in the same page you go with AJAX.
http://www.w3schools.com/jquery/ajax_ajax.asp
Here is a possible jQuery solution:
HTML:
<form action="POST.php" method="post" name="form">
<input id="id" name="name" type="text">
<button id="submit">submit</button>
</form>
<div id="serverresponse"></div>
PHP:
<?php
echo("Name is: " . $_POST['name']);
?>
jQuery:
$("#submit").click(function(){
$.ajax({
type: "POST",
url: "POST.php",
data: $('#id').serialize(),
async: false,
success: function(response){
$("#serverresponse").html(response);
},
error: function(text){
$("#serverresponse").html(response);
}
});
return false;
});
This sends the content of the "name" input to the POST.php witch is just returning it and the response is displayed in the "serverresponse" div.
But you have to make sure jQuery is loaded.
My JSF page is as follows
<h:head>
<title>Ajax Test</title>
<h:outputScript name="giveEffect.js" library="jquery"/>
<h:outputScript name="jquery.js" library="jquery"/>
</h:head>
<h:body>
<div id="div1">
<h:button id="b1" onclick=" button1Click(this)" value="#{kp.firstname}"/>
<h:button id="b2" onclick="button1Click(this)" value="#{kp.home}"/>
</div>
</h:body>
</html>
button1Click is a jquery function which does ajax call and updates my page. But unable to see ajax update. Due to postback/jsf life cylce call, I changes are getting lost.
On inspecting the Dom using firebug. I found the following code.
<div id="div1">
<input id="b1" type="button" value="Kar" onclick="button1Click(this); window.location.href='/AJAXTest/faces/index.xhtml'; return false;">
<input id="b2" type="button" value="Alike" onclick="button1Click(this); window.location.href='/AJAXTest/faces/index.xhtml'; return false;">
</div>
Suppose I eliminate window.location.href='/AJAXTest/faces/index.xhtml' using firebug I get the expected output.
Is there any tag or mechanism to remove postback call?
The button component's outcome attribute is used to determine the target URL which is activated by onclick. The entire target URL string will be written out to the onclick attribute of the button as "window.location.href = ''". If you have a custom onclick method the window.location.href will be appended at the end of your script. Since you did not mention an outcome it will result in a GET request to your current view.
You can instead use
<h:commandButton> and mention type="button" like this:
<h:commandButton id="b1" onclick=" button1Click(this)" value="#{kp.firstname} "type="button">
Documentation
I have a page with a input box and a button, when the user clicks the button i want to redirect to a controller action that has as parameter the value of the input box.
<input id="CodProiect" type="text" />
<input id="Cauta" type="button" value="Cauta" onclick="window.location.href='#Url.Action("Cauta", "Componente", new { CodProiect = "param" })';"/>
How can i get the "param" from the input box ?
You could just use a form with a GET method
<form action="#Url.Action("Cauta", "Componente")" method="GET">
<input id="CodProiect" name="CodProiect" type="text" />
<input id="Cauta" type="submit" value="Cauta" />
</form>
The form will add the parameter as part of the query string of the URL e.g. www.yoursite.com/Cauta/Componente?CodProiect=user+entered+value
Value of the Action is prepared at server side and sent to the browser so you cannot have the value at the server when it is a user input.
You can use jquery to change the URL at client side.
Also passing state in an PRG scenario is a common problem in ASP NET MVC. You can either:
Store it temporarily in session
Pass it as a parameter in URL
Use a form.
Form:
<form action="Componente/Cauta">
<input id="CodProiect" type="text" />
<input id="Cauta" type="submit" value="Cauta" />
</form>
Controller:
public ActionResult Cauta(string CodProiect)
{
//Do some stuff
}
More info: http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx
Syntax may be outdated, but you get the point...
I have a View in which the user is able to upload a file to the server.
In this view I also have 2 buttons: one to Upload a file and other to Download the last file imported.
In my Controller I created 2 action methods: Import and Export.
How could I manage to redirect each button click to the proper action method in my Controller?
I have tried Html.ActionLink:
<%= Html.ActionLink("Upload", "Import", "OracleFile")%>
<%= Html.ActionLink("Download", "Export", "OracleFile")%>
Html.ActionLink didn't do the trick. The action links were taking me to the right Action methods but they were generating a GET request. This way Request.Files.Count = 0.
I need a POST request.
Note: the most intriguing part is that the upload was working and all of sudden it stopped working. I've seen that some people are having the same problem with FileUpload tasks in which the Request.Files is always Empty. I think it's empty because you need a post to the server. Isn't it?
maybe this will give u the idea:
view:
<form enctype="multipart/form-data" method="post" action="/Media/Upload/Photo">
<input type="file" name="file" id="file" />
<input type="submit" name= "submitImport" value="Upload" />
<input type="submit" name = "submitExport" value="Download" />
</form>
controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Action (FormCollection formCollection)
{
if (formCollection["submitImport"] != null)
{
return Import(formCollection);
}
if (formCollection["submitExport"] != null)
{
return Export(formCollection);
}
}
the Export and Import are the appropriateactions
You have to use a "multipart/form-data" form, and submit the form. No ActionLink.
<form enctype="multipart/form-data" method="post" action="/Media/Upload/Photo">
<input type="file" name="file" id="file" />
<input type="submit" value="Upload" />
</form>
To generate a POST request for the upload, use the File Input form element and just post back to the server ala normal.
http://www.w3schools.com/jsref/dom_obj_fileupload.asp
Have a look at this blog post from Scott Hanselman.
http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFileUploadWithASPNETMVCIncludingTestsAndMocks.aspx
If you are using Ajax.BeginForm() with multiple submit buttons similar to this:
// View.aspx
<% using (Ajax.BeginForm("Action", "Controller",
new AjaxOptions { UpdateTargetId = "MyControl", }))
{ %>
<span id="MyControl">
<% Html.RenderPartial("MyControl"); %>
</span>
<% } %>
//MyControl.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input name="prev" type="submit" value="prev" />
<input name="next" type="submit" value="next" />
//...
Everything is submitted to the controller fine but the params for the submit button that was clicked are absent from the Request. In otherwords Request["next"] and Request["prev"] are always null.
I looked in to the JavaScript in Microsoft.MvcAjax.js and it looks like the function Sys_Mvc_MvcHelpers$_serializeForm completely skips over the inputs that are of type 'submit'.
This doesn't seem logical at all. How else can you find out what button has been clicked?
It looks like a bug to me. Is there any logical reason to skip these form parameters?
UPDATE: 2009-11-21
I downloaded MVC Release 2 Preview 2 and looked to see if this problem was fixed.
I did a quick test and found similar results to MVC Release 2 Preview 1.
I don't believe it is fixed yet.
UPDATE: 2009-08-07
I downloaded MVC Release 2 Preview 1 and looked to see if this problem was fixed.
I see a new function in the script MicrosoftMvcAjax.debug.js called _serializeSubmitButton and I see that when Ajax.BeginForm() renders the output there is a onclick event but when this event fires it generates an error "Microsoft JScript runtime error: 'Sys.Mvc.AsyncForm' is null or not an object".
In short it looks like a fix was attempted but it isn't working yet or I need to do something more. The bad news is if it isn't the later then Ajax Forms will be broken for everyone until the fix is complete.
UPDATE: 2009-05-07
I received feedback today from Microsoft confirming that this is a bug. They have logged the defect and said they hope to have it fixed in a future release.
For reference I'm leaving the details of my investigation that I submitted to Microsoft. Appologies for the long post but perhaps it will be useful for anyone trying to create a work around..
There are a couple problems in the Ajax support in MVC. To illustrate, consider the pattern illustrated in several examples on the web:
//===========
// View.aspx
//===========
<% using (Ajax.BeginForm("Action", "Controller",
new AjaxOptions { UpdateTargetId = "MyControl", HttpMethod = "POST"}))
{ %>
<span id="MyControl">
<% Html.RenderPartial("MyControl"); %>
</span>
<% } %>
//================
// MyControl.ascx
//================
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input name="startIndex" type="hidden" value="0" />
<%= Ajax.ActionLink("Prev", "PrevAction",
new AjaxOptions() { UpdateTargetId="MyControl", HttpMethod="POST"}) %>
<%= Ajax.ActionLink("Next", "NextAction",
new AjaxOptions() { UpdateTargetId="MyControl", HttpMethod="POST"}) %>
//...
Expected:
It is just a list that can the user can page forward and back without updating the entire page.
Given this setup. I expect 2 links labeled "Prev" and "Next". Clicking on "Prev" should fire the PrevAction method in the controller as a post and the value in the hidden field named "startIndex" should be available in the request parameters. I expect similar results when clicking the Next link.
Actual:
The reality is that the request object contains NONE of the form parameters even though it shows that it came in as a POST.
In order to get any of the parameters using action link they must be explicitly supplied through the variation of ActionLink that includes parameters. When this is used the parameters become part of the URL of the link which defeats the purpose of having a POST.
So why is the javascript wrong?
I dug into the javascript code that is used to handle the submit for the example I posted with my question and I now better understand why it doesn't handle it. The reason appears to be related to the way they have wired up events and what I believe is a shortcoming in Internet Explorer.
The way it currently works is that the Ajax.BeginForm() helper class generates a form tag with an onsubmit() function to intercept the form submit event. When the user clicks on a submit button the onsubmit() function fires and recieves parameters, one of which is the event.
The MicrosoftMvcAjax scripts look at the event, bundle up the form properties that are supposed to be submitted and sends the request off to the server. The problem is that per WC3 standards only the successful controls are supposed to be posted. In the case of submit buttons this is the button that was actually clicked. Under internet explorer there is no way to determine which button actually caused the submit event to fire so the script just skips all submit buttons.
(In Firefox the event contains a property called "explictOriginalTarget" which points to the button that actually caused the event in the first place)
Whats the fix?
Microsoft should be fixing it. However if we need something sooner I believe the only option is to hack the MicrosoftMvcAjax scripts to wire up events differently. I have found that the form can be wired to a handle a mousedown event where the button clicked can be saved in a global variable where the onsubmit handler can insert it into the post parameters.
Here is some code that I was testing to illustrate this technique. I have confirmed it works in both IE8 and FireFox but I haven't tried to hack it into the MVC Ajax scripts yet... If I get more time. I may post the results here.
<script type="text/javascript">
var _clicked = "";
function onSubmit(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) //defeat Safari bug
targ = targ.parentNode;
alert("OnSubmit:" + _clicked + " was clicked.");
return false;
}
function Click(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) //defeat Safari bug
targ = targ.parentNode;
_clicked = targ.name;
return true;
}
<form action="/Home/StandardForm" method="post"
onsubmit="onSubmit(event)" onmousedown="Click(event)">
<input type="submit" name="StdPrev" value="StdPrev" />
<input type="submit" name="StdNext" value="StdNext" />
</form>
In order for your submit buttons to be "successfull" controls as per the specification, they must be defined within the form element:
http://www.w3.org/TR/html401/interact/forms.html#successful-controls
If you can't nest your submit buttons inside your form, you'll probably need to use javascript (or jquery) to submit your form and pass in an additional paramater to indicate which button was clicked.
I suppose this has been fixed in MVC 2 (or it was never broken). Just make sure your HTML markup validates. The following example should show it works.
Vote.aspx:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Vote</title>
</head>
<body>
<%using (Ajax.BeginForm("Vote", "Voting", new AjaxOptions { UpdateTargetId = "message" }))
{ %>
<%= Html.Hidden("itemId", "1")%>
<p>I love ASP.NET MVC!</p>
<input type="submit" name="voteValue" value="+" />
<input type="submit" name="voteValue" value="-" />
<%} %>
<p id="message"><%= TempData["message"] %></p>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjax.js")%>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.js")%>"></script>
</body>
</html>
VotingController.aspx:
using System.Web.Mvc;
namespace Examples.FormWithMultipleSubmitButtons.Controllers
{
public class VotingController : Controller
{
public ViewResult Vote()
{
return View();
}
[HttpPost]
public ActionResult Vote(int itemId, string voteValue)
{
switch(voteValue)
{
case "+":
TempData["message"] = "You voted up.";
break;
case "-":
TempData["message"] = "You voted down.";
break;
default:
TempData["message"] = "Your vote was not recognized.";
break;
}
if(Request.IsAjaxRequest())
{
return Content(TempData["message"].ToString());
}
else
{
return View();
}
}
}
}
I had the same issue today (Oct 8, 2010) with my form with multiple submit buttons. The HTML didn't validate. I cleaned it up. It's still doesn't validate (but less error than the original) and now the value of clicked button is submitted.
A possible workaround could be to have each button in a seperate form routed to different actions on your controller.
Not ideal but could work.
I did the following:
<input id="btnSubmit" name="btnSubmit" type="hidden" value="" />
<input type="submit" name="btnSubmit" value="Delete" id = "btnDelete" onclick="$('#btnSubmit').attr('value','Delete');"/>
<input type="submit" name="btnSubmit" value="Save New" id = "btnSaveNew" onclick="$('#btnSubmit').attr('value','Save New');"/>
<input type="submit" name="btnSubmit" value="Save" id = "btnSave" onclick="$('#btnSubmit').attr('value','Save');"/>
i.e. defined a hidden input type with id of "btnSubmit" and on each button added the onclick event as onclick="$('#btnSubmit').attr('value','Delete');". this seems to work
as I was able to get the value of the button clicked in the controller:
public ActionResult SaveCreateBlot(string btnSubmit)
{
}