ASP.NET MVC, Cancel triggering Client Validation, Why? - asp.net-mvc

I am using MVC3, C#, Razor, .NET 4.5
I have a required field value.
#Html.ValidationMessageFor(model => model.Name)
rendered as :
<input data-val="true" data-val-required="* Required" id="Name" name="Name" style="width:440px" type="text" value="" />
Unfortunately it being triggered by the Cancel button, although buttons defined as:
<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())
{
#Html.ValidationSummary(true)
#Html.TextBoxFor(model => model.Name, new {#style="width:440px" })
#Html.ValidationMessageFor(model => model.Name)
<p class="form-buttons">
<button type="submit" name="btn" value="Save">Save</button>
<button type="submit" name="btn" value="Cancel">Cancel</button>
</p>
}
Also it seems to be triggered pre Post Action, so must be via Javascript.
I do not mind JS triggering the validation, but I do need to ensure that the Cancel button just closes the page and returns to another page as handled by the post action if btn != Save.
So how do I stop this Cancel validation please?

Related

Html.ValidationMessageFor not displaying at all

I have the following form:
<form action="~/buy-online" method="get" class="buy-online-form clearfix" autocomplete="off" id="buy-online-search">
<div class="infield-holder clearfix">
#Html.LabelFor(m => m.CustomerPostcode, new { #class = "infield" })
#Html.TextBoxFor(m => m.CustomerPostcode, new { #class = "textbox" })
<input type="submit" value="Buy Online" id="find-retailer-button" class="button" />
</div>
</form>
#Html.ValidationMessageFor(m => m.CustomerPostcode)
Which works fine and will display an error message when submitted without jQuery, but when I add the jQuery validate scripts (v 1.11.1):
<script src="/scripts/jquery.validate.js"></script>
<script src="/scripts/jquery.validate.unobtrusive.js"></script>
It stops the form submitting but doesn't display the error message
My property is marked like so:
[DisplayName("Enter your full postcode")]
[Required(ErrorMessage = "Please enter your full postcode")]
public string CustomerPostcode { get; set; }
And the html renders like this:
<input class="textbox" data-val="true" data-val-required="Please enter your full postcode" id="CustomerPostcode" name="CustomerPostcode" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="CustomerPostcode" data-valmsg-replace="true"></span>
If I inspect the input when I hit submit it is adding the class input-validation-error to the textbox but just not updating the validation message.
All the posts that I have checked on this problem just say to include the scripts so I'm at a loss as to why the message is not showing.
I've even tried adding the jquery.unobtrusive-ajax.js script but that didn't seem to do anything either. Any help would be appreciated, thanks.
You need to include the #Html.ValidationMessageFor(m => m.CustomerPostcode) within the form tags for jquery.validate.unobtrusive to work.

umbraco mvc form model validation markup not showing

Running Umbraco 6.05, I have a custom model class with Data Annotations like:
[Required, StringLength(100), DataType(DataType.EmailAddress), DataType(DataType.MultilineText)]
and I pass the model to the view like so:
#inherits Umbraco.Web.Mvc.UmbracoViewPage<test.local.Models.ContactForm>
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>ContactForm</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
...
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
But when it renders, the "data-val" attributes are missing, though interestingly the DataType EmailAddress/MultiLine work fine by inserting 'type="email"' and creating a 'textarea' appropriately.
Any ideas what I might be doing wrong?
Cheers
Answer found here:
http://our.umbraco.org/forum/developers/extending-umbraco/36898-Enable-unobtrusive-validation-for-mvc-forms
Turn on client side validation in your web.config

Multiple Submit buttons in Form neither appearing in FormCollection of ASP.Net MVC Method

I'm at my wits end here...I have the following razor markup for my form:
<input class="k-button" type="submit" value="Post" name="SubmitButton" />
<input class="k-button" type="submit" value="Save" name="SubmitButton" />
The problem I'm experiencing is that the FormCollection parameter of the controller action method does not include SubmitButton in its Key/Value pairs.
I've come across this post here that seems to have had the same problem. The solution seemed to be to use a ActionMethodSelectorAttribute AND to remove the use of [Remote] validation. But I really need my [Remote] validator though, so it is not an option for me to remove that. Is there no other solution, or is this some bug I just have to deal with?
I'm thinking along the lines of having to replace my use of two buttons with a single Save button, and then add a "Post" checkbox. Then in the controller action I check for the presence of the Post KeyValue pair. But this is less than idea. I prefer the use of two buttons.
EDIT: more view markup following Igor's request:
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
<fieldset>
<legend>Edit details for Client Warehouse Request </legend>
#Html.HiddenFor(model => model.ModelObject.CustomerCode)
#Html.HiddenFor(model => model.ModelObject.ReqNr)
<div style="table-layout: initial;">
<div class="columnDivider">
<div class="editor-label">
#Html.LabelFor(model => model.ModelObject.ReqNr)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.ModelObject.ReqNr)
</div>
<div class="clear">
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModelObject.CreationDate)
</div>
... many other fields following the above structure...
<input class="k-button" type="submit" value="Post" name="SubmitButton" />
<input class="k-button" type="submit" value="Save" name="SubmitButton" />
</div>
<div class="columnDivider">
...some more fields
</div>
<div>
Here I have a Kendo UI datagrid that gets submitted with the form
</div>
</fieldset>
}
Try:
<input type="hidden" name="SubmitButtonValue" id="SubmitButtonValue" />
<input class="k-button" type="submit" value="Post" name="SubmitButton" />
<input class="k-button" type="submit" value="Save" name="SubmitButton" />
<script type="text/javascript">
$(document).ready(function(){
$(".k-button").click(function(){
$("#SubmitButtonValue").val($(this).val());
});
});
</script>
and check for "SubmitButtonValue" key in FormCollection.

In this ASP.NET MVC 3 app, what am I missing to get unobtrusive client-side validation?

I need help figuring out how to succeed in implementing unobtrusive client-side validation of a field in my ASP.NET MVC 3 app. I can see that unobtrusive client-side validation is basically enabled, since MVC generates related HTML.
What I want to achieve in this case is to have validation of input to the Bugs editor (i.e., the corresponding <input> element) as I type, for testing purposes I've set the property's max length to 2. When I test, I can tell that validation does not currently take place, so something is at least missing. So, the success criteria for this question is working client-side validation of the Bugs form field.
I can see one possible problem in the generated HTML: The Verbose property is not marked as Required in the model, but its corresponding <input> still gets the dataval=true attribute for instance, whereas the <input> for Bugs does not. Shouldn't it be the other way around, as fields with validation rules should get dataval=true, to enable unobtrusive validation?
The code that should be relevant to understanding the case follows, please let me know if more info is required:
Options.cs:
public class Options
{
[Required, StringLength(2)]
public string Bugs;
public bool Verbose;
}
Options.cshtml:
<script src="#Url.Content("~/Scripts/jquery-1.6.2.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>
<div id="options-form">
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Options</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Bugs)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Bugs)
#Html.ValidationMessageFor(model => model.Bugs)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Verbose)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.Verbose)
#Html.ValidationMessageFor(model => model.Verbose)
</div>
</fieldset>
}
</div>
The two editors (for Bugs and Verbose) are rendered as follows:
<div id="options-form">
<form action="/Options" method="post">
<fieldset>
<legend>Options</legend>
<div class="editor-label">
<label for="Bugs">Bugs</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Bugs" name="Bugs" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Bugs" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Verbose">Verbose</label>
</div>
<div class="editor-field">
<input data-val="true" data-val-required="The Boolean field is required." id="Verbose" name="Verbose" type="checkbox" value="true" /><input name="Verbose" type="hidden" value="false" />
<span class="field-validation-valid" data-valmsg-for="Verbose" data-valmsg-replace="true"></span>
</div>
</fieldset>
</form>
</div>
Bugs and Verbose are public fields in this code, not properties. Make them properties and that should fix it.
Define get; and set; for both Bugs and Verbose properties. That will not just correct(add) validation, but in the future, model binder will be able to bind models back from form fields on server.
And regarding required attribute for Verbose. That is because of implicit required validation for value types taking place. string is nullable, so it is not required if you do not set Required attribute on it explicitely - so Bugs stays without required. But bool cannot be null by nature of c#, so mvc automatically adds Required attribute to it. You can control that with
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
I experienced the same problem recently (unobtrusive client-side validation didn't work in IE but worked in the other browsers though). The reason was in jQuery version. I rolled back from jQuery 1.6.x version to the version 1.5.2 an it started to work.

Why doesn't ASP.NET MVC 3 enable client-side validation in this case?

I'm trying to integrate unobtrusive client-side validation in my ASP.NET MVC 3 project, as per Brad Wilson's recipe. However, it does not get enabled in the rendered view. For example, my <input> elements (i.e., editor fields) do not receive a data-val attribute as prescribed.
I have done the following to enable unobtrusive client-side validation:
Web.config:
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
</configuration>
Options.cs:
public class Options
{
// Annotate with validation rules, in order to generate client-side validation code
[Required, StringLength(60)]
public string Bugs = "";
}
_Layout.cshtml:
<head>
<script src="#Url.Content("~/Scripts/jquery-1.6.2.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>
</head>
Options.cshtml:
#model MyProject.Models.Options
<div id="options-form">
#Html.ValidationSummary(true)
<fieldset>
<legend>Options</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Bugs)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Bugs)
#Html.ValidationMessageFor(model => model.Bugs)
</div>
</fieldset>
</div>
This HTML gets generated for the editor field:
<div class="editor-label">
<label for="Bugs">Bugs</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Bugs" name="Bugs" type="text" value="" />
As you can see, no data-val attribute :(
You forgot to use form. Surround your fieldset with Html.BeginForm
<div id="options-form">
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Options</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Bugs)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Bugs)
#Html.ValidationMessageFor(model => model.Bugs)
</div>
</fieldset>
}
</div>
This will initialize FormContext and your inputs will receive data-val-* validation attributes

Resources