Is it possible to display all validation messages at once? - c#

In my cshtml file I have the lines
#Html.ValidationMessageFor(m => m, "{{dict.err_comb_cluster}}", new { #class = "text-danger" })
#Html.ValidationMessageFor(m => m.WarnMailAddress, "{{dict.val_req_err_alarm_email}}", new { #class = "text-danger" })
#Html.ValidationMessageFor(m => m.EmailToSendTo, "{{dict.val_req_err_email}}", new { #class = "text-danger" })
This has the effect that if there is an error concerning the WarnMailAddress or the field EmailToSendTo, the validation message for it will be displayed, but if at the same time there is an error concerning the whole model (that triggers "m => m"), the validation message for this error will not be displayed. It will be only displayed as soon as the other errors have been corrected. In other words, there is a hierarchy of the validation messages.
What we want to achieve is to display all the validation messages at once, ignoring this hierarchy. I've extensively used Google to find possible answers to my question but found none.
Additional information: The validation for the entire model is made using a custom attribute. We defined:
[MetadataType(typeof(CLUSTER_Validation))]
[CustomValidation(typeof(ClusterUniqueAttribute), "IsValid")]
public partial class CLUSTER: VMIEntityObject<CLUSTER>
{
and
public class ClusterUniqueAttribute : ValidationAttribute
{
public static ValidationResult IsValid(CLUSTER cluster)
{
The attributes for the properties are defined inside the class CLUSTER_Validation, and this looks like:
[Display(Description = "Email-Adresse", Name = "Email-Adresse", Order = 15)]
[RequiredIf("isSendMaiImmidiately", true, ErrorMessage = "If alarm email has been activated, an email address must be provided")]
public string WarnMailAddress { get; set; }

Related

Custom validation attribute's ValidationContext is missing a field

I'm working in MVC 5. I'm writing a form for users to submit claims to an internal application, and I need to validate the user's claim amount against their current balance when they create a claim. It rejects if the amount is greater than the balance, say $10 vs. $5, and asks them to zero out their balance instead.
I felt it would be best to have the balance be a (non-editable) property, CurrentBalance, on the viewmodel with a custom validation attribute comparing the two values. I render it as a readonly field on the form. When the user picks which program they are submitting to, like their HRA, an ajax request fills in their current balance per which program they selected.
The trouble is that when the viewmodel instance is passed as part of the ValidationContext to my attribute, CurrentBalance always appears as zero. Here's a snip while debugging: https://i.imgur.com/syDEuJ2.png
So no matter what the balance is, validation fails without exception.
I've tried making CurrentBalance an ordinary, non-readonly field on the view and setting the value myself before submitting. I've also tried setting the value in my controller before rendering the view. In either case, it's still zero, as in the image above.
My custom attribute is as follows:
public class ClaimAmountAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var claim = (ClaimCreateViewModel)validationContext.ObjectInstance;
var amount = (decimal)value;
if (claim.CurrentBalance - amount < 0)
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
public string GetErrorMessage() => "Amount must be less than balance; please zero out balance instead.";
}
Here are the relevant parts of my view—though again, it didn't seem to make a difference whether the readonly attribute was there or not:
#model ClaimCreateViewModel
<div class="form-group">
#Html.LabelFor(model => model.CurrentBalance, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CurrentBalance, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Amount, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Amount, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Amount, "", new { #class = "text-danger" })
</div>
</div>
Finally, here's a snippet from the viewmodel:
public class ClaimCreateViewModel
{
[Key]
public int TransactionID { get; set; }
// ...
[Required]
[ClaimAmount] //my custom attribute
public decimal Amount { get; set; }
[Display(Name = "Balance")]
public decimal CurrentBalance { get; set; }
// ...
}
Seemingly nothing I do produces the value of CurrentBalance in the ValidationContext. Please help me out.
Well, this is embarrassing. It turns out that the [Bind] attribute on my POST action was missing CurrentBalance. Validation occurs before the action, but that doesn't matter; [Bind] is acting before then, to prevent overposting. I've updated that action and it works now:
public ActionResult Create([Bind(Include = "TransactionID,Amount,CurrentBalance")] ClaimCreateViewModel claim)
{
// ...
}

Create dynamic fields in asp.net mvc

I have table user with fields in additional custom fields for user that added by admin.
sql click this to diagram explain this
so i want to create Register page with user fields and custom fields.
i get FiledType and FieldName to list.
in Controler:
public ActionResult Index()
{
ViewBag.CustomeFields = userCustomeFields.GetCustomeField();
return View();
}
UserField model:
public class UserField
{
public string FieldName;
public string FieldTypeName;
}
so i want to create dynamic fields in cshtml file.
i wrote this code:
Update:
#foreach (var item in ViewBag.CustomeFields)
{
<div class="form-group">
#*#Html.LabelFor(i=>item.FieldTypeName , htmlAttributes: new { #class = "control-label col-md-2" })*#
<div class="col-md-10">
#if (item.FieldTypeName == "Textbox")
{
#Html.TextBox(item.FieldName)
}
</div>
</div>
#*#Html.Editor(item.FieldName, new { htmlAttributes = new { #class = "form-control" } })*#
}
but i give error!
HtmlHelper<User>' has no applicable method named 'TextBox' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
i don't know is my way correct or not?!
Here again the answar to your first question, in case you want t mark it as a correct answer ^^
You have to cast it for example like this
#foreach(UserField item in ViewBag.CustomFields) {
or
#Html.TextBox(((UserField)item).FieldName)
or
#Html.TextBox((string)item.FieldName)
For the attributes you can use a anonymouse type object with new { ... }
#Html.TextBox("nameOfTheTexbox", "initialValue", new { #class ="myCssClass myOtherCssClass", disabled = "disabled" })

ASP.NET MVC Model validation ignoring inputs that have become readonly

I have a form with shipping and billing information using a view model containing some required attributes.
Here's an exctract of the code enough to explain the issue.
Extract of the view model:
public class CheckoutViewModel
{
[Required]
public string ShippingPostalCode { get; set; }
[Required(ErrorMessage = "*")]
public string BillingPostalCode { get; set; }
}
Extract of the razor form:
#Html.TextBoxFor(m => m.ShippingPostalCode, new { #class = "form-control", placeholder = "Postal code" })
#Html.TextBoxFor(m => m.BillingPostalCode, new { #class = "form-control", placeholder = "Postal code", data_bind = "attr: { 'readonly': billingSameAsShipping }" }) #Html.ValidationMessageFor(model => model.BillingPostalCode)
I use Knockout to make the billing fields (including BillingPostalCode) readonly if a checkbox is checked using the observable billingSameAsShipping variable.
<input type="checkbox" data-bind="checked: billingSameAsShipping" id="billingSameAsShippingCheckbox" />
If the checkbox is not checked, and the BillingPostalCode is left empty, the validation fires correctly.
However, if BillingPostalCode is empty but the checkbox is checked, making the field readonly, the validation is not fired and the ModelState's IsValid is having the value true.
Any clues if this expected behaviour, or ideas how to work around it?
Any help is appreciated. Thanks.
Edit: I added the JavaScript code if it helps.
var shipping = {
billingSameAsShipping: ko.observable(false)
};
ko.applyBindings(shipping);
$("#billingSameAsShippingCheckbox").on("change", function () {
if (this.checked) {
$("#BillingPostalCode").val($("#ShippingPostalCode").val());
}
});
It seems that the jQuery validator that it uses ignores readonly inputs.
I managed to fix it with this.
$.validator.setDefaults({ ignore: null });

Display validation message for multiple fields of the same model property in the same view

I've got a model field like so:
[Required(ErrorMessage = "Required!")]
[Display(Name = "Some ID")]
[DataType(DataType.Text)]
[RegularExpression(#"SomeRegexHere"]
public string someId { get; set; }
On my view, I have a form for updating the model. Something like this:
<div class="form-group">
#Html.LabelFor(model => model.someId, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.someId, new { htmlAttributes = new { type = "number", #class = "form-control" } })
#Html.ValidationMessageFor(model => model.someId, "", new { #class = "text-danger" })
</div>
Say on this same view I can fill in this field in order to submit it to the database, but I may also fill in some other field to retrieve an entry in the database by this value. However, I'd like to apply the same validations to both fields. Without creating a dummy model attribute, can I display validation errors for both fields?
As I understand form you question, you need
conditional validation. It is better to use third party validation provider for this porpose. I recommend MVC Foolproof Validation. Have a look on this and this as samples for conditional validation in foolproof.

Add required to LabelFor

I'm having the following code:
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
And I'm looking for a way to add the html attribute required to it, so a user can't submit without having the field filld. But now sure how to do? I know the easies way is to add required But don't know how, i tryed with #html "reguired" Without any luck.
EDIT:
Answere = required = ""
You can add RequiredAttribute to your model property:
[Required(ErrorMessage = "Title is required")]
public string Title { get;set; }
And add ValidationMessageFor to your cshtml:
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(m => m.Model)
Then add model validation to controller method via. It's the standard pipeline for asp.net mvc.
You also can implement your own HtmlHepler to add required attribute to your html code.
You will need this for client validation
"~/Scripts/jquery.js"
, "~/Scripts/jquery.validate.js"
,"~/Scripts/jquery.validate.unobtrusive.js"
whereas for only server side on Controller or necessary even if some disables javascript
if (ModelState.IsValid)
As above using annotation
[Required(ErrorMessage = "Title is required")]
public string Title { get;set; }
Using Fluent API
public class ClassNameConfiguration : EntityTypeConfiguration<ClassName>
{
public ClassNameConfiguration()
{
Property(x => x.Title).IsRequired();
}
}

Categories