Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#4.0

A Nice Way to Collect All Input Errors in a Submit and Feedback to the User at a Time

4.50/5 (2 votes)
2 Mar 2010GPL32 min read 14.2K  
ValidationScope is used to collect all input errors in a context although validation code exists in independent APIs.

Introduction

ValidationScope is used to collect all input errors in a context although validation code exists in independent APIs. We don't need to return error messages and throw exceptions explicitly. It like transaction context is managed by TransactionScope and we don't need to transmit transaction instances. It's thread safe.

ValidationScope implements the interface IDisposable that we can initialize a scope by using block. And in a block, you can add errors into the scope that the using block disposal throws an exception with all added errors if there is one. And ValidationScope supports nest. A validation scope and its nested scopes share the same validation context so that it is possible to write independent APIs with great coordination on validation.

Background

ValidationScope is included in CommonLibrary of RapidWebDev. RapidWebDev is an infrastructure that helps engineers to develop enterprise software solutions in Microsoft .NET easily and productively. It consists of an extendable and maintainable web system architecture with a suite of generic business model, APIs and services as fundamental functionalities needed in development for almost all business solutions. So when engineers develop solutions in RapidWebDev, they can have a lot of reusable and ready things, then they can focus more on business logics implementation. In practice, we can save more than 50% time on developing a high quality and performance business solution than traditional ASP.NET development.

Source Code

The source code of the implementation, sample and test cases can be found in RapidWebDev source package which you can download from the official website.

Using the Code

  • Project: RapidWebDev.Common
  • Namespace: RapidWebDev.Common.Validation

There are four constructors for ValidationScope:

  1. ValidationScope()
  2. ValidationScope(Type thrownExceptionType)
  3. ValidationScope(bool forceToThrowExceptionIfHasErrorsWhenDisposing)
  4. ValidationScope(bool forceToThrowExceptionIfHasErrorsWhenDisposing, Type thrownExceptionType)

Parameters:

  • thrownExceptionType is to specify type of exceptions which are thrown in disposal if there are errors logged. By default, BaoJianSoft.Common.Validation.ValidationException is thrown.
  • forceToThrowExceptionIfHasErrorsWhenDisposing is True to indicate that the disposal for nested validation scope throws an exception directly if there are errors. The ancestor validation scope catches and integrates all errors from its nested scope with it equals to False.

A simple sample using ValidationScope is as below. An InvalidOperationException instance with 2 error messages is thrown in disposal of this using block. If you don't specify typeof(InvalidOperationException) explicitly, a ValidationException instance is thrown instead.

C#
using (ValidationScope scope = new ValidationScope(typeof(InvalidOperationException)))
{
    if (true)
        scope.Error("Name cannot be empty!");
    if (true)
        scope.Error("Password cannot be empty!");
}

A nested validation scope sample is as follows. You can imagine that the NestedMethod1 and NestedMethod2 are from independent APIs. The ancestor scope disposal throws a validation exception with all 5 error messages in this case. But if you construct the first nested validation scope using 3rd/4th constructor with forceToThrowExceptionIfHasErrorsWhenDisposing to True, the thrown exception only contains the top 3 error messages.

C#
public void NestedValidationScopeTest()
{
    using (ValidationScope scope = new ValidationScope())
    {
        scope.Error("Error 1");

        NestedMethod1();
        NestedMethod2();
    }
}

private void NestedMethod1()
{
    using (ValidationScope scope = new ValidationScope())
    {
        scope.Error("Error 2");
        scope.Error("Error 3");
    }
}

private void NestedMethod2()
{
    using (ValidationScope scope = new ValidationScope())
    {
        scope.Error("Error 4");
        scope.Error("Error 5");
    }
}

You can also call method Throw() of validation scope which throws an exception for current validation scope immediately in nested or ancestor scope if there are errors logged.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)