Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate required fields in class properties?

I wanted a simple way to ensure that some properties in a class contained values and/or were within a range (ie: not more than 50 characters long). I used the question and answer on How to validate Class properties? unfortunately I was not able to get it to work.

To test it, I created a very simple WinForm example using C#. Even though I am doing everything the same, it never throws a validation exception when I apply incorrect values (ie: setting the age above the allowed limit).

Can someone explain why it does not throw the exception? It's as if the class doesn't know it is supposed to use the required attributes.

Form1.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel.DataAnnotations;

namespace RequiredFieldsInClassExample {
public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    private void btnTest_Click(object sender, EventArgs e) {
        try {
            lstStatus.Items.Clear();
            lstStatus.Items.Add("Creating list of people");
            List<Person> CollectionOfPeople = new List<Person>();

            lstStatus.Items.Add("Creating a good person");
            Person Jeff = new Person();
            Jeff.Age = 33;
            Jeff.Firstname = "Jeff";
            Jeff.Lastname = "Jefferson";
            Jeff.GroupCode = "JJJ";

            CollectionOfPeople.Add(Jeff);

            lstStatus.Items.Add("Creating a bad person");
            Person Tim = new Person();
            Tim.Age = 444;
            Tim.Firstname = "";
            Tim.Lastname = "";
            Tim.GroupCode = "";

            CollectionOfPeople.Add(Tim);

            lstStatus.Items.Add("Done");
        } catch (ValidationException Exp) {
            MessageBox.Show(this, Exp.Message, "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        } catch (Exception Exp) {
            MessageBox.Show(this, Exp.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
    }
}
}

Person.cs

using System.ComponentModel.DataAnnotations;

public class Person {
private int m_iAge = 1;
private string m_sFirstname = "Unknown";
private string m_sLastname = "";
private string m_sGroupCode = "AAA";

//[Required(ErrorMessage = "Age is a required field.")]
//[Range(1, 100, ErrorMessage = "A persons age must be between 1 and 100.")]
[Required, Range(1, 100)]
public int Age
{
    get { return m_iAge; }
    set { m_iAge = value; }
}

//[Required(ErrorMessage = "Firstname is a required field.")]
[Required]
public string Firstname
{
    get { return m_sFirstname; }
    set { m_sFirstname = value; }
}

public string Lastname
{
    get { return m_sLastname; }
    set { m_sLastname = value; }
}

//[StringLength(3)]
public string GroupCode
{
    get { return m_sGroupCode; }
    set { m_sGroupCode = value; }
}
}
like image 372
ThePeter Avatar asked Sep 13 '16 18:09

ThePeter


2 Answers

Add a new method into the Person class to perform the validation. The new "Validate" method works for required values, range, and string length.

Person.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

public class Person {
private int m_iAge = 1;
private string m_sFirstname = "Unknown";
private string m_sLastname = "";
private string m_sGroupCode = "AAA";

[Required(ErrorMessage = "Age is a required field.")]
[Range(1, 100, ErrorMessage = "A persons age must be between 1 and 100.")]
public int Age
{
    get { return m_iAge; }
    set { m_iAge = value; }
}

[Required(ErrorMessage = "Firstname is a required field.")]
public string Firstname
{
    get { return m_sFirstname; }
    set { m_sFirstname = value; }
}

public string Lastname
{
    get { return m_sLastname; }
    set { m_sLastname = value; }
}

[StringLength(3, MinimumLength = 3)]
public string GroupCode
{
    get { return m_sGroupCode; }
    set { m_sGroupCode = value; }
}

public void Validate() {
    ValidationContext context = new ValidationContext(this, serviceProvider: null, items: null);
    List<ValidationResult> results = new List<ValidationResult>();
    bool isValid = Validator.TryValidateObject(this, context, results, true);

    if (isValid == false) {
        StringBuilder sbrErrors = new StringBuilder();
        foreach (var validationResult in results) {
            sbrErrors.AppendLine(validationResult.ErrorMessage);
        }
        throw new ValidationException(sbrErrors.ToString());
    }
}
}

Back in the code behind of the form, you just need to call the Validate method for each class.

Form1.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel.DataAnnotations;

namespace RequiredFieldsInClassExample {
public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    private void btnTest_Click(object sender, EventArgs e) {
        try {
            lstStatus.Items.Clear();
            lstStatus.Items.Add("Creating list of people");
            List<Person> CollectionOfPeople = new List<Person>();

            lstStatus.Items.Add("Creating a good person");
            Person Jeff = new Person();
            Jeff.Age = 33;
            Jeff.Firstname = "Jeff";
            Jeff.Lastname = "Jefferson";
            Jeff.GroupCode = "JJJ";
            // LOOK! This line was added
            Jeff.Validate();

            CollectionOfPeople.Add(Jeff);

            lstStatus.Items.Add("Creating a bad person");
            Person Tim = new Person();
            Tim.Age = 444;
            Tim.Firstname = "";
            Tim.Lastname = "";
            Tim.GroupCode = "";
            // LOOK! This line was added
            Tim.Validate();

            CollectionOfPeople.Add(Tim);

            lstStatus.Items.Add("Done");
        } catch (ValidationException Exp) {
            MessageBox.Show(this, Exp.Message, "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        } catch (Exception Exp) {
            MessageBox.Show(this, Exp.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
    }
}
}
like image 57
ThePeter Avatar answered Oct 25 '22 16:10

ThePeter


It's been a long time since I've done this in , but I'll give it a shot. It think you need to manually validate the class using the System.ComponentModel.DataAnnotations.Validator class. You can also implement IValidatableObject on the class that needs validating - I like this approach.

like image 35
Big Daddy Avatar answered Oct 25 '22 16:10

Big Daddy