How add custom validation to my razor page? - asp.net-mvc

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

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.

MVC Validation model attributes: Client side validation not occurring, only server side

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

Why validation is not working with Html.TextBoxFor but is when using Html.EditorFor?

I am trying MVC's datatype attributes, and just created a simple scenario like the following:
The View:
#model MVC4.Models.Model
#{
ViewBag.Title = "DataTypeAttribute";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<h2>DataTypeAttribute</h2>
#using (Html.BeginForm("SubmitData", "Home"))
{
<div>
#Html.ValidationSummary()
</div>
#Html.EditorFor(m => m.Email)
<br />
<br />
#Html.EditorFor(m => m.PostalCode)
<br />
<br />
#Html.EditorFor(m => m.TextOnly)
<br />
<br />
<button type="submit">Submit</button>
}
The Model:
public class Model
{
[DataType(DataType.EmailAddress)]
[Required]
//[EmailAddress]
public string Email { get; set; }
[DataType(DataType.PostalCode)]
public string PostalCode { get; set; }
public string TextOnly { get; set; }
}
"SubmitData" is just a controller that, returns View(..., model) if ModelState.IsValid is false.
Although posts like this do a good job in tackling the differences between Html.TextBoxFor and Html.EditorFor, I could not find an answer as to why validation for the datatype EmailAddress will not work when using TextBoxFor. I did find people mentioning TextBoxFor does not take metadata into account, while EditorFor does.
But does this make sense ? So TextBoxFor does not offer support for client validations ?!
I wonder what is the reason for the difference between the two ?
TextBoxFor() does work with validations.
[DataType(DataType.EmailAddress)] is not a validation attribute. Its an attribute that determines the type of input to display by setting the type attribute in the rendered html. For example <input type="text" ..>, <input type="date" ..>, <input type="email" ..> in order to render the browsers implementation of a HTML4 datepicker, email input etc.. It works only for EditorFor() because TextBoxFor() as its name suggest generates and input with type="text"
If you want validation for an email address, then you use the [EmailAddress] attribute on your property.
[Required]
[EmailAddress]
public string Email { get; set; }
Edit (further to the comments)
One of the features of HTML5 is the ability to validate user data without relying on scripts. One such form of browser validation is using the type attribute. The use of [DataType(DataType.EmailAddress)] on a property that is rendered with #Html.EditorFor() adds type="email" to the input element. From the MDN documentation
email: The element represents one email address. Line breaks are automatically stripped from the input value. An invalid email address can be set, but the input field will only satisfy its constraints if the email address satisfies the ABNF production 1*( atext / "." ) "#" ldh-str 1*( "." ldh-str ) where atext is defined in RFC 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section 3.5.
If your are currently seeing a validation error message associated with the property, and you have not added the [EmailAddress] attribute, then it means that jquery.validate.js is not loaded and you are seeing the browsers error message associated with type="email".
When jquery.validate.js is loaded (correctly), the novalidate="novalidate" attribute is added to the form element, which specifies that form is not to be validated (using the HTML5 validation) when submitted. The relevant code from jquery.validate.js is (approx line 35)
// Add novalidate tag if HTML5.
this.attr('novalidate', 'novalidate');
This is added to prevent possible confusion between error messages displayed by browser validation and jquery unobtrusive validation.
As to why DataTypeAttribute attribute inherits ValidationAttribute when it does not actually do validation, from Brad Wilson himself in this answer
The reason it derives from ValidationAttribute is so that you could create a new custom data type class, which was both a DataType and a Validation, all wrapped up into one. It's an unfortunate side-effect of .NET not allowing multiple inheritance.

Email validation not working in MVC

In my MVC application, email validation is working perfectly locally but when I m publishing and deploying to server It won't work. I have compared the html source of both local and deployed files and there is no difference. My Razor view mark up is
<li>
<p><strong>Email: </strong>#Model.CurrentEmailAddress <span class="deliverychange" onclick="showHidden('emailchange');">(Change email)</span></p>
<div id="emailchange" class="fullborder" style="display: none;">
<div class="orderrow newemailaddress">
#Html.LabelFor(m => m.UpdatedEmailAddress)
#Html.TextBoxFor(m => m.UpdatedEmailAddress, new { #onkeypress = "showEmailChangeConfirmation();" })
#Html.ValidationMessageFor(m => m.UpdatedEmailAddress)
</div>
<div id="updatedemailkeypress" style="display: none;">
<div class="orderrow checkboxrow emailchangeconfirm">
#Html.LabelFor(m => m.UpdateEmailAddress)
#Html.EnumRadioButtonFor(m => m.UpdateEmailAddress, false)
</div>
</div>
<div class="clear"> </div>
</div>
</li>
and my model is as
[DataType(DataType.EmailAddress)]
[RegularExpression(#"^([\w.-]+)#([\w-]+)((.(\w){2,3})+)$", ErrorMessage = "Email is not valid")]
[Display(Name = "Enter new email address: ")]
public string UpdatedEmailAddress { get; set; }
[Display(Name = "We will use ****")]
public YesNo UpdateEmailAddress { get; set; }
Use the EmailAddress-attribute instead
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.emailaddressattribute%28v=vs.110%29.aspx
Please recheck that form tag is there.
Form validation works actually by validating form valid method.
So, the form is required to be exist.
Hope this helps.
After spending a lot of time on this I found the publish wizard is not copying the jquery.validate-vsdoc.js to the scripts folder. I manually copied this to the server and all started working.
Try to use dataannotationsextensions library, you can download from nuget.
and just add Email attribute to your model like this
using DataAnnotationsExtensions;
[Required]
[DataType(DataType.EmailAddress)]
[Email]
public string UpdatedEmailAddress { get; set; }

ASP.NET/MVC3 - How do I perform validation on checkboxes and array?

I have this field in my model.
class AddUserModel
{
// ....other fields
[Required(ErrorMessage = "Please select at least one role.")]
public string[] Roles { get; set; }
}
In the view this is being rendered as a list of checkboxes:
<div class="editor-field">
#Html.ValidationMessageFor(model => model.Roles)
<ul class="list_roles">
#foreach (string role in ViewBag.PossibleRoles)
{
<li><input type="checkbox" name="Roles" value="#role" />#role</li>
}
</ul>
</div>
How do I get the validation error message to fire if none of the checkboxes are clicked? Will I need to write a custom validator?
I suspect you'll have to write a custom validator (which isn't hard, BTW; the biggest challenge would be to include client-side error checking, but even that's not that hard).
Another option might be to try using a listbox instead. In Html those have multiple selection capability. The listbox validator might let you require at least one value (I don't know for sure, as I haven't had reason to use a validated listbox in my MVC app yet).

Resources