I know that i from Application_Start can ActionFilterAttribute add a custom global filter and manipulate the ModelState and what not.
Is there a similar way, to access the #Html (HtmlHelper) Before it get's send to the view?
The reason for this is that i want to edit (or remove and recreate) the UnobtrosiveValidationAttributes. And if i try to do that in the View like this: #Html.GetUnobtrusiveValidationAttributes("PhoneNumber").Clear(); Nothing happens, but i'm thinking it might would work if i got to it earlier?
(If you are wondering why: i need to translate the ErrorMessages inside)
I'm not sure if there are ways to intercept where the unobtrusive validating code is assigning the message text. I'm not sure that it's the best idea either because one property could have many different validations (Required, Regex, StringLength, etc...)
I can tell you there are other ways to localize error messages though. One way that works out of the box is to use resource files and to define a resource key instead of an error message.
[Required(ErrorMessageResourceName="resource-key")]
public string PhoneNumber { get; set; }
Another way that works but requires writing more code is to create your own custom validators that retrieve your error messages from wherever they are stored. I had to recently do this because all of our localization happens in the database.
Related
I'm currently working on a large project involving Sitecore CMS (7.2). For viewmodel validation we are using FluentValidations. Because of the combination of Sitecore and FluentValidations I seem to be running in some kind of technical deadlock. I sort-of found a solution myself, but I'm not sure whether this is the right approach or not. Here's the problem:
Situation
There is a Sitecore component which contains a HTML form. Via the modelbinder each value of this form is binded to it's corresponding field in the (complex) viewmodel. This is standard .NET MVC approach.
However, some values in the viewmodel are NOT part of the form. For instance, a date at which the mutation will be applied is calculated by the application. The user can only see this date-value as plain text, and thus can not edit it. It's still part of the viewmodel though. To make sure this value is being posted back to the model in code, one would normally use a hidden field. But if I use a hidden field, it means that users are able to spoof that date and because some validations depend on this value, they are able to spoof the entire validity of the form.
Moreover, in the same viewmodel I have a list of complex objects that I can't simply put in a hidden field (or I should serialize it to JSON, which I don't want).
The conclusion is that I need to store this data somewhere else. Somewhere the user can't spoof it, but I'm still able to validate user input with FluentValidations. I therefore decided to put the entire viewmodel in the users Session, and delete it directly after a succesful mutation.
Problem
By using session data I run into problems. Let's first see these steps:
(GET) Viewmodel is created. Calculated date is set and list of complex types is retrieved once from a (slow) webservice.
Entire viewmodel is stored as session data.
Form is shown to the user, who fills the form. Some data is only shown as readonly, like the date and list of complex types.
User submits form, FluentValidations kicks in to validate the data (POST).
That's where I run into problems. The validation done by FluentValidations kicks in before it reaches the POST controller method. That's exactly the way we want it, because that means validation errors are automatically added to the ModelState. However, because of security reasons I don't want to add this data as hidden fields to the cshtml file, which means they are empty at the time FluentValidations is going to validate the form.
This is creating problems because some of the form validations rely on the missing data. What I basically want is to merge the viewmodel that is stored in the session with the viewmodel that was posted to the controller method. But I have to do that before FluentValidations is going to do it's work.
My current solution
Gladly, I learned about FluentValidation's IValidatorInterceptor: an interface that can be used to 'do stuff' before or after the validations process kicks in. I used the BeforeMvcValidation method to do my merging process. The code is as follows:
public ValidationContext BeforeMvcValidation(ControllerContext controllerContext, ValidationContext validationContext)
{
if (controllerContext.HttpContext.Session == null)
return validationContext;
var sessionData = controllerContext.HttpContext.Session["some_identifier"];
if (sessionData == null)
return validationContext;
var mergedObjectToValidate = Utils.MergeViewModelData(sessionData, validationContext.InstanceToValidate);
// Unfortunately, we have to do this..
var privateSetterProperty = validationContext.GetType().GetProperty(ValidationContextInstancePropertyName);
if (privateSetterProperty == null)
return validationContext;
privateSetterProperty.SetValue(validationContext, mergedObjectToValidate);
return validationContext;
}
Basically this interceptor method allows me to do my merging-process before validation. So I thought I had the solution here, but as you can see I am using reflection to set a property. That is because the property InstanceToValidate in the ValidationContext object has a private setter. I simply can not set it without using reflection. Which is, obviously, a bit dirty.
It does work exactly as I want though! :) I do not need any hidden fields that can be spoofed (which is horrible for straight-trough-processing) and I can still use FluentValidations exactly as I always did before. Also, the MVC modelbinding-process is left untouched, which I prefer.
The actual question
So the above solution works exactly as you want so what are your questions?! Well, simple:
I'm using reflection to set a private property in a 3rd party library (FluentValidations). The obvious answer is: don't go that way. But in this case it works flawlessly. If the InstanceToValidate-property had a public setter, I wouldn't even be posting this question at all: I would feel like I nailed it. But unfortunately it is private, so are there any real reasons why I shouldn't do this, maybe someone being an expert in FluentValidations behaviour?
Let's say there is a genuine reason why I shouldn't go this way; is there another approach which has the same effect? Can I hook in even earlier, so before FluentValidations kicks in, perhaps some kind of 'hook' just after the MVC model-binding process but before validation kicks in?
Is this entire approach simply wrong and should I tackle it in a completely different way?
Thanks!
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
Is there a best practice way to validate user input?
Actual Problem:
A user gives certain inputs in a window. When he is done with those inputs, he can click 'create'. Now, a pop up message should be shown with all invalid input given. If no invalid input, then just continue.
I could easily do this in the Form class. But I remember some best practice way of validating the input in the set properties. Problem is that I already created an instance of that class (or otherwise, can't set properties ;) ) if I validate this way. That should not happen, no instance of the class may be created unless input is valid.
I was planning to create a ErrorMessages class that contains a list where I can put all errorMessages. Every time an invalid input is given, a new message is added to the errorMessages list. So if user click's 'create' button, all messages in the list are shown. Is this a good way of handling things?
So is there a best practice way? Any design patterns that provide such solution?
Edit: This is a school task. So with illogical requirements. I HAVE to show all invalid inputs when I click 'create'. I would like to do this out of Form class. (So validation works even without GUI, I did't even create the GUI yet at this point). First making sure my functionality works correctly ;). I want to keep my code clean, abstract and OOP. So how should I show my error messages?
I was planning to create a ErrorMessages class that contains a list where I can put all errorMessages. Every time an invalid input is given, a new message is added to the errorMessages list. So if user click's 'create' button, all messages in the list are shown. Is this a good way of handling things?
Subjectively, I think it would be better to provide instant feedback that the value the user entered is invalid. That way, they can immediately go back and fix it.
I mean, think about it. The approach you propose would literally give them a giant list of problems at the end, which is not very user-friendly. Besides, how are they going to remember all of those problems to be able to go back and fix them one at a time? (Hint: they're not.)
Instead, I recommend using the ErrorProvider class to display any errors right next to the appropriate control. I talked a little bit more about this approach in my answer here and here.
Of course, you'll still need to make sure upon final submission (clicking the OK/Submit button) that all the input is valid, but then that's just a simple case of checking for the presence of any errors.
I could easily do this in the Form class. But I remember some best practice way of validating the input in the set properties.
Yes, the idea here is encapsulation. The Form class should only know about form stuff. It shouldn't be required to know what kind of input is/is not valid for all of your different controls.
Instead, this validation logic should be placed elsewhere, such as in a class that stores your data. That class would expose public properties to get and set the data, and inside of the setter method, it would verify the data.
That means that all your Form has to do is call a setter method on your data class. The Form needs to know nothing about how to validate the data, or even what the data means, because the data class handles all of that.
That should not happen, no instance of the class may be created unless input is valid.
If this is indeed the case, you will need to provide a constructor for the class that accepts as parameters all of the data it needs. The body of the constructor will then validate the specified data and throw an exception if any of it is invalid. The exception will prevent the class from being created, ensuring that no instance of a class that contains invalid data ever exists.
Such a class would probably not have setter methods at all—only getters.
However, this is kind of an unusual requirement in the world of C# (however common it may be in C++). Generally, placing your validation code inside of the setters works just fine.
My properties have some private setters. So they only get set in the constructor of my data class. Problem is now that this seems to make my validation not eassy
Why would that change anything? You still handle the validation inside of the private setters. If validation fails, you throw an exception. Because the constructor doesn't handle the exception, it continues bubbling up out of that method to the code that attempted to instantiate the object. If that code wants to handle the exception (e.g., to display an error message to the user), it can do so.
Granted, throwing an exception in the case of invalid input is not necessarily a "best practice". The reason is that exceptions should generally be reserved for unexpected conditions, and users screwing up and providing you with invalid data is, well, to be expected. However:
This is the only option you have for data validation inside of a constructor, because constructors can't return values.
The cost of exception handling is basically negligible in UI code since modern computers can process exceptions faster than users can perceive on-screen changes.
This is a simple requirement but sometimes being debated. This is my "current" approach how to deal with validation. I have not yet used this approach, and this is just a concept. This approach need to be developed more
First, create a custom validation attributes
public class ValidationAttribute : Attribute{
public type RuleType{get;set;}
public string Rule{get;set;}
public string[] RuleValue{get;set;}
}
Second, create a custom error handler / message
public class ValidationResult{
public bool IsSuccess{get;set;};
public string[] ErrorMessages{get;set;};
}
Then create a validator
public class RuleValidator{
public ValidationResult Validate(object o){
ValidationResult result = new ValidationResult();
List<string> validationErrors = new List<string>();
PropertyInfo[] properties = o.GetType().GetProperties();
foreach(PropertyInfo prop in properties){
// validate here
// if error occur{
validationErrors.Add(string.Format("ErrorMessage at {0}", prop.Name));
//}
}
result.ErrorMessages = validationErrors.ToArray();
}
}
To use it, then you can do like this:
public class Person{
[ValidationAttribute(typeof(string), "Required", "true")]
public string Name{get;set;}
[ValidationAttribute(typeof(int), "Min", "1")]
public int Age{get;set;}
}
To call the validator
public void ValidatePerson(Person person){
RuleValidator validator = new RuleValidator();
ValidationResult result = validator.Validate(person);
// generate the error message here, use result.ErrorMessages as source
}
What is the advantage:
You can use in any application platform (Winforms, Asp.Net, WCF,
etc)
You can set the rule in attribute-level
It can do automated validation
This approach can be used with DependencyInjection with custom
validators to separate validation logics
The disadvantage:
Hard to create the validators
If not handled well, the validators can become very large in number
Bad performance due to use of reflection
See the ErrorProvider class (documentation here). It provides a set of standard visual indicators that can be attached to most of the standard WinForms controls.
There are several possible approaches:
Use "instant" validation.
When user enters value it is checked during input (TextChanged) and validated right away. Create instance of a new class, call property/method what should accept string and return bool (or throw Exception in case of property), on false - draw special error condition (red label next to text box, something blinking, ErrorProvider or whatever you can do what should tell user "wrong!").
This one I like to use, but a bit differently, usually I only check Type and then just trying to parse it straight away in the form. It is possible to abstract more if form operate with the string's and all formattings and validation occurs in the class (property setters). Or you can supply form with additional information (by using query methods or attributes) so it can do instant validation without need to instantiate class or using setters. As example, double factor property can be identified in the form (or even control) to perform 'double.Parseand you can have attributeDefaultValuewhich can be used to display to the user value in the different way when it's different from default (like it is done byPropertyGrid`).
Use normal validation.
When user finished input, validate (by trying to set value and catching exception), if wrong - user can't "leave" or "progress" until he press ESC (to cancel changes) or correct his input to pass validation.
This one I dislike. Idea of holding user annoy me (and user ofc). Also it is hard to implement cross checks (like if you have Min and Max values, then user will be pushed to increase "right" one first, otherwise invalidation will fail).
Use "ok" validation.
That just means let user to enter everything and only validate when he clicks "Ok" button.
I think combining "Ok" button and interactive instant validation is the best for the user. As user knows where he made a mistake through input, but still is free to browse and only will get a "slap" from validation after clicking "Ok" button (at which step you can simply show him first of errors he did, not necessary to show them all).
Error messages can be provided by setters in the old-fashion LastError way or as a text in the Exception.
I'm using MVC2.
Whats the recommended way of server side validation of forms when using knockout?
Currently, most of my forms are in partial views, which have a C# ViewModel with Validation Attributes. Something like this:
public class SomeThingViewModel
{
[Required]
public string Name { get; set; }
[Required]
public int Number{ get; set; }
}
So when the form gets submitted to the server, I get all the model errors and I can return the form with errors, which are displayed with something like: <%: Html.ValidationMessageFor(m => m.Name)%>. This is then reloaded into the element that holds the form on the main page so that the user can see the errors. This would kill any bindings I had with the form in knockout I would assume.
I'm not really sure how to go about this using knockout.
This can be tricky, but done right works like a breeze.
First, synchronize your viewmodels. What you have client-side in knockout you pass exactly to the server. Second, don't do server-side HTML with knockout. Create fields that are set server-side and read client-side that indicate the validity of each data field in your ViewModel.
So if your Model has a field Name, your ViewModel has Name and Name_ValidationResult, which is an enum that indicates whether or not the Name field is valid and why it's not. If your server-side validation fails, set your validation result fields and pass the whole server-side ViewModel back to the client to be re-set as the client-side ViewModel after the request completes. Basically, you a re-creating the ViewState portion of ASP.NET, but doing so in a format that will work with Knockout.js
On the client-side, you have error messages that only show based on values of the ValidationResult fields. So you might have a canned error message that states "The Name field must be set" that is only displayed if Name_ValidationResult has the value "Empty" (for example).
Basically, you actually use the MVVM pattern with a minor tweak to account for having to round-trip to the server.
So you are suggesting that I add ValidationResult fields in my C# ViewModel for each property. Then set the ValidationResult Properties in my controller when I check for the Model's validity. Then pass back the viewmodel as JSON? so that I can update my knockout viewmodel. This will require me to manually validate to some extent right? Or can I leverage the ModelState errors that I will end up with? – Blankasaurus
Bottom line is yes to all your questions.
In truth, I missed the fact that you were using DataAnnotations for your validation, or I'd have mentioned it. You should be able to leverage ModelState errors to set your validation results that you pass back to your knockout page.
The problem is that you're using two fundamentally incompatible technologies and hoping they'll play nice together, and I don't think that's going to work out the way you hope. Something is going to have to give, and I suggest that the best point for that is server-side. Drink the knockout cool-aid and fix what you have to server-side.
I'm building a driver's application for employment and I'd like the list of 'accidents' to be dynamic in the sense of only one field appears, but they can add however many they need and once added they appear in a table above the input..
I'm trying to find out what the best way to do this is in a MVC3 Form that is using Razor syntax?
Model has a declaration similar to...
public class FormModel {
...other properties
public IEnumerable<AccidentDetail> AccidentDetails { get; set; }
...other properties
}
This is very much shortened, but wanted to ensure that I was declaring it properly in the model and then I need to know how it's generally handled in the Form to do something like this. I can't make any assumptions to the existence of an accident or the limit of how many they may have.
I personally would approach this with some JavaScript. In particular, I'd use jQuery to add a new field to the table when a button is clicked to "Add another accident". You can use jQuery to grab the values of the fields into an array. The array of accidents would be serialized to json and stored in a hidden field on the form that would be submitted to the server. In your controller you could deserialize that string of json to your strong type. On the server side I've used Json.NET with great success. On the client side you can use Doug Crockford's json2.js. Feel free to email me if you need a little bigger push in the right direction.
I'm wondering how others deal with trying to centralize MessageBox function calling. Instead of having long text embedded all over the place in code, in the past (non .net language), I would put system and application base "messagebox" type of messages into a database file which would be "burned" into the executable, much like a resource file in .Net. When a prompting condition would arise, I would just do call something like
MBAnswer = MyApplication.CallMsgBox( IDUserCantDoThat )
then check the MBAnswer upon return, such as a yes/no/cancel or whatever.
In the database table, I would have things like what the messagebox title would be, the buttons that would be shown, the actual message, a special flag that automatically tacked on a subsequent standard comment like "Please contact help desk if this happens.". The function would call the messagebox with all applicable settings and just return back the answer. The big benefits of this was, one location to have all the "context" of messages, and via constants, easier to read what message was going to be presented to the user.
Does anyone have a similar system in .Net to do a similar approach, or is this just a bad idea in the .Net environment.
We used to handle centralized messages with Modules (VB). We had one module with all messages and we call that in our code. This was done so that we change the message in one place (due to business needs) and it gets reflected everywhere. And it was also easy to handle change in one file instead of multiple files to change the message. Also we opened up that file to Business Analysts (VSS) so that they can change it. I don't think it is a bad idea if it involves modules or static class but it might be a overkill to fetch it from DB.
HTH
You could use resource files to export all text into there (kinda localization feature as well). Resharper 5.0 really helps in that highlighting text that can be moved to resource.
Usually it looks like this:
Before: MessageBox.Show(error.ToString(), "Error with extraction");
Suggestion: Localizable string "Error with extraction"
Right click Move to Resource
Choose resource file and name (MainForm_ExtractArchive_Error_with_extraction), also check checkbox Find identical items in class ...
Call it like this MessageBox.Show(error.ToString(), Resources.MainForm_ExtractArchive_Error_with_extraction);
Best of all it makes it easy to translate stuff to other languages as well as keeping text for MessageBox in separate Resource. Of course Resharper does it all for you so no need to type that much :-)
I suppose you could use a HashTable to do something similar like this, this can be found in:
using System.Collections;
To keep it globally accessable i was thinking a couple of functions in a class holding the hashtable to get/set a certain one.
lets see now.
public class MessageBoxStore
{
private HashTable stock;
public string Get(string msg)
{
if (stock.ContainsKey(msg))
return stock[msg];
else
return string.Empty;
}
public string Set(string msg, string msgcontent)
{
stock[msg] = msgcontent;
}
}
or something like that, you could keep multiple different information in the hashtable and subsequently compose the messagebox in the function too.. instead of just returning the string for the messagebox contents...
but to use this it would be quite simple.
call a function like this on program load.
public LoadErrorMessages()
{
storeClass = new MessageBoxStore();
storeClass.Set("UserCantDoThat", "Invalid action. Please confirm your action and try again");
}
for example, and then.
MessageBox.Show(storeClass.Get("UserCantDoThat"));
i put this in a new class instead of using the HashTable get/set methods direct because this leaves room for customization so the messagebox could be created in the get, and more than 1 piece of information could be stored in the set to handle messagebox title, buttontype, content, etc etc.