I have a 3 layered system of presentation, logic, and data access. In my logic layer, I have a Validate() method which makes sure that the data that's about to get forwarded to the data access layer is valid for the database (no nulls where nulls are not allowed, and so on).
On top of that, in the .aspx presentation layer, we have some user-friendly error checking and validation, directly checking the controls on the web form. My problem is the ValidateInput() method in the code behind which checks the controls, it's several hundreds of lines long and really annoying to maintain. The code for checking the data is far far longer than the code that does the actual work.
What I've got looks like this:
private List<string> ValidateInput()
{
List<string> errormessages = new List<string>();
if (LastNameETextBox.Text.Trim() == String.Empty)
{
errormessages.Add("Last name required.");
}
if (FirstNameETextBox.Text.Trim() == String.Empty)
{
errormessages.Add("First name required.");
}
//etc. etc.
}
We have a nice styled notification box hidden in the master page that gets turned from Visible false to true when we call it, creating the "illusion" of an overlaying box. It looks really nice and works really well so we want to use it. The idea is that we gather up all the errors for the whole form, put them in a list, and then send that list to the notification box, which then gives you all the errors in one nice list.
But the Validate() is just a torturous amount of "if" statements and it's hard to keep track of. Is this just the nature of input validation, or is there some other, better way of handling this?
I think you can able to avoid using these kind of If statements using a Generic function.
My suggestion is to define a function like this
private List<string> ValidateInput(string ErrorMessage, TextBox txtInput, ValidatationType validationType)
{
List<string> errormessages = new List<string>();
if (validatationType == ValidationType.NoNullValues)
{
if (txtInput.Text.Equals(String.Empty))
{
errormessages.Add(ErrorMessage);
}
}
if (validatationType == ValidationType.Integer)
{
int number;
if (Int32.TryParse(value, out number))
{
errormessages.Add(ErrorMessage);
}
}
// etc. etc.
}
Enum ValidationType
enum ValidationType
{
NoNullValues,
Integer,
// etc
}
Please modify the function. Also checks the syntax, I am using notepad to write the code.
This approach also helps you to achieve re-useabilty if you are use all validation methods in a separate class.
Thanks
Couple of the different ways that I had handled it (in different projects) :
Use custom control library - controls were simply extending existing ASP.NET/3rd party controls to add validation logic which was controlled by properties such as IsMandatory, MandatoryMessage etc. Properties were typically set at the design-time (and were not backed by view-state). The validation logic would accumulate error messages in the message collection exposed by base page. Another variant had used user controls combining ASP.NET controls along with validators but frankly speaking, ASP.NET validators sucks.
Essentially a base page class had a validation logic that would traverse the control collection within the page and then perform validation based on control type. The page would offer a registry to register control to validate, type of validations and error message to display. There was also method to un-register/skip control validation that was used primarily to skip control traversal within control such as repeater/grid-view.
For client-side(browser side) validation, I had used jquery validation (or own JS library). In both cases above, the validation logic would also emit necessary start-up scripts to set-up the client-side validation - however, #2 could generate a single start-up script (with less size) while #1 entails generating a start-up script per control instance. From flexibility perspective, #1 is better and fits nicely in control based development approach. #2 centralizes your validation logic at one central place (i.e. a base page) which can be very handy.
a) Create an validation type enum to enumerate all types of validation you want to perform. (In your code you are doing string null checking for both controls which are both textboxes, its unnecessary repetition of code logic)
b) Create a class of constants / or resource file that holds all the error messages.
c) Write a function that takes a control, Validation type enum, arguments for validation and error message id. It will check the type of control and perform validation as indicated by enum. If error, error message is added to your "errorMessages" collection.
enum ValidationType{
NullCheck,
IsNumber,
RangeCheck,
....
}
class ErrorMessages{
const string FNEMPTY = "First Name is empty";
....
}
class BusinessObject{
function ValidateControl(Control cntrl, ValidationType type, object[] args, string message)
{
if(cntrl is TextBox)
{
if(cntrl as TextBox).Text.Trim() == String.Empty
errorMessages.Add(message);
}
...
}
}
Now you can call the above function on every control you want to validate. One more improvement will be to Implement a base class for all your controls that holds the corresponding error message collection in a property (Dictionary<ValidationType,String>). Then you can modify the validation function to accept an array of ValidationType enum to perform several validation in one call. Each control will give you its error message for every validation type in its property we created in the base class.
Hope this helps.
Thanks
Ven
Related
Here is a little background on the specifications of my project:
We use Specflow and Microsoft CodedUI Framework for UI Automation
I have built a PageFactory that combines three Abstract Base Classes : BasePage, BaseMap, and BaseValidator that all Maps, Pages, and Validators inherit
Our Application that we are automating has numerous workflows that make defined HTML Controls have different InnerText Values (HTMLComboBoxes for example)
Everything is and needs to be abstracted from the actual Specflow Test Code in the Page Object Pattern, no unique code can exist within a Specflow Step
In my Maps I have certain controls like a combobox that has an InnerText change if a certain workflow is selected. I need to build assertion and verification statements to make sure the InnerText is correct for the workflow that is selected. This is not a problem. However, I do not want to just define a new variable for every InnerText change(There are A LOT).
Is there any way I can account for the InnerText variations in the Page Object Pattern and not have to code a new variable for every single one?
Here is an example of a Map Entry:
public HtmlComboBox NextActionControlDropDownList()
{
var NextActionControlDropDownList = new PropertyExpressionCollection {
new PropertyExpression(HtmlComboBox.PropertyNames.Id, "MEDCHARTContent_EmmpsContent_nextActionControl_ActionDropDownList", PropertyExpressionOperator.EqualTo)
};
return Window.Find<HtmlComboBox>(NextActionControlDropDownList);
}
This is the Base Control definition. It can also be this:
public HtmlComboBox NextActionControlARFormalComplReview()
{
var NextActionControlARFormalComplReview = new PropertyExpressionCollection {
new PropertyExpression(HtmlComboBox.PropertyNames.Id, "MEDCHARTContent_EmmpsContent_nextActionControl_ActionDropDownList", PropertyExpressionOperator.EqualTo),
new PropertyExpression(HtmlComboBox.PropertyNames.InnerText, "--Select Action-- Return to USARC ", PropertyExpressionOperator.EqualTo)
};
return Window.Find<HtmlComboBox>(NextActionControlARFormalComplReview);
}
My thoughts so far were to maybe make another map and inherit it? But that wouldn't solve my initial problem of too many variables for a single control. I don't see how If statements would help either because it needs to be defined for the framework to find the control. Maybe I could store the differing values in a collection of sorts and have a parameter key value to access them... but that seems like I would run into a lot of issues.
If you try and see the methods under PropertyExpressionOperator you would see something called Contains.
new PropertyExpression(HtmlComboBox.PropertyNames.InnerText, "--Select Action--", PropertyExpressionOperator.Contains)
I have to validate three things when a consumer of my API tries to do an update on a customer.
Prevent the customer to be updated if:
The first name or last name are blank
For a certain country, if the customer's inner collection of X is empty, then throw an exception. X is hard to explain, so just assume it's some collection. For all other countries, X doesn't apply / will always be empty. But if it's a certain country, then X is required. So it's almost a conditional required attribute. A customer belongs to a country, so it's figured out from the JSON being sent.
Prevent the customer from being updated if some conditions in the database are true.
So basically i'm stuck with the following problem, and I wanted some advice on the most appropriately way to solve it:
Do I create an Action Filter to do the validation on the customer entity before the saving takes place? Or would it be better to create custom validation attribute derived from ValidationAttribute and override the IsValid member function.
Basically a question of saying
if (first name is empty, if x, if y, etc) vs (!ModelState.IsValid)
And then using IsValid to cause the custom attributes to work.
It seems like validation attributes are best for "simple" validation, i.e. required field. But once you start getting into things like "I need to look at my database, or analyze the http request header for custom values, and based on that, invalid = false" then it almost seems wrong to do this sort of stuff so close to the entity.
Thoughts?
Thanks!
I like FluentValidation a lot: https://github.com/JeremySkinner/FluentValidation
As you mentioned built-in validation attributes are limited. For complex validations you had better implement your own attributes or use a library like this.
One thing I like about FluentValidation is that it performs at model-level rather than field-level, meaning that you can use related fields' values for validation. For example
RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
(Code excerpt taken from project's Wiki page)
It's also extensible so you can develop your own custom validators on top of this library as well.
Have a few custom content-types registered via
ContentTypeFilters.Register(contentType, StreamSerializer, StreamDeserializer);
and would like to restrict the display for routes on the metadata page. These content-types are only meant to be used with request dto's which are restricted to InternalNetworkAccess. Just looking to not clutter up the public facing metadata page with stuff that isn't necessary.
For the builtin contentTypes you would just add it under the RestrictAttribute. Is there a similar feature hidden somewhere else that isn't documented yet maybe for the custom types?
It looks like perhaps I could customize the MetadataFeature plugin and possibly restrict which request dto's get the content type and which don't. But I only just recently noticed that, and not sure how well that would turn out (also don't really know yet how to remove the MetadataFeature and safely replace with my own).
Essentially I only want this custom contentType visible on the metadata page for the requestDtos restricted to InternalNetworkAccess.
Any ideas?
Edit:
Also am still on ServiceStack v3, but still interested in possibilities for v4.
You can prevent your custom type from showing up in the metadata using.
If your content type is application/yourformat you would use:
SetConfig(new HostConfig {
IgnoreFormatsInMetadata = new HashSet<string>{ "yourformat" }
});
So I found that the initial class handling the metadata requests was ServiceStack.MetadataFeature an IPlugin. This actually controls both the layout of the underlying example request/response page (for each content-type) as well as the overall "/metadata" page.
From this small segment
private IHttpHandler GetHandlerForPathParts(String[] pathParts)
{
var pathController = string.Intern(pathParts[0].ToLower());
if (pathParts.Length == 1)
{
if (pathController == "metadata")
return new IndexMetadataHandler();
return null;
}
...
}
is where the handler for the actual "/metadata" page is sent off. You don't find the actual construction of the ContentTypes per request until you get down a little further, inside IndexMetadataHandler's parent class BaseSoapMetadataHandler in the method
protected override void RenderOperations(HtmlTextWriter writer, IHttpRequest httpReq, ServiceMetadata metadata)
An internal control is created (IndexOperationsControl) which has a method RenderRow, which is where all the magic occurs. Here you'll see some obvious checks for the "Operation" (which is another word for the Dto now) and ContentType like
if (this.MetadataConfig.IsVisible(this.HttpRequest, EndpointAttributesExtensions.ToFormat(config.Format), operation))
So all that needs to be done is create your own class of IndexOperationsControl and handle the config.Format in the RenderRow method. The config.Format is simply everything after the forward slash in the ContentType you registered, so if it was "application/x-my-type" the config.Format String will be "x-my-type". Operation is simply the class name of the RequestDto. Unfortunately because the class is marked internal it means you pretty much have to copy it completely instead of using inheritance. In order to keep a 1:1 likeness with how the pages are generated by default you'll also need a copy of the internal classes ListTemplate, TableTemplate, and XsdTypes (used in construction of IndexOperationsControl).
After this you simply need your own IndexMetadataHandler and overload RenderOperations (you can use inheritance for this one) to create your new IndexOperationsControl. Also we'll need our own MetadataFeature equivalent IPlugin but we'll need to copy it completely and modify GetHandlerForPathParts to return our new IndexMetadataHandler. The only other thing to do is remove MetadataFeature and add our own as a plugin.
// removing default metadata feature
Plugins.RemoveAll(x => x is MetadataFeature);
// add our custom one
Plugins.Add(new CustomMetadataFeature());
Voila, you can display custom ContentTypes exactly how you want per RequestDto.
Background:
I am new to MVP and just coding my first winform application using Model View Presenter
Question:
I have been browsing for best practices on how to write user input validation code for windows controls (e.g TextBox etc) and where to put that code in winforms application using Model View Presenter desing pattern but still confused.
Let me explain
Suppose I have some TextBox controls on my form, which accept inputs like Name, Phone, email, zip etc. Normally I would call different methods like validateName(), validatePhone(), validateEmail() and validateZip() then in each of these methods I would definitely have to check that the input provided by the user in not empty like
if(txtName.Text.Length == 0)
{
errorMessage = "Name is required.";
return false;
}
if(txtEmail.Text.Length == 0)
{
errorMessage = "e-mail address is required.";
return false;
}
That smells like code repetition and I think there must be a better and efficient way to check whether the text is not null (may be by looping through all textbox controls).
So, What I am thinking is to have a CommonMethods class containing common methods like CheckifTextEmply(), CheckifNumber() etc and use this class throughout all my forms since these is common functionality and can be used by other TextBox controls on other forms in the project.
Now can you please tell me if
1. Is this the right approach, if not then how should I approach this issue
2. If right, where should I put the CommonMethods class (code) in Model View Presenter design.
Regards,
ZB
Looks a bit old post. Try creating a method which takes control as an argument and then try to validate it.
bool validate(TextBox txt)
{
return string.IsNUllOrEmpty(txt.Text);
}
you can also try taking a params[] argument to take multiple controls and validate them.
Regarding the error messages, instead of "Name is required" if you go for "required field" message, it will make the job easier. But if not, try creating dictionary of control and bool, pass false if the validation fails and take action according to it.
I know the answer is not very descriptive, but right now, I am a bit busy so cant take much time to explain this. Let me know if it helps.
In our new product we have a few data entry fields that require you to search for the correct value to place in this field.
When you enter this data entry field I would like to provide a search option via something on the view (perhaps an Ajax implementation) and have it allow searching of the database for the value, but when the result returns I want to keep the existing values in place for other fields not affected by the search.
But I have no idea how to do this with MVC. Does anyone have any suggestions on how this should be done?
Write your data entry page in the
usual way for an ASP.NET MVC view.
Get it working without the Ajax
(e.g., submit works correctly when
you just type in the values, without
auto complete).
Write the prototype for a JavaScript method you'll called when the user performs a certain action (e.g. presses a key inside of a certain control). But this inside a script tag in your aspx page. Unfortunately, stack overflow seems to "sanitize" script tags in my example, so I can't demonstrate that part. But you're JavaScript prototype will look something like this:
function startAutoComplete() {
}
Now hook up the event handlers on the user interface control. You need to call the function you've just prototyped an appropriate event handlers for your application. From your description, it sounds like you might want to use onkeydown, but there are lots of events to choose from. You probably need to handle more than one event, as appropriate for your application.
So far, everything that we've done has been standard aspx and JavaScript. In this step, we'll do the only part of the whole process which is really different for ASP.NET MVC. You need to add an action to your controller which will be called (indirectly) by the JavaScript prototype you've just written. The action should accept appropriate input (e.g., a string representing the text from control, or something like that, as appropriate for your application) and return its results in JSON format. I'm going to show a really simple example here; feel free to substitute more complex code in your real application.
public ActionResult GetSuggestions(string searchText)
{
return Json(new {SearchText = searchText});
}
This example just returns a JavaScript object containing one property, which contains the value passed to the function. Like you said, you can write something more useful for your application.
Now you need to call this function in JavaScript. The URI will look something like:
http://localhost/mycontroller/GetSuggestions?searchText=Foo
It is possible to make Ajax calls without a JavaScript library, but much easier if you use jQuery or some other library which handles cross-browser compatibility issues for you. Since I happen to like jQuery, I'll demonstrate that. Let's update the startAutoComplete method we prototyped earlier:
function startAutoComplete() {
var searchText = $("#myeditorid").text();
$.getJSON("/mycontroller/GetSuggestions?searchText=" + searchText,
null,
autoCompleteResponse);
}
The first line uses jQuery to get the text in the control with the ID myeditorid. We'll pass this to the ASP.NET MVC action as the searchText argument, by appending it as a query string parameter.
The next line, which starts with $.getJSON calls a jQuery function which makes an Ajax call to the URI you specify. We pass an argument, autoCompleteResponse, which is the name of a JavaScript method to be called if the response from the Ajax call is successful. Now we have to write autoCompleteResponse.
function autoCompleteResponse(data) {
if (data.SearchText)
{
$("#myeditorid").text(data.SearchText);
}
}
This says, "If the data returned has a SearchText property, set the text of the control to that value." Again, do whatever is appropriate for your application with the data returned.