Auto Tooltip Validation in MVC 4? - c#

Where the heck are these things coming from? I like them, and I would like to leverage them elsewhere in my site. It appears they only show when I do regular expression validation in model:
[Display(Name = "Residential")]
[RegularExpression(#"[-+]?[0-9]*\.?[0-9]?[0-9]", ErrorMessage = "Must be a number")]
public Byte? residentialExperience { get; set; }
<div class="editor-label row">
#Html.LabelFor(model => model.residentialExperience)
</div>
<div class="editor-field row">
#Html.EditorFor(model => model.residentialExperience)
#Html.ValidationMessageFor(model => model.residentialExperience)
</div>
How can I use these validation tooltips elsewhere? Also, how can I turn them off?
Also: It's not displaying the same message as I have in my model. It says, "Please enter a number" whereas I have written "Must be a number."

This is because you are outputting a numeric field. If you look at your HTML you will see that you have something like this:
<input type="number" ... />
By defining the type as a numbber, the browser knows what to expect and it will give you a generic message. This is part of Html 5 spec.
If you want to override the default behavior you could do this:
#Html.TextBoxFor(model => model.residentialExperience, new { #type = "text" })

Related

MVC Model validation on lose focus

Is it possible to change when client side validation happens when using MVC data annotations? Currently, all validation seems to occure on keyup, but I need it to occure onchange or losefocus.
ViewModel:
[Display(Name = "First Name")]
[Required(ErrorMessage = "First Name is Required")]
public string FirstName { get; set; }
cshtml
#Html.TextBoxFor(m => m.FirstName, new { placeholder = Html.DisplayNameFor(n => n.FirstName) })
#Html.ValidationMessageFor(m => m.FirstName)
Rendered HTML
<div class="field">
<input data-val="true"
data-val-required="First Name is Required"
id="FirstName"
name="FirstName"
placeholder="First Name"
type="text"
value="">
<span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
</div>
This works as it should, but when I type into input, validation occurs as I type. How can I make validation occure after I've clicked or tabbed off the input?
Versions
.NET 4.6.1
Microsoft.Aspnet.Mvc 5.2.3
Microsoft.jQuery.Unobtrusive.Validation 3.2.3
I was able to use Javascript to get the desired behavior.
$.validator.setDefaults({
onkeyup: false
})
All validation now happens on blur

How to validate email in c#

I am trying to validate email field. And I have a regular expression for email
/^[a-z0-9._%+-]+##[a-z0-9.-]+.[a-z]{2,4}$/
In visual studio my code
Email:<br>
<input type="text" ng-model="Email" id="txtEmail" ng-pattern="/^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$/" name="Email" placeholder="Email" required>
<span ng-show="myForm.Email.$error.pattern">Please enter valid Email!</span>
<span ng-show="myForm.Email.$error.required">*</span><br>
An error occuring
Email validation is a popular problem and each regex pattern that you will find doesn't cover all the cases. The best way is to try to send any message to this email or you can use System.Net.Mail.MailAddress class
try
{
var email = new System.Net.Mail.MailAddress(value);
}
catch (FormatException)
{
//handle it here
}
You say you are using C# and MVC. You can use the built in validation; the email validation is supported via an attribute on the field in the model class:
[EmailAddress(ErrorMessage = "The email address is not valid")]
public string Email { get; set; }
The attributes are in the namespace System.ComponentModel.DataAnnotations
The Razor view then needs something like:
<div class="control-group">
#Html.ValidationMessageFor(m => m.Email)
#Html.LabelFor(m => m.Email, new { #class = "editor-label control-label" })
<div class="editor-field controls">
#Html.MbrraceTextBoxFor(m => m.Email, new { #class = "input-xlarge" })
</div>
</div>
There are many variants on the cshtml display styles.
You can create a variable for pattern.
#{
var pattern = "/^[a-z0-9._%+-]+##[a-z0-9.-]+.[a-z]{2,4}$/";
}
<input type="text" ng-model="Email" id="txtEmail" ng-pattern="#pattern" name="Email" placeholder="Email" required>

MVC Unobtrusive validation data-val-* markup attributes not being generated

Edit: It seems as though no attributes work whatsoever, validation or not. For example, [DataType(DataType.Date)] doesn't change the markup in anyway either, while it should add 'type=date' to the element, the [Authorize] attribute lets even unauthorized users through etc. Anywone have any ideas about what could be the problem?
Edit 2: Added the following while trying to figure out what's wrong:
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(m => m.Name, Html.ViewData);
var val = metadata.GetValidators(new ControllerContext());
var attributes = metadata.ContainerType.GetProperties().Where(x => x.Name == "Name").FirstOrDefault().CustomAttributes;
The 'val' variable doesn't return any validators, while in a new project the same line works correctly and returns an IEnumerable of all the attributes the model property has. The 'attributes' variable, though, does find all the attributes the property has. So where do I go from here and find out what's wrong?
Edit 3: So I compared what the property 'ModelValidatorProviders.Providers' returns in Global.asax's 'Application_Start()' method between my project and a new project and it turns out that for some reason for my project it doesn't have a 'DataAnnotationsModelValidatorProvider'. So I did this at 'Application_Start()':
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
And now the validation works (except the [Authorize] attribute and others not related to models, it looks like they still dont work)! Not much of a fix, though, is it. Why isn't the provider in the ModelValidatorProviders property in the first place? Could it have anything to do with the fact that I have Autofac installed and maybe that messes with it somehow?
Edit 4: Fixed it, see answer.
Original post:
I'm pulling my hair out at this point, because I've read multiple articles about this and none of them help. The weird part is that the validation worked before and then it suddenly stopped working (I didn't change anything). I even restarted my PC, but that didn't really help.
Yes, both ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are set to true in web.config
The required validation JavaScript files work fine too - they are imported correctly and load fine, but the problem doesn't even reach those, because the serverside isn't even generating the required HTML markup.
My ViewModel looks like this (the validation doesn't work anywhere on the site, so I could give you literally any viewmodel):
public class ChangePasswordViewModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Current password")]
public string OldPassword { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
And here's the view (pretty much the default MVC view as well, so there's nothing wrong with it):
#model AwenterWeb.Models.ChangePasswordViewModel
#{
ViewBag.Title = "Change Password";
}
<h2>#ViewBag.Title.</h2>
#using (Html.BeginForm("ChangePassword", "Manage", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Change Password Form</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.OldPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.OldPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.NewPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.NewPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Change password" class="btn btn-default" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I put a breakpoint on Html.TextBoxFor and made sure that indeed the HTML that it returns does not have the necessary validation attributes.
What else could be broken? It is definitely not an issue with the Validation JS files, but rather Html.TextBoxFor and other helper classes for some reason can't tell that the fields have attributes on them!
After a whole day of trying to figure out what could possibly be wrong I decided to completely uninstall any traces of Autofac and Ninject I had (don't know why I had Ninject, don't remember ever installing it) and surprise, surprise things started working again. I then reinstalled the latest versions of the Autofac packages I had and attributes still worked, so maybe it had something to do with those rogue Ninject packages.
I still don't know why exactly Autofac or Ninject would mess with how attributes and validation work, without me explicitly telling them to do so, but at this point I don't even care.
Hopefully this helps someone!

Issue displaying money on view

I have the following
public decimal? Price {get;set;}
When I enter 3000.00 in to the textbox on the view (textbox below)
<div class="form-group">
<label class="col-lg-3 control-label no-padding-right">Price</label>
<div class="col-lg-5">
#Html.ValidationMessageFor(m => m.Price)
<div class="input-group">
<span class="input-group-addon">£</span>
#Html.TextBoxFor(m => m.Price, new { #class = "form-control", type = "text", id = "txtPrice", onkeypress = "return isNumberKey(event)" })
</div>
</div>
<label class="col-lg-4 control-label" style="text-align: left">Decimal format</label>
So it would look like this
It saves in the database as 3000.00 which is expected, but when I return back to the view to edit it the value in the textbox is 3000.0000
I have tried some of the solutions on here
Remove trailing zeros of decimal
I think the issue I have is the field on the view is of type decimal not a string, so I'm uncertain on how to format this decimal to remove the trailing zeros so it looks like picture above
You need to use the oveload of TextBoxFor that accepts a format string
#Html.TextBoxFor(m => m.Price, "{0:0.00}", new { #class = "form-control", type = "text", id = "txtPrice", onkeypress = "return isNumberKey(event)"})
Side notes:
Remove type="text". The html helper already adds this for you (add
is there a reason why you dont just use the default id rendered by
the helper, which would be id="Price"?).
Use Unobtrusive Javascript rather that polluting your markup
with behavior - e.g. $('#txtPrice').keypress(...

ASP.NET MVC Client Side Validation Message Error

Can somebody tell me why "This field is required" and "Please insert database name" are being displayed instead of just "Please insert database name"?
This is my model :
public class InstallViewModel
{
[Required(AllowEmptyStrings = false, ErrorMessage = "Please insert database name")]
public string DatabaseName { get; set; }
and this is my view :
<div class="input-group">
<span class="input-group-addon">Database</span>
#Html.TextBoxFor(w => w.DatabaseName, new { #class = "form-control", placeholder = "Database name" })
</div>
#Html.ValidationMessageFor(w=> w.DatabaseName)
Thank you.
EDIT:
Can you see the image attached ? I have some problems uploading images.
The view is a partial view and this is the whole partial view:
#Html.ValidationMessageFor(w => w.DatabaseName)
<div class="input-group">
<span class="input-group-addon">Database</span>
#Html.TextBoxFor(w => w.DatabaseName, new { #class = "form-control", placeholder = "Database name" })
</div>
<br />
#Html.CheckBoxFor(w => w.UseWindowsAuthentication, new { #checked = "checked" }) Use Windows Authentication<br /><br />
<div class="wizard-sqlauth" style="display: none">
<div class="input-group">
<span class="input-group-addon">User name</span>
#Html.TextBoxFor(w => w.UserName, new { #class = "form-control", placeholder = "User name" })
</div>
#Html.ValidationMessageFor(w => w.UserName)<br />
<div class="input-group">
<span class="input-group-addon">Password</span>
#Html.PasswordFor(w => w.Password, new { #class = "form-control" })
</div>
#Html.ValidationMessageFor(w => w.Password)
</div>
DatabaseName is "Required" and your input is empty. (There is only placeholder text)
Are you calling jquery validation "manually" anywhere in javascript, i.e.
$('#myform').valid() ?
That would trigger the default value for the required rule ("This field is required."), and would append it as a label after the input, which is exactly the behavior your are experiencing.
If you really need to use both (MVC's Unobstrusive validation + jQuery validation) you can configure jquery validation to ignore certain fields, for example
$('#myform').validate({
ignore: '#databasefieldId'
});
You have applied the RequiredAttribute attribute to a property to the property DatabaseName which implies that the property must contain a value.
A validation exception is raised if the property is null, an empty string (""), or contains only white-space characters.
You just add #Html.ValidationMessageFor(w=> w.DatabaseName) in the top of div. This will show the summary.

Categories