I am trying to use unobtrusive Jquery to validate in client side but something is wrong.
the error like the attached image :
this is my code:
*In BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*", "~/Scripts/jquery.unobtrusive*"));
*in the master page :
<script src="~/Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
*In view model class :
public class EmployeeViewModel
{
public int? EmployeeId { get; set; }
[MaxLength(length: 10, ErrorMessage = "First name can't be more than 10 charechers")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("First name is required!"))]
public string FirstName { get; set; }
[MaxLength(length: 10, ErrorMessage = "First name can't be more than 10 charechers")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("Last Nmae is required!"))]
public string LastName { get; set; }
[MaxLength(length: 20)]
public string FullName { get; set; }
[Range(500, 1500, ErrorMessage = "Salare must be between 500 DK and 1500 DK")]
[Required(AllowEmptyStrings = false, ErrorMessage = ("Salary is required!"))]
public double Salary { get; set; }
[EmailAddress(ErrorMessage = "Invalid Email")]
[Required(AllowEmptyStrings =false,ErrorMessage =("Email is required!"))]
public string Email { get; set; }
public bool IsMarriage { get; set; } = false;
public string Gender { get; set; }
public string DepartmentName { get; set; }
[Required(AllowEmptyStrings = false,ErrorMessage ="Birth day is required")]
//[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
public TimeSpan? StartWorkingTime { get; set; }
public TimeSpan? EndWorkingTime { get; set; }
public int? DepartmentId { get; set; }
}
*In view :
#using (Html.BeginForm("Save","Employee",FormMethod.Post))
{
<div class="form-group ">
<div class="row">
<div class="col-md-2 col-form-label">
#Html.LabelFor(e => e.FirstName, "First Name")
</div>
<div class="col-md-10">
#Html.TextBoxFor(e => Model.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(e => e.FirstName, "", new { #class = "text-danger text-left" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-2">
#Html.LabelFor(e => e.LastName, "Last Name")
</div>
<div class="col-md-10">
#Html.TextBoxFor(e => Model.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(e => e.LastName, "", new { #class = "text-danger text-left" })
</div>
</div>
</div>
}
**the problem that the client validation not working, but the server side working good
I think there could be a problem with your MaxLength attribute syntax. It shoud be
[MaxLength(10, ErrorMessage = "First name can't be more than 10 charechers.")]
But for client validation, instead of using MaxLength attribute, you should try to replace it by StringLength attribute.
[StringLength(10, ErrorMessage = "First name can't be more than 10
charechers.")] [Required(AllowEmptyStrings = false, ErrorMessage =
("First name is required!"))]
public string FirstName { get; set; }
I understand this is an year old question however might help someone who might come here looking for answer.
First of all, questioner has not posted the code completely, so it is difficult to arrive at a conclusion why exactly we get error(what is undefined). I do not see the jquery client side validation rules which define the rules and messages for form inputs.
Apart from what he has done, he will need to have client side validation rules as follows:
This example is for a simple registration form which consists are Email, Password and Confirm Password as text input.The code is as follows:
$('#registerFormId').validate({
errorClass: 'help-block animation-slideDown',
// You can change the animation class for a different entrance animation - check
animations page
errorElement: 'div',
errorPlacement: function (error, e) {
e.parents('.form-group > div').append(error);
},
highlight: function (e) {
$(e).closest('.form-group').removeClass('has-success has-error').addClass('has-error');
$(e).closest('.help-block').remove();
},
success: function (e) {
e.closest('.form-group').removeClass('has-success has-error');
e.closest('.help-block').remove();
},
rules: {
'Email': {
required: true,
email: true
},
'Password': {
required: true,
minlength: 6
},
'ConfirmPassword': {
required: true,
equalTo: '#Password'
}
},
messages: {
'Email': 'Please enter valid email address',
'Password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 6 characters long'
},
'ConfirmPassword': {
required: 'Please provide a password',
minlength: 'Your password must be at least 6 characters long',
equalTo: 'Please enter the same password as above'
}
}
});
Please make sure the names of your text inputs should be same as the properties that you want to validate.
Apart from this make sure Client side validation unobtrusive is enabled in web.config as follows:
Here is an excellent blog post which explains how to implement client and server side validation using jquery unobstrusive validation.
https://www.c-sharpcorner.com/article/asp-net-mvc5-jquery-form-validator/#:~:text=Server%20side%20form%20validation%2C%20as,with%20ASP.NET%20MVC5%20platform.
Asma Shaikh
Note : Above blog post is NOT written by me
Related
I am trying to post the form values back to the controller. But in the action, I get the ViewModel as null.
Here is ViewModel
public class CommunicationDetailsViewModel
{
public string OrganizationName { get; set; }
public List<Country> Country { get; set; }
public List<State> State { get; set; }
public List<City> City { get; set; }
[Display(Name = "Id")]
public int CountryId { get; set; }
[Display(Name = "Id")]
public int StateId { get; set; }
[Display(Name = "Id")]
public int CityId { get; set; }
[StringLength(32), Required(ErrorMessage ="Address is required")]
public string Address { get; set; }
[StringLength(32), Required(ErrorMessage = "Building name is required")]
public string BuildingName { get; set; }
}
Below is the controller action:
[HttpPost]
public ActionResult Save(CommunicationDetailsViewModel communicationDetailsViewModel)
{
return View();
}
Does it have to do anything with the Kendo UI for MVC? Because this is the very first time I am using Kendo UI. Below is the view:
#model WebAPI.ViewModels.CommunicationDetailsViewModel
#{
ViewBag.Title = "Supplier Information";
}
<h4>Supplier Details</h4>
#using (Html.BeginForm("Save", "SupplierInformation", FormMethod.Post ))
{
<div class="demo-section k-content">
<div class="form-group">
#Html.Label("Organization name")
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("txtOrganization").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
</div>
<div class="form-group">
#Html.Label("Country")
#(Html.Kendo().DropDownList().Name("ddlCountry").DataTextField("CountryName").DataValueField("Id").BindTo(Model.Country))
</div>
<div class="form-group">
#Html.Label("State")
#(Html.Kendo().DropDownList().Name("ddlState").DataTextField("StateName").DataValueField("Id").BindTo(Model.State))
</div>
<div class="form-group">
#Html.Label("City")
#(Html.Kendo().DropDownList().Name("ddlCity").DataTextField("CityName").DataValueField("Id").BindTo(Model.City))
</div>
<div class="form-group">
#Html.Label("Address")
#Html.Kendo().TextBoxFor(model => model.Address).Name("txtAddress").HtmlAttributes(new { #class="k-textbox required", placeholder="Address", #maxlength = "32" })
</div>
<div class="form-group">
#Html.Label("Building name")
#Html.Kendo().TextBoxFor(model => Model.BuildingName).Name("txtBuildingName").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Address", #maxlength = "32" })
</div>
</div>
#Html.Kendo().Button().Name("btnSave").Content("Save").HtmlAttributes(new { type = "submit", #class = "k-button k-primary" })
}
And interestingly, if I use FormCollection instead of my ViewModel, I am able to get the values in the action.
What am I missing here? Must be something stupid. Any help appreciated.
I think problem here is caused by you change name by Name function. Note that MVC binding properties by name attribute of input tag so don't change it
For example you use
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("txtOrganization").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
You change name of input from OrganizationName to txtOrganization that may cause MVC cann't binding properties exactly. You should keep its original name or ignore change its name like this
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("OrganizationName").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
I have a simple requirement but unable to understand how to achieve this. I have these properties in my View Model.
public class Feedback
{
[Required]
[Display(Name = "Current ID")]
public int? PreviousID { get; set; }
[Required]
[Display(Name = "Next ID")]
public int? NextID { get; set; }
[Required]
public int ScenarioID { get; set; }
[Display(Name = "Select you scenario")]
public IEnumerable<SelectListItem> YourScenario { get; set; }
}
Now on the view I have,
<div class="form-group">
#Html.LabelFor(m => m.YourScenario, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.DropDownListFor(m => m.ScenarioID, m.YourScenario, "Choose Scenario", new { #class = "form-control chosen-select" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.PreviousID, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.TextBoxFor(m => m.PreviousID)
</div>
</div>
<div class="form-group" style="display:none">
#Html.LabelFor(m => m.NextID, new { #class = "col-sm-3 control-label" })
<div class="col-sm-9">
#Html.TextBoxFor(m => m.NextID)
</div>
</div>
On the view as it can be seen that only PreviousID and a DropDownList for Scenario is displayed. Using JQuery I am showing and hiding the div for NextID based on some specific value of DropDownList. So suppose if user select "Scenario 3" from the dropdown then the Input for NextID is displayed.
Having explained all of this what I want is to change the Display name for PreviousID based on the selected value of dropdownlist. So if user selects "Scenario 1" and "Scenario 2" then the Display Name for PreviousID should be "Current ID" and if user selects "Scenario 3" then the Display Name should be "Previous ID". This change should also be reflected in the Validation Summary. So kindly tell me how to achieve this? Many Thanks
I have two ideas:
1)
You could remove the line [Display(Name = "Current ID")]. Then you need to use Label("SomeName") instead of LabelFor.
Then you create an event like DropDownList_SelectionChanged that then changes the Name of the Label.
2)
Or you add a member DisplayName and bind to it:
public class Feedback
{
[Required]
public int? PreviousID { get; set; }
[Required]
[Display(Name = "Next ID")]
public int? NextID { get; set; }
[Required]
public int ScenarioID { get; set; }
[Display(Name = "Select you scenario")]
public IEnumerable<SelectListItem> YourScenario { get; set; }
public String DisplayName {
get
{
String name = "";
if (ScenarioID == 1) {
name = "SomeName";
} else {
name = "otherName";
}
return name;
}
}
}
In your view:
#Html.Label({Binding Content=m,Path=DisplayName}
It's probably not completely correct since I can not test your project but I hope you get the idea. Please tell me what you tried.
I suggest you remove the [DisplayName] attribute, and instead use a <label> element manually in the view. Give the label an id e.g.
<label for="whatever" id="lbl-whatever">Hello World</label>
Create a JavaScript file that the view references, via a <script> tag, which uses jQuery to capture the change event of the dropdown
$(function(){
$("#ScenarioID").on("change", function() {
console.log(this.id);
console.log(this.value);
// I think this.id and this.value should display the id and value of the selected // item in the list.
$("#lbl-whatever").text("Foo");
});
});
Hopefully the above should be enough to get you started.
I have form which validate inputed email on uniqueness.
<form id="emailValidationForm">
#Html.ValidationSummary(true, String.Empty, new {#class = "text-danger text-center"})
<div class="form-group text-center">
<div class="input-group margin-bottom-5 margin-top-10">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
#Html.TextBoxFor(m => m.Email, new {#class="form-control", #placeholder="Enter your Email",#data_toggle="tooltip"})
#*<input type="text" name="Email" placeholder="Enter your Email" class="form-control" data-toggle="tooltip">*#
</div>
#Html.ValidationMessageFor(m => m.Email, null, new { #class = "text-danger text-center" })
</div>
<div class="text-right">
<button type="submit" class="btn-u btn-u-wide btn-u-orange" title="Validate email">Join</button>
</div>
</form>
Email is part of next Model :
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
So, when i type nothing in text-box i will get error. When i type email that is already registered, i will get also error from function which checks uniqueness.
[AllowAnonymous]
public JsonResult EmailValidation(string email)
{
if (ModelState.IsValid)
{
var user = _service.FindByEmail(email);
if (user == null)
{
return Json(new {result = true, message = "Email is validated"}, JsonRequestBehavior.AllowGet);
}
ModelState.AddModelError(string.Empty, "Email already exists");
return Json(new
{
result = false,
message =
RenderRazorViewToString("~/Views/Account/_RegisterPartialView.cshtml",
new RegisterViewModel {Email = email})
}, JsonRequestBehavior.AllowGet);
}
return Json(new {result = false, message = "Input Email"}, JsonRequestBehavior.AllowGet);
}
But then client validation doesn't works, i can input nothing in email text-box and it will go on.
How can i fix it?
I use jquery 1.10.2 and jquery.validate for validation. Work on MVC5. Use Bootstrap3 for styling.
Also i have set custom defaults:
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".input-group").addClass("has-error");
},
unhighlight: function (element) {
$(element).closest(".input-group").removeClass("has-error");
}
});
That script is in partialView (i try to replace it in js-module that is used on partialView, but this doesn't works. So i left script it in partialView)
You need to add the remote annotation to the Email-field:
[Remote("EmailValidation","<ControllerName>", ErrorMessage="{0} already has an account, please enter a different email address.")]
public string Email { get; set; }
Also it appears to me like you are mixing two concepts here. The validation-check should be a simple JSON-result like this:
public JsonResult EmailValidation(string email)
{
var user = _service.FindByEmail(email);
return user == null
? Json(true, JsonRequestBehavior.AllowGet)
: Json(false, JsonRequestBehavior.AllowGet);
}
I have a ASP.NET MVC 4 webpage where I use the following HTML code to generate a form for enduser :
#using (Html.BeginForm("JEdit", "Post", FormMethod.Post, new { id = "frmEditPost" }))
{
<div id="postListEditor" class="regularContainer" style="position:relative;">
#Html.ValidationSummary(false)
#Html.HiddenFor(c=> c.Id, false)
<div class="floatLeft">
#Html.LabelFor(c => c.Title, true)
#Html.TextBoxFor(c => c.Title, new { #class = "tb1", #Style = "width:400px;" })
#Html.ValidationMessageFor(model => model.Title)
</div>
<br style="clear:both;" />
<div class="floatLeft">
#Html.LabelFor(c => c.Text, true)
#Html.TextAreaFor(c => c.Text, new { #class = "tb1", #Style = "width:400px; height:200px" })
#Html.ValidationMessageFor(model => model.Text)
</div>
<div style="clear:both;"></div>
#Html.Raw(#Html.SubmitButton("Posta", "btPost", "", "", "ValidateFormAndAjaxSubmit('frmEditPost', this);"))
</div>
}
When clicking the submitbutton the following javascript will be runned :
function ValidateFormAndAjaxSubmit(formId, callingElement) {
if (IsNotDblClick(callingElement.id)) {
var _form = $("#" + formId);
var validator = _form.validate();
var anyError = false;
anyError = !_form.valid();
if (anyError) {
window.latestClick = '';
return false; // exit if any error found
}
$.post(_form.attr("action"), _form.serialize(), function (data) {
if (data.success && data.redirectUrl.length > 0) {
window.location.href = data.redirectUrl;
}
else {
var isValid = validateResponse(_form, data);
window.latestClick = '';
}
})
}
}
The problem is that the hiddenFor is never sent back but all other members are? I can see in the generated HTML that the hitten field is set like this :
<input data-val="true" data-val-number="The field Int32 must be a number." data-val-required="The Int32 field is required." id="Id" name="Id" type="hidden" value="21">
So why is this hittenField not sent back to the service?
Edit1 :
This is sent according to dev in Chrome
Request URL:http://localhost:5215/Post/JEdit
Request Headersview source
Accept:*/*
Content-Type:application/x-www-form-urlencoded
Origin:http://localhost:5215
Referer:http://localhost:5215/Post/Edit/42
User-Agent:Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
X-Requested-With:XMLHttpRequest
Form Dataview sourceview URL encoded
Id:42
Title:testar3532
Text:testas3532
Url:http://test.se
Tags:
Edti2 :
This is how the ViewModel looks like :
public class EditPostViewModel
{
public int Id = -1;
public EditPostViewModel() { }
public EditPostViewModel(string title, string text, string url)
{
Title = title;
Text = text;
Url = url;
}
[Display(Name = "Titel"/*Description = "..."*/)]
[StringLength(100, MinimumLength = 3, ErrorMessage = "...")]
[Required(ErrorMessage="...")]
public string Title { get; set; }
[Display(Name = "Text")]
[StringLength(2500, MinimumLength = 3, ErrorMessage = "...")]
public string Text { get; set; }
[StringLength(100, MinimumLength = 3, ErrorMessage = "...")]
[Display(Name = "Länk")]
[RegularExpression(#"^(http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?)?$", ErrorMessage="...")]
public string Url { get; set; }
[Display(Name = "Tags")]
[TagAttribute(ErrorMessage="...a")]
public string Tags { get; set; }
public List<int> TagIdList { get; set; }
public string CustomError { get; set; }
}
ASP.NET MVC cannot bind to fields by default. Only properties. So change your Id member to a property.
Try doing #Html.HiddenFor(c => c.Id, new { Value = Model.Id })
Im using .net 4.5, MVC 4 and im using a model binder for a form. I have a HTML Validation summary which will display the errors as a list, which works fine.
What I want to do is get if a single Model Property has triggered an error based on the ModelState and if so, give it an "Error" CSS class which will turn it red. please see below.
<div class="controls">
#{
// does this element have an error??
if (Model.LastName == error)
{
#Html.ValidationMessageFor(x => x.LastName)
#Html.TextBoxFor(x => x.LastName, new { type = "text", id = "LastName", name = "LastName", value = Model.LastName, #class = "Error" })
}
else
{
#Html.ValidationMessageFor(x => x.LastName)
#Html.TextBoxFor(x => x.LastName, new { type = "text", id = "LastName", name = "LastName", value = Model.LastName, })
}
}
}
Validation Summary
#{
if (ViewBag.Error != null && ViewBag.Error == true)
{
<div class="alert alert-error">
<h3>Error</h3>
<p>#ViewBag.Message</p>
<p>#Html.ValidationSummary(false)</p>
</div>
}
else if (ViewBag.Error != null && ViewBag.Error == false)
{
<div class="alert alert-success">
<h3 style="color:green;">Details Updated Successfully Received</h3>
<p style="color:green;">#ViewBag.Message</p>
</div>
}
}
Model
public class UpdateDetailsModel
{
public VIPSessionObject VIPSessionObject { get; set; }
[Required]
[DataType(DataType.Text, ErrorMessage = "Please Enter your First Name")]
public string FirstName { get; set; }
[Required]
[DataType(DataType.Text, ErrorMessage = "Please Enter your Last Name")]
public string LastName { get; set; }
[Required]
[DataType(DataType.PhoneNumber, ErrorMessage = "Please Enter your Phone Number")]
public string Telephone { get; set; }
[Required]
[DataType(DataType.EmailAddress, ErrorMessage = "Please Enter your Email Address")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password, ErrorMessage = "Please Enter your Motorpoint VIP Password")]
public string Password { get; set; }
[Required]
[DataType(DataType.Password, ErrorMessage = "The Passwords must match")]
[Compare("Password")]
public string PasswordConfirm { get; set; }
[Required]
[DataType(DataType.Date, ErrorMessage = "Please Enter your Date of Birth")]
public DateTime DateOfBirth { get; set; }
[Required]
public int VehiclesInHousehold { get; set; }
[Required(ErrorMessage = "Please select the number of cars in your household")]
public int NoOfVehicles { get; set; }
}
#Html.ValidationMessageFor(model => model.LastName, null, new { #class = "error" })
Then simply style your .error CSS class with red text, if the Last Name does not meet what your Model Data Annotation specifies, it will use the error message provided in the Annotation on your Model Property.
In your model you can drop the:
[DataType(DataType.Text, ErrorMessage = "Please Enter your Last Name")]
and replace your [required] with:
[Required(ErrorMessage ="Required Field")]
I have read in the past there are bugs with using the [DataType] attribute and I am googling around now to find the article.
What about manual JavaScript(or JQuery) validation of a control? The simpliest example:
function CheckForm()
{
var elementValue = document.getElementById('elementId').Value;
if(elementValue == null || elementValue == '')
{
document.getElementById('elementId').className = "Error";
}
else
{
document.getElementById('elementId').className = "";
}
}
Then you can use it in your form tag
<form method="POST" action="...">
...
<input id="elementId" type="text" ... />
<input type="submit" onClick="CheckForm()" .../>
</form>
You can perform any verification.
OR
Set ErrorMessage property for Display, Required, DataType as #Robert advised.
I'm not sure what exactly your problem is but any new MVC 4 project comes with styles for validation helpers. Here they are:
/* Styles for validation helpers
-----------------------------------------------------------*/
.field-validation-error {
color: #f00;
}
.field-validation-valid {
display: none;
}
.input-validation-error {
border: 1px solid #f00;
background-color: #fee;
}
.validation-summary-errors {
font-weight: bold;
color: #f00;
}
.validation-summary-valid {
display: none;
}
And basically this will get you a red text when validation of a form field fails as long as you have:
#Html.ValidationMessageFor(x => x.LastName)
next to your form field that need to be validated. Model and data validators you placed on your view model look good.
Every Form helper has an optional parameter called HtmlAttributes via which you can pass any html attributes you want to render on your page:
#Html.TextBoxFor(x => x.LastName, null, new {#class = "Error"})
Notice the # symbol which is there because class is a reserved word in C#...