In my web app i have service layer responsible for all logic (like registering, etc.). I wanted to implement server-side validation for my forms. The thing is i can't just throw an exception every time i catch invalid data, because if user typed incorrect email AND password, my service method would just throw exception as soon as it checks email, and password error would be noticed only after user corrected email and resubmitted form. I want my entire form validated at once. The important thing is: i need only to pass error types, display messages must be added to ModelState in controller. I have some ideas and i would like you to help me decide which one is better from performance and good-practice point of view (maybe none - maybe there is another solution superior to all posted by me).
Ideas:
Collect errors in a dictionary and then throw single exception
containing all model errors in form of key-value (ex. "Password", "Must
be >5 signs"). In controller i catch error, and read all entries using switch() to detect error type and add proper message to ModelState.
Pros: uses built-in Exception.Data dictionary
Cons: need to decipher error type from the string
Similar to previous, but i create custom exception class, which has additional field-enum dictionary (ex. "Password", ValidationEnum.LessThanFiveSignsError).
Pros: Enums are more elegant solution for switch() operations
Cons: need to implement custom exception to do something that built-in exception class could do actually
Custom exception with dictionary, but with exceptions instead of enums - i create classes like StringTooShortException and UsernameAlreadyExistsException and add them to dictionary (ex. "Password", new StringTooShortException()). Switch would probably need to check type object...
Pros: i use exceptions? the more i think about it the more i believe this is not a good idea...
Cons: pass objects Exception subclass (with all Exception class attributes and stuff) and only use information of what type is that object?
Make my every service method return custom class containing {object regularReturnValueDependingOnMethod, MyCustomErrorContainer canBeListOfEnumsOrSomething}. Basic difference between this and previous ideas is that i don't throw an exception just to carry my error container up to controller, i use proper workflow.
Pros: doesn't throw exception, just returns validation errors to controller, uses proper workflow to pass values
Cons: isn't it too much to wrap return value of every method just to pass validation errors back to controller? maybe validation error is exactly the kind of situation, where i should use exception to carry a message to controller (whatever that message could be: a text string or, in this case, an entire object)
Don't wrap return value, just create validation error container in controller and pass it to service as "out" parameter
Pros: simple
Cons: need to create error container instance before calling any service method (ok, just ones which validate input). is it elegant?
What do you think? Which one is best? I'm not interested in just getting it done. I want to get it done the way it should be done. I want to learn good programming behavior :)
Thanks for any help :)
//edit:
My latest thought: I could create another service method just for validation purpose (ex. method: RegisterUser() for registration, and ValidateRegisterUser() for model validation, i would just have to make sure to call validation method before i call regular method. What do you think?
Related
I'm new to FluentValidation and am trying to create a validator that accepts some context/parameters at validate time. I've created a custom validator and in the constructor I have something like:
RuleFor(request => request.someField).Custom((request, context) => {
var foo = context.ParentContext.RootContextData["someDependency"];
});
And in the calling code I do:
var validator = new FooValidator();
var context = new ValidationContext<SomeRequest>(request);
context.RootContextData["someDependency"] = someDependency;
validator.Validate(context);
which causes:
System.Collections.Generic.KeyNotFoundException: The given key 'someDependency' was not present in the dictionary.
Any ideas? The reason I want to pass in some context parameters is that they come from the database. If I instead pass that into the validator constructor, then by the time the validate method is called, those context parameters might be out of date. I also don't want to do the fetching from the database in the validator constructor as I will also need to fetch the same data before/after the validate method is called, and database caching is not possible in this scenario, so I'd like to avoid the unnecessary database roundtrips. I've read and am doing what seems to be the same as what is described https://docs.fluentvalidation.net/en/latest/advanced.html#root-context-data
As mentioned in my OP comment, the code looks sound but it's likely failing at the MVC validation pipeline stage and never makes it to your Validate invocation. With the former as it stands you've not added your dependency to the dictionary so it barfs.
There's probably a couple of ways to solve it. My first thought would be to introduce a rule set so this rule only executes server-side as part of your Validate invocation. There's a whole section on rule sets in the doco which covers it pretty well. You may need to combine it with a CustomizeValidator attribute so that the rule set doesn't get executed in the MVC validation pipeline (I've never had to when using a server-side rule set but I've mentioned it for completeness).
The nice thing with this is that you probably won't need to change much of your existing code; you've mentioned you load a number of dependencies into the validation context so it could be a good fit.
Another methodology that looks good, but one that I haven't tried myself, would be to populate the validation context in the BeforeMvcValidation validation interceptor. The value of this option is going to depend on how you gather those dependencies and whether they are used for anything other than validation. It'd probably require more effort than a rule set based on your implementation description as well.
Problem:
I need to handle web api 2 exceptions and return a rich object with the correct status code (401 for Unauthorized, 404 for ContentNotFound, etc) and some extra information as the content. Moreover, I need the content to look like a serialized Exception object (have the message, exceptionMessage, stackTrace, ... properties).
Suggested Solutions:
Create custom exception classes and writing a custom exception filter to apply to any controller's action. this custom exception filters handles the exception thrown according to it's type (one of the custom exceptions that I've already defined) and responds accordingly via something like this (filter's code):
context.Response = context.Request.CreateErrorResponse(HttpStatusCode.Unauthorized,
new Exception("my exception")));
wrapping the already written web api 2 *ActionResult classes ( System.Web.Http.Results.UnauthorizedResult Unauthorized(), System.Web.Http.Results.OkResult Ok(), etc ) and adding some custom data to them and use them so that their result get passed to client every time they're called (the problem is in this case my controller's action's return type should be IHttpActionResult which is not as easily testable and readable as a strongly typed action).
What solution should I choose? Or is there any other way to do what I'm trying to achieve here?
Or you could use the built-in, out-of-the-box solution: exception filters.
Furthermore, you may be interested on exception handling starting from Web API 2.x.
From what I understand you don't want to handle exceptions thrown by the code, rather create them in your action methods. For the case where exceptions are thrown by other areas in the code (other things you call inside your actions or by other filters, you can either use exception filters or global error handling).
Hence I would go with your second approach (though you don't need to customize the action results much). Your code is actually a lot more easy to unit test with IHttpActionResult, because you can inspect the result type directly. In fact one of the reasons IHttpActionResults where added is to simplify unit testing.
The flow of your code is simpler as you don't need to throw to generate errors, and you can always inspect the content of an ok(returnValue) as you can see below.
[TestMethod]
public void GetProduct_ShouldReturnCorrectProduct()
{
var testProducts = GetTestProducts();
var controller = new SimpleProductController(testProducts);
var result = controller.GetProduct(4) as OkNegotiatedContentResult<Product>;
Assert.IsNotNull(result);
Assert.AreEqual(testProducts[3].Name, result.Content.Name);
}
http://www.asp.net/web-api/overview/testing-and-debugging/unit-testing-with-aspnet-web-api
I am now working on an existing asp.net MVC application which has a few submit button in one web page(e.g. ignore, delete, update, submit...) And they all send a post request to the server and the server will perform different operation based on the request action type (e.g. ignore, delete, update, submit).
However, an issue is raised that the model validation will always triggered regardless of the operation. According to the business rule, we only need to perform validation for some certain operations. I can clear the error in the modelstate after the validation. (for example MVC3 Remove ModelState Errors).
However I am hoping there is a better way to just bypass the model validation according to the operation parameter from the client.
BTW: I am not allowed to significantly change the way how it works (e.g. send to another action for those operation that does not care about the validation), so I am hoping there is some trick that I can use to achieve this easily.
I assume now you are checking model state errors like...
if (ModelState.Valid)
{... valid and do something...}
If so, you can include some additional checking before hand that will be considered in your conditional. For instance, if it is a delete submit, you can check that before hand.
bool isDelete = ***check some value***
if (isDelete || ModelState.Valid)
{... valid and do something...}
This way even if the model state is invalid, it will still move forward.
One thing to consider is you will need to set something in the model to tell you what action is happening. This probably means using javascript to capture the submit, set a model field, and then perform the submit.
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.
Since I am trying to learn WPF I see more and more the use of the interface IDataErrorInfo to bind the error to the interface. My problem is that I usually put the validation of the data in the setter of the property and not in a method like IDataErrorInfo.this[string columnName]... Here is a blog I have found that have make me confuse.
What is the good way to proceed in .Net 3.5 to validate data object? Do I need to implement validations in method called by the Setter AND the IDataErrorInfo? Or just the IDataErrorInfo? Or in the setter call the IDataErrorInfo?
Example: I have a firstname string that can have only 3 to 50 chars. Do I put the string validation in the setter (What I would do usually) or now I can simply use the IDataErrorINfo.this method, check the property name and return a String Error when the data is not the good length? I found more intuitive to throw an error in the setter and not using the Interface but most example I see use the IDataErrorInfo interface.
If you throw an exception in the setter, then IDataErrorInfo is redundant since it can't (in theory) get into an illegal state. IDataErrorInfo allows you to accept all input, but tell the user that there is a problem. The nice thing about this is that it allows less interruption to the UI (as the user can continue to enter data even though one field is in error and marked as such), and it is easy to report multiple errors at once - visually, rather than by message-boxes etc.
However, if you go this route you need to be sure to validate that the object is OK before saving it to a database, etc.
You could do this by checking .Error from your business logic (and check that it is null/empty), assuming that you write .Error to report all errors. Or a similar Validate() method.
I believe that the IDataError allows for a much richer user experience. Like Marc said, it allows less interruption, especially when editing a grid eg. a list of Customer objects.
I recommend you download the CSLA.net framework from www.lhotka.net, developed by Rocky Lhotka (He is the author of Expert C# 2008 Business Objects). This framework supports validation rules and each business object implements the IDataError. Each time a property is changed, the rules for that property are validated. If the property value is invalid, the object state will become InValid, causing a exception to be thrown whenever the Save() method is invoked.
His framework also supports n-level undo. When you start editing a business object, a snapshot of the object is taken (including the broken rules). So if you decide to rollback your changes, the state of the object returns to the previous state - even the broken rules!