bool property without Required attribute is required - asp.net-mvc

have a simple ViewModel with three properties like so:
public bool RememberMe { get; set; }
In my view I have a simple #Html.CheckBoxFor(p => p.RememberMe)
I am using Client Side validation enabled using Html.EnableClientValidation();
Why is this being set as a required field?

Try a nullable bool.
public bool? RememberMe { get; set; }
With reference types there are a number of default validation rules applied. If a reference type is not nullable, it becomes required by default. The best illustration of this is if you use a textbox to display some properties (not something you would do in your site, but good for testing purposes):
Model:
public bool? MyBool { get; set; }
public int MyInt { get; set; }
View:
#Html.TextBoxFor(p => p.MyBool)
#Html.TextBoxFor(p => p.MyInt)
You can see from a view source what happens on the page:
<input id="MyNullBool" name="MyNullBool" type="text" value="">
<input data-val="true" data-val-required="The MyBool field is required." id="MyBool" name="MyBool" type="text" value="False">
<input data-val="true" data-val-number="The field MyInt must be a number." data-val-required="The MyInt field is required." id="MyInt" name="MyInt" type="text" value="0">
The nullable bool has no validation attributes, whereas the bool has a data-val-required tag. The int has a data-val-required tag and a data-val-number attribute
Of course, on a checkbox this is all pretty redundant as it can only be checked (true) or not checked (false) so a required tag isn't much use.

#Html.CheckBoxFor(c => c.TermsAndConditions, new { required = "required" })
#Html.ValidationMessageFor(c => c.TermsAndConditions, "you must agree to terms and conditions of Service.)"

Related

MVC 5 view still render required field

Initially I have two required date time properties in my model. The client side validation works fine for them. But when i comment out the required DataAnnotation on one of the property, MVC view still generating data-val=true, ect... How to i fix this so that mvc view is rendering field is not required.
I've try $('#endDate').rules('remove', 'required')
but it still checking required field.
Model:
public class mymodel{
...
[Required]
public Datetime startDate { get; set;}
//[Required]
public Datetime endDate {get; set}
}
View:
#Html.LabelFor(model => mode.endDate ....)
#Html.EditorFor(model => model.endDate, new { htmlAttributes = new { #class = "form-control", id="endDate" } })
View Render
<input class="form-control text-box single-line hasDatepicker input-validation-error" data-val="true" data-val-date="The field endDate must be a date." data-val-required="The endDate field is required." id="endDate" ....>
<span class="text-danger field-validation-error" ....>
<span for="endDate" class> The endDate field is required.</span>
</span>
Properties with non-nullable types (such as DateTime) are inherently required, with or without the Required attribute, because they must have some value. To make it optional, you must use a nullable DateTime:
public DateTime? endDate { get; set; }

HtmlHelper Generate Validation Markup in Controller

This is somehow related to The Question
I am using jquery unobtrusive validation. I have the following model
public class MyModel
{
[Required]
public int ID { get; set; }
[MinLength(2)]
public string Description { get; set; }
}
I want to generate an html markup with validation(This is what I want to generate my self using code)
<input class="FormElement form-control valid" type="text" data-val="true" data-val-required="The ID field is required." id="ID" name="ID">
<input class="FormElement form-control valid" type="text" data-val="true" data-val-minlength="The field Description must be a string or array type with a minimum length of '2'." data-val-minlength-min="2" id="Description" name="Description" value="description changed 6">
My question is how Can I manually generate the markup from the model attributes inside my controller.
So My code will simply look like this
private readonly IHtmlGenerator htmlGenerator;
private readonly IHtmlHelper helper;
public MyController(IHtmlGenerator htmlGenerator, IHtmlHelper hh)
{
if (htmlGenerator == null)
throw new ArgumentNullException("htmlGenerator");
this.htmlGenerator = htmlGenerator;
this.helper = hh;
}
public IActionResult GenerateHtml()
{
HtmlHelper tempHelper= this.HtmlHelper;
// Generate the markup for ID and Description here from model MyModel(With VALIDATION)
}

RemoteAttribute is not passing parameter to action?

I am trying to use the RemoteAttribute to validate a data element serverside using JSON.
My data field is:
[Display(Name = "My Number")]
[Required]
[Remote("IsValidMyNumber","Home",ErrorMessage="Bummer")]
public string MyNumber { get; set; }
My controller is:
public JsonResult IsValidMyNumber(string MyNumber)
{
var test = services.ValidateMyNumber(MyNumber);
return Json(test,JsonRequestBehavior.AllowGet);
}
My view is:
<div class="editor-field">
#Html.EditorFor(model => model.CheckInformation.MyNumber)
#Html.ValidationMessageFor(model => model.CheckInformation.MyNumber)
</div>
The HTML generated is:
<input class="text-box single-line" data-val="true" data-val-remote="Bummer"
data-val-remote-additionalfields="*.MyNumber" data-val-remote-url="/Home/IsValidMyNumber"
data-val-required="The Number field is required." id="CheckInformation_MyNumber"
name="CheckInformation.MyNumber" type="text" value="" />
When I debug and step inside my controller the "MyNumber" parameter is null even though I have text in the textbox that this represents.
I know that the name has to be the same in the textbox as in the parameter and I have validated that.
Any ideas?
Seems like the generated name of your input field is:
name="CheckInformation.MyNumber"
That's probably because your view model is a parent model of what you have shown in your question and you used something along the lines of:
#Html.TextBoxFor(x => x.CheckInformation.MyNumber)
So make sure you have specified this prefix or the default model binder will never be able to rehydrate the values:
public ActionResult IsValidMyNumber([Bind(Prefix = "CheckInformation")] string myNumber)
{
var test = services.ValidateMyNumber(myNumber);
return Json(test, JsonRequestBehavior.AllowGet);
}
You can also receive the value of myNumber to pass your view model in the action parameter, Like.
It works for me.
public ActionResult IsValidMyNumber(YourViewModel vm)
{
var test = services.ValidateMyNumber(vm.myNumber);
return Json(test, JsonRequestBehavior.AllowGet);
}

Asp.Net Mvc Checkboxfor default value?

model
[DefaultValue(true)]
public bool IsActive { get; set; }
view
#Html.CheckBoxFor(model => model.IsActive)
html output and that is my expected
<input data-val="true" data-val-required="Yayında alanı boş bırakılmamalıdır!" id="IsActive" name="IsActive" type="checkbox" value="true" class="valid">
but checkbox is not checked. I cant understand why? What am I missing?
Thanks.
Per the MSDN
A DefaultValueAttribute will not cause a member to be automatically initialized with the attribute's value. You must set the initial value in your code.

Unrequired property keeps getting data-val-required attribute

This is the model with it's validation:
[MetadataType(typeof(TagValidation))]
public partial class Tag
{
}
public class TagValidation
{
[Editable(false)]
[HiddenInput(DisplayValue = false)]
public int TagId { get; set; }
[Required]
[StringLength(20)]
[DataType(DataType.Text)]
public string Name { get; set; }
//...
}
Here is the view:
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Tag</legend>
<div>#Html.EditorForModel()</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
And here is what get's renderd:
<form action="/Tag/Create" method="post">
<fieldset>
<legend>Tag</legend>
<div><input data-val="true" data-val-number="The field TagId must be a number." data-val-required="The TagId field is required." id="TagId" name="TagId" type="hidden" value="" />
<div class="editor-label"><label for="Name">Name</label></div>
<div class="editor-field"><input class="text-box single-line" data-val="true" data-val-length="The field Name must be a string with a maximum length of 20." data-val-length-max="20" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" /> <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span></div>
...
</fieldset>
</form>
The problem is that TagId validation gets generated althoug thare is no Required attribute set on TagId property. Because of that I can't even pass the client-side validation in order to create new Tag in db.
What am I missing?
I found the answer. Just add this to Application_Start:
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
Make the view-model value-types nullable. Then they won't be Required by default.
Note also if you put the attribute 'required="false"' in html 5 (if you set html 5 in your doctype meta data), it will see "required" and make it required. You can use dojo-data-props="required:false".
frennky's solution only removed data-val-required but in my case I still had data-val-number and data-val
I had to add the two lines below to Application_Start to get rid of everything.
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
The problem is that the value of the hidden field is empty. This shouldn't happen if you use integer type. I suppose that the TagId property is defined as a nullable type in the Tag class. So either assign it a value before rendering the view or use an integer type:
[MetadataType(typeof(TagValidation))]
public partial class Tag
{
public int TagId { get; set; }
public string Name { get; set; }
}
so that the generated hidden field looks like this:
<input
data-val="true"
data-val-number="The field TagId must be a number."
data-val-required="The TagId field is required."
id="TagId"
name="TagId"
type="hidden"
value="0"
/>
Also normally client side validation shouldn't be triggered for this hidden field.
jquery validate target cheking "disabled" html attribute.
$(function () {
$("#TagId").attr("disabled", "disabled")
});
or use Nullable.
hope this code!
With MVC4 you can also use this:
#{ Html.EnableClientValidation(false); }
#Html.EditorForModel()
#{ Html.EnableClientValidation(true); }
Make your Model or View-Model property value-types "nullabel". This will solve your problem.One important thing that remove "required" attribute from your tag otherwise it will take i "required"
Example:-
public class ViewModle
{
public int? foo{get;set;}
}
Here in example foo is integer nullable type, this will no longer required in mvc.
Hope this will help you.
I had the unfortunate experience that my model attributes were suddenly required causing my web APIs to return 400 errors when attributes were missing from web requests.
I found out this was caused by an accidental change of the "Nullable" setting in the project (Project properties -> Build -> Nullable: Enable"
After changing Nullable to Disable, all was good again.
I found a more detailed explanation of the issue here:
https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-contexts

Resources