HiveBrain v1.2.0
Get Started
← Back to all entries
debugcsharpMinor

Validation that also returns error messages

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
errorvalidationalsothatmessagesreturns

Problem

My Create, Update and Delete methods should return a success and errors list depending up on the result. I want to avoid the out parameters in the method. Therefore I came up with an implementation of ResultModel class which gets returned for the above mentioned methods.

Is my implementation elegant enough to go ahead with the real world project? Or could there be other better ways to return the result?

Here is the sample code which actually works. I have inserted comments in the code where I think is necessary.

```
public sealed class CountryModel
{
public string CountryName { get; set; } //mandatory and upto 32 chars
public string CountryCode { get; set; } //mandatory and upto 5 chars
}

///
/// To hold the results, be it the list of errors or just the success message.
///
public sealed class ResultModel
{
private object _success; // to hold boolean and int value.
public object Success { get { return _success; } }

private List _errors; // to hold multiple errors, could be validation errors.
public List Errors { get { return _errors; } }

public void AddSuccess(object any)
{
this._success = any;
}

public void AddError(string text)
{
if (string.IsNullOrEmpty(text))
{
return;
}

if (this._errors == null)
{
this._errors = new List();
}

this._errors.Add(text);
}
}

public sealed class CountryManager
{
private const string EmptyErrorSuffix = "is empty.";
private const string LengthErrorSuffix = "has exceeded it's length.";
private const short CountryCodeMaxLength = 5;
private const short CountryNameMaxLength = 32;

public ResultModel AddCountry(CountryModel model)
{
var result = this.ValidateTheModel(model);
if (result.Errors == null) //if no errors then perform the Database operation, in this case Add a record.
{
try
{

Solution

This is a more elegant solution as we have incorporated generics. I've started with 2 constructors, with a single parameter result indicating success. One could build off more functionality as needed. Instead of object, one can now specify the type of result model to return. I believe this makes the code a little more explicit. Sample code include implementation and sample usage below based on returning a 'Foo' object.

The boolean flag success (Success) indicates overall status. The result code (ResultCode) is a number which can be used to communicate additional status. On success this would be zero. On failure conditions this could be a number indicating a certain condition occurred. This could be business or technical errors. For example, 10 = Not Authorized, 20 = No records Found, 99 = Unexpected Error and so forth. The reason I like to include a result code is for client/server or service type situations. We would just send the number back to the client. The client would then do the proper localization and prepare the appropriate string based on the number. If one doesn't have to worry about that, just the error string can be returned and the result code can be omitted.

public class ResultModel
    {
        public ResultModel(bool success, int resultCode, T result)
        {
            Success = success;
            ResultCode = resultCode;
            Result = result;
            Errors = new List();
        }

        public ResultModel(T result)
        {
            Success = true;
            ResultCode = 0;
            Result = result;
            Errors = new List();
        }

        public bool Success { get; private set; }
        public int ResultCode { get; private set; }
        public T Result { get; private set; }
        public IList Errors { get; private set; }

        public void AddError(string error)
        {
            Errors.Add(error);
        }
    }

public class Foo
    {
        public string Name { get; set; }
        public bool Flag { get; set; }
    }

public class FooResult
    {
        public ResultModel GetHappyFooResult()
        {
            var foo = new Foo {Name = "Test", Flag = false};
            return new ResultModel(foo);
        }

        public ResultModel GetSadFooResult()
        {
            var foo = new Foo {Name = "Test", Flag = false};
            var result = new ResultModel(false, 999, foo);
            result.AddError("Something bad happened.");
            return result;
        }
    }

Code Snippets

public class ResultModel<T>
    {
        public ResultModel(bool success, int resultCode, T result)
        {
            Success = success;
            ResultCode = resultCode;
            Result = result;
            Errors = new List<string>();
        }

        public ResultModel(T result)
        {
            Success = true;
            ResultCode = 0;
            Result = result;
            Errors = new List<string>();
        }

        public bool Success { get; private set; }
        public int ResultCode { get; private set; }
        public T Result { get; private set; }
        public IList<string> Errors { get; private set; }

        public void AddError(string error)
        {
            Errors.Add(error);
        }
    }


public class Foo
    {
        public string Name { get; set; }
        public bool Flag { get; set; }
    }



public class FooResult
    {
        public ResultModel<Foo> GetHappyFooResult()
        {
            var foo = new Foo {Name = "Test", Flag = false};
            return new ResultModel<Foo>(foo);
        }

        public ResultModel<Foo> GetSadFooResult()
        {
            var foo = new Foo {Name = "Test", Flag = false};
            var result = new ResultModel<Foo>(false, 999, foo);
            result.AddError("Something bad happened.");
            return result;
        }
    }

Context

StackExchange Code Review Q#135945, answer score: 7

Revisions (0)

No revisions yet.