I have an AJAX.BeginForm() form and I want to submit an Html post as the final post. Here's my form
#using (Ajax.BeginForm("createSet", "Workout",
new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "divs",
HttpMethod = "POST"}, new { id = "myForm" }))
{
<div id="divs">
#Html.Partial("WorkoutSet", Session["WorkoutSetList"])
</div>
#Html.ActionLink("Submit", "SavePlan", "Workout", new { type = "submit" });
//<input type="submit" value="Submit" id="submit" name="command" />
<input type="submit" value="Create Set" name="command" />
}
Basically my "create set" button is used a lot for ajax calls which is working fine. I'm able to bind the model rendered from the partial view and update my model to session on every ajax call.
For my final step, I want to submit the whole form to the SavePlan Action along with the model values and then redirect to home page after that.
Problems faced:
First I tried the Ajax Submit button(the code commented out), a script redirects it to the SavePlan along with the model values rendered from partialview. Only problem is I could not redirect to HomePage and I've read that redirection cannot be done on an ajax call.
Second, I've tried the #Html.ActionLink which does goes to the SavePlan action and then proceeds to redirect to HomePage, BUT the model values were never passed. I've tried FormCollection but the values don't get passed either.
Please provide some advise on how to solve this? I've already spent 2 days on it and I'm tearing myself on it.
To recap:
Trying the Ajax way allows me to pass the model values but does not redirect to home page
Trying the Html way doesn't allow me to pass the model values but does redirect to home page.
You can redirect from an ajax POST - in your controller, you need to return a window.location javascript snippet:
return JavaScript(string.format("window.location = '{0}'", Url.Action("Index")));
There is an article here: Breaking out of an AJAX POST
Related
I am new to mvc i am trying to pass model into controller from view
This is my view
My Control
but while debugging im getting all null values
i am using view model
where i am doing mistake
Help me
thanks
You cannot use an ActionLink to post a form. Have a look at this post
#model YourViewModel
#using(Html.BeginForm())
{
Model NAme : #Html.TextBoxFor(s=>s.Name)
<input type="submit" value="Post to server" />
}
You seem to use an "ActionLink" to call the "AddUser2" method controller. An ActionLink generates a basic link which redirects to the controller passed in parameter.
You need to post the form (to send values typed by the user to the controller), not redirect.
To post the form, use the following html tag (instead of the ActionLink) :
<input type="submit" value="ok" />
This code generate a button, which will send your form when user will click on it.
I have an MVC site. I have a form submit (it submits no data in this case) that triggers an Action in the Controller and returns a View. If I refresh, it asks to resubmit the form and works. If I click on the URL in the "awesome bar" or whatever, and hit Enter, I get a 404 resource cannot be found error.
The URL displayed is /pts/reports/subject. I don't get what's happening. Any suggestions?
Action in Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Subject()
{
return View(new SubjectModel());
}
Form:
<% using (Html.BeginForm("Subject", "Reports", FormMethod.Post, new {#class = "form-a"}))
{ %>
<fieldset>
<h5 class="section-header">Subject</h5>
<div class="positionbottom">
<button type="submit" name="Submit" value="csv" class="right">Web</button>
</div>
</fieldset>
<% } %>
MapRoute:
context.MapRoute(
"Pts_Reports",
"pts/reports/{action}/{id}",
new { controller = "Reports", action = "Index", id = UrlParameter.Optional }
);
The action expects a POST:
[AcceptVerbs(HttpVerbs.Post)]
If you submit a form with a POST method (which you are... FormMethod.Post), then it will work as expected. Which you've observed. However, just clicking a link or manually entering the address is a GET request, not a POST request. So there's no matching action. Thus, a 404 error.
In order you accept any request, just remove that AcceptVerbs usage. But keep in mind that GET requests won't contain form data. The action you show in the code doesn't use any form data, so that's fine. (But then why are you posting a form to it?)
I used the following code in one of my controller;
if (Request.IsAjaxRequest()) {
return RedirectToAction("PreviewAndSendEmail");
}
I debugged it and it comes to return line and but redirect didn't occur. Is it possible to do that inside Ajax.BeginForm ? Here is the razor code;
using(Ajax.BeginForm( new AjaxOptions { LoadingElementId = "loading" })) {
<b>Choose E-mail Template : </b>#Html.DropDownList("emailtemps")<br /><br />
<input type="submit" value="Preview & Send" />
<span id="loading" style="display: none;">
<img title="loading..." alt="load" src="#Url.Content("~/Content/App_Icons/gifs/loading.gif")"
</span>
}
You can't redirect in an AJAX action from the server. If you want your browser to redirect in an AJAX action you need to do it from javascript. Obviously using AJAX to redirect is absolutely useless. If you intend to redirect use a normal Html.Begin form and don't bother with AJAX.
Why don't you call the PreviewAndSendMailEmail directly? Since you don't need the redirection itself (change in url,etc), there is no need to use it.
I want to use jQuery ($.post) to submit my html form, but I want to use the client side validation feature of MVC 2. Currently I hook up the post function to the "OnSubmit" event of the form tag, but I can't hook into the validation, ideally I want to be able to do
if (formIsValid) {
$.post('<%=Url.Action("{some action}")%>'...
}
Please note, Client side validation is working with jQuery.validation, I just can't get it to test if the validation was successful or not before I post my data.
Andrew
The final solution
<%
Html.EnableClientValidation();
using (Html.BeginForm("Register", "Account", FormMethod.Post, new { id = "registrationForm" })) {
%>
...
<button type="submit" onclick="return submitRegistration();">Register</button>
<%
}
%>
<script type="text/javascript">
function submitRegistration() {
if ($("#registrationForm").valid()) {
$.post('<%=Url.Action("{some action}")'...
}
// this is required to prevent the form from submitting
return false;
}
</script>
You can initiate jQuery validation on the button click event. Place the following inside your button-click event-handler:
if ($('form').valid())
//take appropriate action for a valid form. e.g:
$('form').post('<%=Url.Action("{some action}")%>')
else
//take appropriate action for an invalid form
See the Validation plugin documentation for more information.
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)
{
}