Trouble with checkbox validation in Razor form - c#

I am currently at an internship and am completely new to Razor and C# MVC. I am currently building a simple Razor form, but my validation is giving me grief for a check box.
Here is my model code:
[DisplayName("Sign me up for spam* ")]
[Range(typeof(bool), "true", "true", ErrorMessage = "You must sign up for spam.")]
public bool Check { get; set; }
Here is my Razor markup:
#Html.LabelFor(model => model.Check, new { #class = "" })
#Html.CheckBoxFor(model => model.Check, new { #class = "example1"})
Here is the generated HTML:
<input class="example1" data-val="true" data-val-range="You must sign up for spam." data-val-range-max="True" data-val-range-min="True" data-val-required="The Sign me up for spam* field is required." id="Check" name="Check" type="checkbox" value="true">
<input name="Check" type="hidden" value="false">
I know that Razor will generate both inputs automatically. My problem is that the validation is simply not working on the check box. The model state is always invalid because of it, and on the client side the error message appears when the box is checked and disappears when the box is unchecked. I have been googling for answers, but have come up short and my mentor doesn't know what is going screwy either.

It looks like a client side reversed issue. Add this jquery in your page and I think it will be fixed:
<script>
// extend range validator method to treat checkboxes differently
var defaultRangeValidator = $.validator.methods.range;
$.validator.methods.range = function(value, element, param) {
if(element.type === 'checkbox') {
// if it's a checkbox return true if it is checked
return element.checked;
} else {
// otherwise run the default validation function
return defaultRangeValidator.call(this, value, element, param);
}
}
</script>

Related

Unobtrusive client-side validation for bool field not working in ASP.NET Core MVC

I found a very interesting problem in ASP.NET Core. I am using my bool field for a checkbox. I want to force the user to check the checkbox for the form to be submitted.
This bool field in my Model class is:
[Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the Terms")]
public bool TermsAccepted { get; set; }
Notice I have applied [Range] validation attribute. And it works perfectly for the Server side validation.
My action method code is fairly simple:
[HttpPost]
public IActionResult Index(JobApplication jobApplication)
{
if (ModelState.IsValid)
return View("Accepted", jobApplication);
else
return View();
}
But the problem is happening when I apply client side validation
On my view i apply the 3 scripts:
#section scripts {
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js">
</script>
}
The client side validation works totally opposite, it is giving error message when I check the checkbox. Why it is happening opposite?
The HTML code produced by the checkbox is:
<input type="checkbox" class="input-validation-error" data-val="true" data-val-range="You must accept the Terms" data-val-range-max="True" data-val-range-min="True" data-val-required="The TermsAccepted field is required." id="TermsAccepted" name="TermsAccepted" value="true" aria-describedby="TermsAccepted-error">
Please help?
I was having this problem, your code is ok with a few additions...
I updated to the latest versions of jquery.validate (1.19.1) and jquery.validation.unobtrusive (3.2.11), (using libman to manage these dependencies).
Also I added this javascript block to extend the functionality of the validator methods on that page.
<script>
// extend range validator method to treat checkboxes differently
var defaultRangeValidator = $.validator.methods.range;
$.validator.methods.range = function(value, element, param) {
if(element.type === 'checkbox') {
// if it's a checkbox return true if it is checked
return element.checked;
} else {
// otherwise run the default validation function
return defaultRangeValidator.call(this, value, element, param);
}
}
</script>
All about jquery.validate.unobtrusive
Maybe too late. But I found one solution for validating check box 'Must Be True'. It will work on client side and server side as well
It's possible to use same as with ConfirmPassword, but need to include to model one more hidden property bool with 'true' value. And to compare your check box with this property. Or just to use pure HTML if you have api call.
HTML for direct use
<div class="input-group has-validation">
<div class="form-check">
<input class="form-check-input" data-val="true" data-val-equalto="You have to agree with 'Terms amd Conditions' to register" data-val-equalto-other="AgreedWithTerms" data-val-required="You have to agree with 'Terms amd Conditions' to register" id="AgreeWithTerms" name="AgreeWithTerms" type="checkbox" value="true">
<input name="AgreedWithTerms" type="hidden" value="true">
<span class="field-validation-valid" data-valmsg-for="AgreeWithTerms" data-valmsg-replace="true"></span>
<label class="form-check-label" for="AgreeWithTerms">
<strong>Agree with</strong>
<a class="" href="/terms/" target="_blank">Terms and Conditions...</a>
</label>
</div>
</div>
In case of ASP.NET Core or Framework. Just include one hidden bool property to model "AgreedWithTerms" with value 'true' as follow:
C# Model
[Required]
[Compare("AgreedWithTerms", ErrorMessage = "You have to agree with 'Terms amd Conditions' to register")]
public bool AgreeWithTerms { get; set; }
[HiddenInput]
public bool AgreedWithTerms { get; set; } = true;

Lost remaining record after validation error comes in MVC

I have one MVC project,containing user registration form which have 25-30 fields to fill. After filling form if user forgot to fill mandatory field then it will shows validation error. But remaining all fields loss their data.
I mentioned in controller like
if (!ModelState.IsValid)
{
ModelToDBclass obj = new ModelToDBclass();
objModel.Id = Convert.ToInt32(obj.GetMaxPaperId());
objModel.countryNameDB = obj.GetcountryName();
return View(objModel);
}
and finally it returns the blank view. but at runtime when it comes to
return View(objModel); , the model shows the data with every field, but when it comes to view it unable to show record in text boxes and dropdown. I used textbox like,
<div class="col-sm-2"><input type="text" class="form-control" name="ConsumerFName" id="txtConsumerFirstName" placeholder="First Name" />
#Html.ValidationMessageFor(m => m.ConsumerFName)</div>
so, please help me how can i display filled record after validation error
You should always use Html Helper
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" }, placeholder = "First Name", autofocus = "autofocus" })
Then only when the Model state is not valid, it will show the returned object values at the respective fields. Don't normal html tags.
Hope this helps

MVC4 validation does not work

I have simple 1 page application to send email out to users. I have 3 fields for name, email and phone number. The code seems to work with input button, with validations firing and throwing proper error message. But I am more inclined towards using anchor tag (ActionLink) for my UI. The data still posts when I click on anchor tag (using jQuery) but the validations don't fire. Is there anything that I am missing or there's a better way of doing it?
I have used this post as reference.
Model
public class Contact
{
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "Phone is required")]
public string PhoneNumber { get; set; }
}
View
<div>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control", placeholder="Name" })
#Html.ValidationMessageFor(model=>model.Name)
</div>
<div>
#Html.TextBoxFor(model => model.Email, new { #class = "form-control", placeholder="Email" })
#Html.ValidationMessageFor(model=>model.Email)
</div>
<div>
#Html.TextBoxFor(model => model.PhoneNumber, new { #class = "form-control", placeholder="Phone" })
#Html.ValidationMessageFor(model=>model.PhoneNumber)
</div>
<div>
<input type="submit" value="Give me Free Advice" />
<div class="btn">
#Html.ActionLink("I want free advice", "designerhome")
</div>
</div>
<script>
$(function () {
$('.btn').click(function (e) {
$.post("/campaign/designerhome", { Name: $("#Name").val(), Email: $("#Email").val(), PhoneNumber: $("#Phone").val() }, function (result) {
//do whatever with the response
if (result.status == true) {
alert('Email submitted successfully');
}
});//end of post
});//end of click
});
</script>
Controller
[HttpPost]
public ActionResult designerhome(Contact contact)
{
if (ModelState.IsValid)
{
}
return View("Advert1");
}
We have some reasons why validation not working
1. Check appsettings in web config
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Both Should be true if you want to run client side validation.
2. Seems in your code you are not using Form tag as it is posted in the question
Form tag is must for validation
3. Jquery is not properly refrenced on layout page
please check following jquery refrence on your layout page
jquery.unobtrusive*.js
jquery.validate*.js
Hope it will help you.
I would force the validation in your click handler, as jQuery seems to do that only for the automatic submit of the form (and not for the manual post() you are doing):
$('.btn').click(function (e) {
if ($('#YourFormIdHere').valid()) { // Will force validation
$.post(...);
}
});
As your making an Ajax request to the Action, your validations will not be reflected as the view is not rendered again. To stay on the same track you can return the JSON like
return Json(new {Valid = validState,
Errors = Get Errors FromModel State,
});
and then repopulate using the JavaScript.
Another Way could be around making custom Helpers which will |make a POST request to the desired Action.Code Reference for the same is here.
And at last what you can do is create a HTML button and make a POST request.
Simply style your input button to look like a link with the following CSS:
input[type=submit] {
background:none!important;
border:none;
padding:0!important;
color:#069;
text-decoration:underline;
cursor:pointer;
}
<input type="submit" value="Give me Free Advice" />
This will allow all the built in validation to work as is, with no difference to the user other than the appearance.
If your requirement is to use ajax to post you must manually call the validate method within the JavaScript with jquery unobtrusive.
This can be done with the following:
// replace the `formId` with the one defined in your view
var $form = $('#formId');
$.validator.unobtrusive.parse($form);
$form.validate();
if ($form.valid()) {
// Do post
}
In order to manually pull out the error messages you can use this:
$.each($form.validate().errorList, function (key, value) {
$errorSpan = $("span[data-valmsg-for='" + value.element.id + "']");
$errorSpan.html("<span style='color:red'>" + value.message + "</span>");
$errorSpan.show();
});
Which replaces the ValidationMessageFor markup with the failure messages.

Display error messages using c# mvc with razor view engine

I want to display error messages dynamically i.e, when the cursor moves out of the field but not when the form is submitted.
My requirement is like this:-
I have to design a registration form with some fields like name,address,phone number,email,password etc.
i designed it & saved the data successfully in DB but what i exactly required in the sense i have to display error messages dynamically without using "ajax" as i have already stated ...
My code is like this:-
View:-
<div class="venfor_line5" popText><label>#Resources.Resources.VendorReg_phoneNumber<img src="~/images/star.png" /> </label>
#Html.TextBoxFor(model => Model.MobileNumber, new { #class = "input" })
#Html.ValidationMessageFor(model => model.MobileNumber)</div>
<div class="venfor_line1" popText = #Resources.Resources.VendorReg_emailHintStr>
<label>#Resources.Resources.VendorReg_email<img src="~/images/star.png" /> </label>
#Html.TextBoxFor(model => Model.Email, new { #class = "input" })
#Html.ValidationMessageFor(model => model.Email)</div>
I have gone through many references but not found exactly what i am looking for.Any help would be greatly appreciated. can anyone guide me in resolving this issue.
You could use jQuery's focusOut() method to perform validation. Something like:
$('#elementId').focusOut(function(){
//do validation here
});
If you are using unobtrusive jQuery validation you could eagerly enable it so that it is automatically triggered onblur without requiring the user to submit the form:
$(document).ready(function () {
var settngs = $.data($('form')[0], 'validator').settings;
settngs.onfocusout = function (element) { $(element).valid(); };
});

ASP .NET MVC Disable Client Side Validation at Per-Field Level

I'm using ASP .NET MVC 3 with Data Annotations and the jQuery validate plugin.
Is there a way to mark that a certain field (or certain data annotation) should only be validated server-side?
I have a phone number field with a masking plugin on it, and the regular expression validator goes crazy on the user's end. The regex is only a fail-safe (in case someone decides to hack the javascript validation), so I don't need it to run on the client side. But I'd still like the other validation to run client side.
I'm not sure if this solution works on MVC3. It surely works on MVC4:
You can simply disable client side validation in the Razor view prior to render the field and re-enable client side validation after the field has been rendered.
Example:
<div class="editor-field">
#{ Html.EnableClientValidation(false); }
#Html.TextBoxFor(m => m.BatchId, new { #class = "k-textbox" })
#{ Html.EnableClientValidation(true); }
</div>
Here we disable client side validation for the BatchId field.
Also I have developed a little helper for this:
public static class YnnovaHtmlHelper
{
public static ClientSideValidationDisabler BeginDisableClientSideValidation(this HtmlHelper html)
{
return new ClientSideValidationDisabler(html);
}
}
public class ClientSideValidationDisabler : IDisposable
{
private HtmlHelper _html;
public ClientSideValidationDisabler(HtmlHelper html)
{
_html = html;
_html.EnableClientValidation(false);
}
public void Dispose()
{
_html.EnableClientValidation(true);
_html = null;
}
}
You will use it as follow:
<div class="editor-field">
#using (Html.BeginDisableClientSideValidation()) {
#Html.TextBoxFor(m => m.BatchId, new { #class = "k-textbox" })
}
</div>
If anyone has better solutions please let me know!
Hope this help.
You can switch off client-side unobtrusive validation for a single field by adding a data-val='false' attribute:
#Html.TextBoxFor(m => m.BatchId, new { data_val = "false" })
This will override the data-val='true' attribute that MVC adds due to any System.ComponentModel.DataAnnotations attributes. The HTML element will still be decorated with other validation attributes (e.g. data-val-required) but they won't have any effect.
(Note the underscore in data_val above. MVC automatically converts underscores to hyphens in anonymous type properties, so data_val becomes data-val when rendering the HTML)
MVC5 use jquery.validate
http://jqueryvalidation.org/rules/
If you want to remove validations in MVC5 client-Side you need to do the following:
Remove all validations on 'myinput'
$("#myinput").rules("remove");
Specific validations
$("#myinput").rules("remove", "min max" );
Listing the validations can help
$("#myinput").rules();
Then you will need to correct your Code Behind to validate manually your model or differently because ModelState.IsValid will be false. Using ModelState.Clear() and TryValidateModel can then be handy.
Edit:
Disabling the control also remove the validations.
$("#myinput").attr('disabled', disabledValue);
Assuming you use default unobtrusive validation, You could use some javascript to remove rules on client side. Take a look at Plugins/Validation/rules
To achieve this goal in the given scenario, we need to make two tweaks.
Client Side
To disable client side validation, we need to disable it by force.
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #data_val = "false" , #class = "form-control"} })
Notice the #data_val= “false”. It will disable the validation on this field.
Server Side (In Action)
When the model is validated on the post action, ModelState.IsValid will always return false because password is not provided. Here we have to provide the current password to the model and Re-validate the model.
var userObj = db.Users_Info.Where(a => a.Id == users_Info.Id).FirstOrDefault();
if (String.IsNullOrEmpty(users_Info.Password))
{
users_Info.Password = userObj.Password;
}
ModelState.Clear();
TryValidateModel(users_Info);
Let me explain, first we retrieve current information saved in the database which we are using later to assign to current model if password is not provided. The last two lines actually reset the ModelState to return updated result on ModelState.IsValid.
I ran into trouble with data_val="true". I had a sequence of radio buttons tied to a single property in my model. The data validation only worked when I applied data_val="true" to the first #Html.RadioButtonFor call.
In debugging this, I discovered you can also disable or alter individual rules on the client side by using data_rule_??. The rules can be found in the jquery validation documentation.
for example;
#Html.RadioButtonFor(m => m.Answer, "Yes", new { data_rule_Required = "false" });
#Html.TextBoxFor(m => m.Answer, new { data_rule_minlength = "10" }
If you want to remove validations in MVC5 client-Side you need to do the following:
$("#Email").rules("remove", {
"required",
"minlength",
"email"
}
});

Categories