MVC Validation model attributes: Client side validation not occurring, only server side - asp.net-mvc

I have jQuery.Validation 1.15.0 installed in an ASP.NET MVC 5.2 project and I am trying to learn the basics of MVC and, at the moment, validating model data.
I was under the impression that the Validation Attributes that I add would generate client side validations and that a post back would not occur until all client validations were passed. However, though the validations are generally working, a post back occurs every time, even when, for example, a value for VendorId is not provided.
public class StateAssessmentViewModel
{
[Required(ErrorMessage = "Vendor ID is required")]
[MaxLength(4, ErrorMessage="{0} can not be longer than {1} characters." )]
[Display(Name = "Vendor ID")]
public int VendorId { get; set; }
[Display(Name = "Effective Date")]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime EffectiveDate { get; set; }
}
This site confirms that the validations should be first performed on the client if Javascript were enabled in the browser, Chrome v49, and it is. In fact, the "Effective Date" field has a working jQuery calendar on it, so Javascript is definitely enabled.
What can I look for to help me identify why the validations are not being performed at all on the client?
Here is the produced html when I view source:
<div class="form-group">
<label class="control-label col-md-2" for="VendorId">Vendor ID</label>
<div class="col-md-10">
<input class="input-validation-error form-control text-box single-line" data-val="true" data-val-maxlength="Vendor ID can not be longer than 4 characters." data-val-maxlength-max="4" data-val-number="The field Vendor ID must be a number." data-val-required="Vendor ID is required" id="VendorId" max="4" min="0" name="VendorId" type="number" value="3333a" />
<span class="field-validation-error text-danger" data-valmsg-for="VendorId" data-valmsg-replace="true">The value '3333a' is not valid for Vendor ID.</span>
</div>
</div>
I'm using Bootstrap, too, and trying to filter out non numeric keystrokes for the VendorId field, but this has no effect. I also tried playing around setting max and min lengths.
I also was expecting the DisplayFormat attribute on the EffectiveDate model property to have some client side effect. It did not. Here's the generated HTML from doing a the "View Source"
<div class="form-group">
<label class="control-label col-md-2" for="EffectiveDate">Effective Date</label>
<div class="col-md-10">
<input class="input-validation-error form-control text-box single-line" data-val="true" data-val-date="The field Effective Date must be a date." data-val-required="The Effective Date field is required." id="txtEffectiveDate" name="EffectiveDate" type="datetime" value="" />
<span class="field-validation-error text-danger" data-valmsg-for="EffectiveDate" data-valmsg-replace="true">The Effective Date field is required.</span>
</div>
</div>
Why is client side validation not occurring?

Are you including the jquery validation library in your BungleConfig.cs class ? If so, are you including that script bundle in your layout file? It should be working given the HTML that it's producing

Related

Default values and validation in ASP RazorPage

My PageModel has a single BindProperty like ?Query=, whose length should not exceed 1000. However, I also want this string to always be defined; on initial page load (or if a blank form is submitted), I want to use the default value "*" instead of null or "":
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
namespace RazorTestApp.Pages;
public class IndexModel : PageModel
{
[BindProperty(SupportsGet = true)]
[StringLength(1000)]
[Required(AllowEmptyStrings = false)]
public string Query { get; set; } = "*";
public void OnGet()
{
}
}
I have an equally simple View:
#page
#model IndexModel
<div class="text-center">
<form method="get">
#Html.EditorForModel()
<div>
<input type="submit" />
</div>
</form>
</div>
I am having 2 issues with this:
Load page with no query string (initial load): the input box correctly displays "*", but I also get a validation error "The Query field is required".
Load page with ?Query= (submit with empty query): the input box does not show the default "*" (shows empty string), and I get the same validation error "The Query field is required".
I am obviously not doing this correctly. How can I set a default value for Query to be used whenever it is empty/not provided, and have it play nicely with validation?
I tried to test the validations on my side.
Below is my model:
[BindProperty(SupportsGet = true), Required, StringLength(1000)]
public string Rating { get; set; } = "*";
View:
<div class="form-group">
<label asp-for="Movie.Rating" class="control-label"></label>
<input asp-for="Movie.Rating" class="form-control" />
<span asp-validation-for="Movie.Rating" class="text-danger"></span>
</div>
Output:
On my side, I could see that * is added to the input field and if I remove it and submit the form then I get the validation message.
For testing purposes, I would suggest you make a test with the <form method="post">. If the issue persists then creating a new model and view and trying to test it separately may help to narrow down the issue.

How can I remove the "type" attribute from Html.EditorFor?

In my View, I have a Html.EditorFor line:
#Html.EditorFor(model => model.DateCreditEarned,
new { htmlAttributes = new { #class = "form-control" } })
When I look at the rendered HTML, I see that the input has a "type = date" attribute. Is there any way I can use EditorFor and remove the type attribute? This way I can have the desired functionality without causing Edge problems.
<input
class="form-control datecontrol"
data-val="true"
data-val-date="The field Date Credit Earned must be a date."
data-val-required="The Date Credit Earned field is required."
id="DateCreditEarned"
name="DateCreditEarned"
type="date" value="6/27/2016">
Update
I discovered that I can use Html.TextboxFor without having any Edge problems (i.e., Edge overriding my Bootstrap datepicker with its own). But I was hoping I could get the same thing done with EditorFor.
Well, making my comment an answer, in ASP.NET MVC You typically do things declaratively in models. In this case a text field was wanted so making the model property like this:
[DataType(DataType.Text)]
public DateTime DateCreditEarned { get; set; }
solved the problem.

How to use HTML5 native validation rules for text input fields in ASP.NET-MVC 5.2?

In HTML5 we can create input fields with custom validation error statements.
For instance:
<input type="text" name="username"
id="username" pattern="[a-zA-Z ]{5,}"
maxlength="30" required />
<div class="validation-messages">
<span data-rule="valueMissing" //FIRST RULE
class="hide">The username is required. </span>
<span data-rule="patternMismatch" //SECOND RULE
class="hide">ust be a series of alpha characters only (min 5, max 30).
</span>
</div>
If user breaks any data rule he gets notification which depends on the broken rule and I look for a way to use them in ASP.NET-MVC.
All HTML5 native errors are:valueMissing, typeMismatch, patternMismatch, tooLong, rangeUnderflow, stepMismatch, value.
In ASP.NET-MVC the Html.EditorFor() method is vastly used. For instance:
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
It generates input fields.
Where and how should I define those native validation errors prompts(for instance patternMismatch seen above)? Should I do it in the EditorFor method or there is a way to define them in the model class?
If you want to validate an input against its type, use EditorFor in the view as you have but then in your model decorate the fields with the DataType attribute like so:
public class ModelTest
{
[DataType(DataType.EmailAddress)]
public string Email {get;set;}
}
You can then go a step futher and use additional parameters to specify various elements of error detailing such as an error message.
[DataType(DataType.EmailAddress,ErrorMessage = "Email is required")]
If you need it to be required use the following attribute
[Required]
If you need to check string length you can use the following attributes as necessary
[StringLength()]
[MinLength()]
[MaxLength()]
For number based validation perhaps try
[Range()]
More often then not, when you are unsure or want to see if some validation exists, just use the Intellisense to browse through possible DataAnnotations
Additional Reading
http://www.asp.net/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-6
https://msdn.microsoft.com/en-us/library/dd901590(VS.95).aspx

data-val-date attribute added to dateTimePicker even without ValidationAttribute in model

I emit a datetimepicker with this line
#Html.EditorFor(model => model.Event.EventStart)
My editor template is like this:
#model DateTime?
#Html.TextBox("", string.Format("{0:yyyy-MM-dd HH:mm}",
Model.HasValue ? Model : null), new { #class = "dateTimePicker" })
and that will result in the following html:
<input type="text" value="2013-10-26 00:00" name="Event.EventStart"
id="Event_EventStart" data-val-required="The Startdatum field is required."
data-val-date="The field Startdatum must be a date." data-val="true"
class="dateTimePicker hasDatepicker input-validation-error">
That is also the case if I do not have a #Html.ValidationMessageFor(model => model.Event.EventStart) line.
There is nothing in my code that should enable validation for the property EventStart.
In my model it only looks like this:
[Display(Name = "Startdatum")]
public DateTime EventStart { get; set; }
It seems like jquery ui (most suspect) is adding validation for dates to my dateTimePicker.
Why?
Or is the presence of the data-val-date attribute also triggering datetime validation?
The validation fails:
The field Startdatum must be a date.
It would be nice to either be able to disable the validation or add validation for datetimes instead of dates.
Is there some way to actually have the responsibility to add validation myself with data annotations as I do usually (with other datatypes)?

How add custom validation to my razor page?

I have razor page in my mvc 4 application .Now imagine i have a simple textbox in my page as follows :
#Html.TextBox("Email")
or
<input id="Email" name="Email" type="text" />
how can I do some client-side validation for this field you know something like asp.net web forms validation controls . I want to make it required and write a Regex for it .
I use to do this:
In the model Person.cs :
[StringLength(50, ErrorMessage = "El campo {0} no puede tener mas de 50 caracteres")]
[Required(ErrorMessage = "El nombre es obligatorio")]
public string Nombre { get; set; }
In the page Create.cshtml:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Person.Nombre" class="control-label">Nombre / Name:</label>
<input asp-for="Person.Nombre" class="form-control" />
<span asp-validation-for="Person.Nombre" class="text-danger"></span>
</div>
You generally decorate your model properties with the RequiredAttribute and the RegexAttribute.
You may want to look at Data Annotations. They provide very simple and straightforward way for you to define your (not only) validation for every field in every view model.
Please take a look at the following link:
How to: Validate Model Data Using DataAnnotations Attributes
In your particular case, it will be
[Required]
[RegularExpression(#"<your RegEx>", ErrorMessage = "<your message, leave out for default>")]
public string fieldYouValidating { get; set; }
Other way for validation preferrable by many is Fluent Validation
RuleFor(x => x.fieldYouValidating)
.NotEmpty()
.WithMessage("This is the message.");
Hope this helps

Resources