I have an ASP.NET MVC3 app and with remote validation on one of my model classes. I discovered if I open the Edit view for the that model and the remote validation routine IS NOT called (due to not editing the field with remote validation on it) before submitting the form, the button clicked to POST the form IS NOT included in the request data sent to the Action method.
If the remote validation routine IS called before the form is POSTed - the button clicked to submit the form IS included in the POST.
I need to know which button was clicked when the Action is called on the server so I can determine if the user clicked UPDATE or CANCEL.
If I remove the remote validation from the model the form submits correctly every time.
Why would the button that was used to submit the form be excluded from the form post when remote validation is not called prior to the form submission.
thanks Michael
Here is some sample code:
@model Channel
<script src="@Url.Content("~/Scripts/jquery-1.6.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
<fieldset>
<legend>Edit Channel</legend>
@Html.HiddenFor(model => model.ChannelGUID)
<div class="editor-label">Name</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">Description</div>
<div class="editor-field">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">Channel Code</div>
<div class="editor-field">
@Html.EditorFor(model => model.Code)
@Html.ValidationMessageFor(model => model.Code)
</div>
<p>
<button type="submit" name="updateCommand" value="Update">Update</button>
<button type="submit" class="cancel">Cancel</button>
</p>
</fieldset>
}
here is the action
[HttpPost]
public ActionResult Edit(string updateCommand, Channel channel)
{
if (updateCommand != null)
{
//update clicked
}
else
{
//cancel clicked
}
here is the remote attribute on the model property Code
[Remote("IsChannelCodeUnique", "Channel", AdditionalFields = "ChannelGUID", ErrorMessage = "code must be unique")]
I encountered the same issue. I added remote validation to a form that had two submit inputs and the value of the submit button that was clicked, was not always posted any more.
While the other answers provide work-arounds, I delved it bit deeper and will answer the actual question you asked: "Why would the button that was used to submit the form be excluded from the form post when remote validation is not called prior to the form submission."
I knew that a Javascript Submit does not include the Submit Button Value. Therefore, I tried to post with javascript disabled. Validation didn't work, but the value of my submit was posted. I assumed that jquery.validate.js jumps in and sends a programmatic submit. This is indeed the case. This is what happens, using jquery.validate.js 1.9.0, uncompressed:
event.preventDefault();
, but this is only called in debug mode. Anyway, the stopRequest method will be called when a submit was clicked and after the remote validation was performed.$(this.currentForm).submit();
, which is a programmatic submit and will not post the value of the submit. This is why I cannot determine which submit button was clicked.Looking more carefully at the way the validation is extended, I found on line 59 the definition of a handler that seems to be designed to overcome some similar issue: It adds a hidden input with exactly the name and value of the submit button it handles. However, in my case neither validator.settings.submitHandler
nor validator.submitButton
are defined, so this code is never called.
It would have been nice if this hidden field were added in this case as well, since MVC will not know nor care what type of input posted the value and the post action on the controller could just use the value.
Addition My workaround for the issue is adding a handler to the click functions of the submits:
$('input[type="submit"]').click(function () {
var hidden = $("<input type='hidden'/>").attr("name", this.name).val(this.value).appendTo($(this).closest("form"));
});
The hidden field is created, so I do not have to rely on a hidden field with the correct name being present. You can either give your submits the same names, and test for the value, or give them different names and test for the presence of a post parameter. Of course, you would also need to use a form field name not already in use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With