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.
Related
Suppose I have a model with some string property.
Imagine also that this string property is actually a comma delimited list of values.
If I want to make a form to update values on my model it would be easy enough to call:
#Html.TextBoxFor(model => model.myCommaDelimitedProp, new { #class = "form-control", placeholder = "CommaDelimitedPropValue" })
However, that is not good enough for the intended application.
I would like to have a custom EditorFor() that could somehow take my property, use string parsing and next generate an array of text boxes to display the pre-existing values.
That would also be relatively trivial.
However, what I cannot seem to solve, mainly because I lack client side experience (js, jquery, angular, ...):
How could I make my editor such that there would be a small button so that I could dynamically add rows, fill them such that, upon form submission, I could string the new values onto the pre-existing string.
So specifically, what would any of you use to achieve this client side behaviour?
I just need some help to be put on the way...
You can achieve this with editor templates. There's a quick intro I threw together on my blog. The only additional thing you'll need is UIHint. Since you won't be able to rely on a specific C# type or DataType annotation to determine that this should be treated as a comma-delimited property. You can just explicitly tell Razor what template it should use. For example:
[UIHint("CommaDelimited")]
public string MyCommaDelimitedProperty { get; set; }
Which would correspond to the editor template: Views\Shared\EditorTemplates\CommaDelimited.cshtml. Once you set up that view how you like it. Then in your form you just call:
#Html.EditorFor(m => m.MyCommaDelimitedProperty)
EDIT
I'll leave my previous answer because it could still be helpful in terms of being able to generate a control for a specific type of thing. You actually may still need to use it to get the right set up on your field to make the JS work properly.
However, when it comes to the client-side handling of this, I figured there had to be something out there already to solve this problem. (Never do more work than you have to.) A cursory search turned up a little script called Tokenfield for Bootstrap. I'm not sure if you're using Bootstrap or not. If not, I also found jQuery Tokeninput and jquery.token-field. I'm sure there's others, as well.
I'm writing my own Rule Engine, I've looked at a couple that existed but I'm looking for something else which I couldn't find examples to.
I'm looking for a similar application where I can dig into and learn how to do it.
Now, my question is REGARDLESS of the Rule Engine, more of a Form/Dynamic question, but if with your answer you can
relate to what I eventually want to do, that would be great.
Regarding the UI, I'm using Visual Form and the I'd like it to be like this:
http://i.imgur.com/5istREF.jpg
Now, once the user select on the final check box "And/Or" I want him to be able to enter another rule, exactly the same format as the first one.
http://i.imgur.com/N588sjj.jpg
Now the user can basically do it as many times as he wants, so I'm looking for a way to dynamically handle it and create buttons/pannels or even using the same ones (but every time he can enter different values).
Like I've said if you know any similar application/code that I can look into, regardless of rule engine, that will help as well.
Eventually I will take all the fields that he entered and turn it into code.
If I understand you correctly, what you can do is make a controller of your own which is defined in an additional form and then you can add it to your main form as much as you want.
You can define this new controller (meaning a new form) to hold only a single line of the comboBox and then add it to a location in your main form which is based on the location of the previous controller.
Here is an example which adds several control of a class called CNewControl to a tab called newControlsTab one after the other.
int controlHeight = 0;
foreach (CNewControl newControl in newControlList)
{
this.newControlsTab.Controls.Add(newControl );
newControl.Dock = DockStyle.Top;
newControl.Location = new System.Drawing.Point(40, 3 + controlHeight);
controlHeight += newControl .Size.Height;
}
You can of course change it to add your line only once when the user chooses the appropriate option in which a line should be added.
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
I think the main distinction in naming is between logic and view-related objects. You might have a variable named “UserName” in the code behind file of a page, but then also a .NET TextBox in which a user is supposed to enter their username (a sensible ID would also be “UserName”). How can we differentiate (ID-wise), between the logic “UserName” and the view “UserName”. My question is, what is a sensible distinction to make when coming up with these names?
In my opinion, a variable name/control ID should never describe what it IS, only what it DOES. “tbUserName” describes that it is a TextBox, “strUserName” defines that it is a string.
One idea would be to prefix all view related objects with “vwUserName” and keep the logic part as “UserName”. Does that make sense? What about when we have a situation where you have validators? Would you name them “vwUserNameRequiredValidator”, or “vwEmailAddressFormatValidator”? In that situation would you need to describe what it actually is? Would you give a .NET RequiredFieldValidator object an ID of “rfvUserName”?
I really want to get an idea of what other people think on this, because I want to come up with a sensible and consistent naming convention system going forward. I’m interesting to hear arguments for any type of system.
Hungarian notation is so 1990s... ;-)
I would use UserName for logic and userName for id.
I tend to use _userName as a variable and UserName as property in code behind, and as ID for a text box UserNameField. I find it easier to work with the intellisense in this way, instead of prefixing as we did in the VB-days with txtUserName.
Edit: not calling it UserNameTextBox, but UserNameField is also easier to work with if you want to the exchange the field (that is TextBox) to another control (it may not apply to this example of username though.
For controls, I always add a prefix like:
Textbox - txtName - I don't use tb because it can be confusing since I use tbl for HtmlTable
Checkbox - cbIsNameRequired
RequiredFieldValidator - rfvName
For variables:
Name
IsNameRequired
etc..
It is all about getting used to a pattern but always have a pattern..
My typical application has a couple of textboxes, checkbuttons, radiobuttons, and so. I always want to load the settings the user used the last time when the program starts, and also want to save the settings as the users clicks "Save settings" or closes the application. When the user attempts to save the settings, I'll have to check each of the controls for input errors (sometimes they have to have a max length, other times only caps, other times other things, there isn't a rule for them all, everytime it'll be different), and only if everything's OK i'll let him save the options. If there is something wrong, no option is saved and my errorcontrol provider will pop up a description of the input type info that should be put in that control.
I've been designing this from scratch for all my projects, but it's being a pain to do it. So I'd thought maybe now was the time to do some library to help me. I thought initially that maybe it'd be a good idea to have all the controls on my form that are going to be part of this save/load process to have an attribute associated with them, something like this
public delegate bool InputIsOkHandler();
public class OptionsAttribute : Attribute {
public Control controlRef;
public InputIsOkHandler IsInputOk;
public string errorMessageToShowOnErrorProvider;
public OptionsAttribute(Control controlRef, InputIsOkHandler inputHandler, string errMessage) {
...
}
}
The main problem here is that when I declare the attribute on a given var:
[Options(...)]
TextBox textBox1 = new TextBox();
I'll get
Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
So I guess this approach isn't the best one. What would you guys do in this situation? Would you use attributes? Would you use other mechanisms?
Thanks
Do you know that .NET already includes such a system since 2.0? See MSDN, CodeProject and this white paper from WestWind.
The Personalization and User Profiles supported in ASP.NET 2.0 can be a nice way to achieve your goal.
You can check this MSDN article for a overview Personalization in ASP.NET 2.0