With MVC stuff when there is an error on property level, we can add error to ModelState
but the same error is added to the summary also. How can we avoid to display it twice.
I want to display only public errors in the message summary and all other at property level.
Regards
Parminder
When defining your validation summary set the first parameter to true which means Exclude Property Errors.
Eg:
<%= Html.ValidationSummary(true, "Unable to save item. Please correct the errors and try again.")%>
From MSDN:
excludePropertyErrors Type: System.Boolean
true to have the summary display model-level errors only, or false to have the summary display all errors.
Related
I am quite new to ASP.Net and so am quite unsure of a lot of things and learning as I go. In one of the forms I have made I have validated the fields, and if the data is not of the correct format I throw an error as below.
If the data is ok then it shows the graph as below.
The problem I am having is if the user then changes the fields and they throw and error I can't seem to remove the table, and so the error appears below the table.
I can't put table.visible = false in the method that creates the table as I am assuming the error from the validator prevents that method from running. For the same reasons I can't seem to put it in the is postback method either. I am wondering if there is a way to do this where I can check whether the validator has caught an error and turn the table visiblity to false?
So theoretically:
if (validatorCaughtError == true)
{
table.visiblity = false;
}
Using MVC5, I have a model with an int value that is not nullable and should not be nullable, however I do not want the model binder to automatically require that field (the view is bound to a List<> and any one item in the List may be left empty and therefore not saved to db) so I am setting the following in Application_Start():
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
This works fine when my view is initially displayed, but when the user clicks Save, all validation passes, the Controller Action then does additional cross-record validation (total across records must equal 100 for instance). If that validation fails, I then set a custom error and return the view:
ModelState.AddModelError("", "Total Allocation must equal 100%.");
return View("Shipment", shipment);
Once that total amount is corrected, the user again clicks Save, and now the implicit Required validation starts occurring on the client-side and never sends the HttpPost back to the Controller correction: the implicit validation occurs on the server side, not client side. That's the same implicit validation I turned off in Application_Start (I checked in debug mode and it's still false when the View returns with the error).
Is this a bug with AddImplicitRequiredAttributeForValueTypes or am I doing something wrong?
TIA
-VG
I found a work-around, which I wouldn't call a "resolution" but at least it is a work-around in case someone else finds this helpful. At first I thought the implicit validation was happening client-side, but no, it does make it into the Controller but ModelState.IsValid is now false. This is important because my work-around relies on control being sent to the controller. Here is what I did:
//Remove implicit validations
foreach (KeyValuePair<string,ModelState> stateItem in ModelState)
{
if (stateItem.Key.Contains("AllocationAmount"))
{
if (stateItem.Value.Errors.Count > 0 && stateItem.Value.Errors[0].ErrorMessage.Contains("required"))
{
stateItem.Value.Errors.RemoveAt(0);
}
}
}
//Check Validation
if (!ModelState.IsValid)
{
return PartialView("pvShipment", shipment);
}
By checking for that specific column having a "required" error message and removing it before checking ModelState.IsValid, the IsValid will now return true (as long as no other errors exist of course), and is able to continue on with the save logic. I hope this makes sense.
-VG
I have an auditing system in place that is failing when form values contain HTML.
I have added the [AllowHtml] attribute to the model property in question, and have tried adding [ValidateInput(false)] to the controller action, as well as using the Unvalidated() extension method on HttpRequestBase.
None of this is preventing the error. The line of code it fails on (in the auditing code, OnActionExecuting() of the derived ActionFilterAttribute) is:
return Json.Encode(new { request.Cookies, request.Headers, request.Files, request.Form, request.QueryString, request.Params });
Error is:
A first chance exception of type
'System.Web.HttpRequestValidationException' occurred in System.Web.dll
Additional information: A potentially dangerous Request.Form value was
detected from the client (Note="<p>test</p>").
"Note" being the model property with [AllowHtml] on it.
Any ideas on how I can prevent this?
It's important to understand the order of operations in the ASP.NET MVC pipeline. Your OnActionExecuting method gets called before the action in your controller even begins. If your controller action hasn't executed, that means your ValidateInput annotation isn't being considered. It also means the model binding hasn't taken place, so your AllowHtml annotation isn't considered. At this point, you've just got access to the basic Form collection, and when you try to access the data by serializing via Json.Encode() the security protection of ASP.NET is still kicking in.
To solve the issue you could either disable request validation entirely in the Web.config (not recommended), or give your JSON serialization more attention. To do so, you will have to call Unvalidated() when unwrapping the value of the property:
return Json.Encode(new {
request.Cookies,
request.Headers,
request.Files,
new {
Note = Request.Unvalidated().Form["Note"]
//Add any other properties you care about here
},
request.Form,
request.QueryString,
request.Params
});
Say I have a model property like this:
[Range(1, 31, ErrorMessage = "O dia de fechamento deve possuir valores entre 1 e 31")]
public int DataInicial { get; set; }
Even with a custom error message set on the annotation, I'm still getting the default error message for the Range annotation "Please enter a value less than or equal to 31.", when I type something like "32" or more at the #Html.TextBoxFor(model => model.DataInicial) field.
I'm aware of this post, but I think if you can set custom messages at annotation level, It should work without setting an App_GlobalResources and a .resx file, setting third-party libraries or whatever... I know that adding a .resx file and put all those validation strings there, is a "best-practice", but...
So, where I could be wrong, since the messages are not showing correctly?
Thank you in advance.
I was running into the same issue and experimented a little. Just learning MVC myself and it wasn't too obvious, but the solution seems nice and makes sense. The issue just comes down to which validation attribute gets triggered.
I found ErrorMessage is specific to the validation it is associated with.
A simple example should make it real clear...
[Required(ErrorMessage="xxx may not be blank.")]
[Range(0.0,1000.0,ErrorMessage="The value entered must be 0 to 1000.00")]
public virtual double xxx () // snip...
If empty, upon validation you will get "xxx may not be blank". While a value has been entered but not valid you should see the other error "The value entered...".
In my model I have a particular field that is annotated in the following manner:
[DataType(System.ComponentModel.DataAnnotations.DataType.Text)]
[RegularExpression("[0-9]{1,10}", ErrorMessage = "The stated Attempt Id is invalid!")]
public long? AttemptId { get; set; }
When I enter incorrect data in the Attempt ID it is giving me the following error message in the Model State:
The value 'cbcbxcb' is not valid for AttemptId.
I have other field with similar error messages but they're of type string instead of long? and the correct error message is being displayed in those cases when an invalid value is given. Why isn't the message for the 'long?' being used? I'm displaying my errors using the folowing literal tag in the page.
<%: Html.TValidationSummary() %>
EDIT: I have attempted to change the validation in the model to the following:
[Required(ErrorMessage="The stated Attempt Id is invalid!", AllowEmptyStrings=true)]
This however is still incorrect. Firstly, I need to allow the field to be left empty, and when I do it's giving me the 'The stated Attempt Id is invalid!' error message. Secondly when I do enter invalid data in the field it's reverting back to its old bad error message.
The RegularExpression validation attribute only works with string types. To get a custom error message, use the Required validation attribute instead and put your own custom error message in.
If your model parameter isn't mandatory, you could perform the validation within the controller and add your own custom message using the ModelState.AddModelError method - this is a bit of a hack, though.
its probably the fact that MVCs binding can't even cast the input value into the correct type, so it already knows the value must be invalid.
You should be using FluentValidation
The built in validation stuff using attributes is brittle and nasty - to say the least.