Reputation: 1497
I have a custom ValidationAttribute like this :
public class ReceiverRegion : ValidationAttribute
{
private RegionService regionService;
private CityService cityService;
public ReceiverRegion() : base("Incorrect region code")
{
this.regionService = new RegionService();
this.cityService = new CityService();
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
int regionId = Convert.ToInt32(value);
int plate = Convert.ToInt32((validationContext.ObjectInstance as CorporateOrderItem).ReceiverCity);
int productGroupId = Convert.ToInt32(validationContext.Items["productGroup"].ToString());
if (!CheckReceiverRegionExistence(regionId, plate, productGroupId))
{
IEnumerable regions = this.regionService.GetList(cityService.GetByPlate(plate).PKCityId);
return new CorporateOrderValidationResult(base.ErrorMessage, regions.Select(r=>r.Name));
}
return CorporateOrderValidationResult.Success;
}
private bool CheckReceiverRegionExistence(int plate, int regionId, int productGroup)
{
return !(regionService.GetByCityAndRegionIdForProductGroup(plate, regionId, productGroup) == null);
}
}
But as you can see in IsValid method, I'm trying to return a custom object which inherits from ValidationResult. My problem is, I can't access the extra members of my CorporateOrderValidationResult
instance since IsValid returns the base ValidationResult type. Below is the code where I call validate and get a collection of ValidationResult as return value.
List results = new List();
bool isValid = Validator.TryValidateObject(instance, context, results, true);
I tried to cast results object to List<CorporateOrderValidationResult>
, but no matter what I try(for instance --> item as CorporateOrderValidationResult
or results.OfType<CorporateOrderValidationResult>()
or (CorporateOrderValidationResult)item)
I either get InvalidCastException or null value. Is there a possible way to convert this list of result to a list of my custom result class? Thanks...
Upvotes: 3
Views: 6156
Reputation: 839
I know this is old question, but first result in Google when you ask for custom ValidationResult
class. Example presented by Vyacheslav Volkov works, but why?
I spent few hours today trying to make my code working - the key line is:
public TestResult(): base ("test")
I was not going to use error message at all, I had my own structure for this so I wrote my ctor like this:
public TestResult() : base("")
- empty string sent to base class has consequences, that are not mentioned in documentation. TryValidate()
method will not insert our object into results
collection as it is returned by our version of IsValid()
, but will build new one with default error message for this field, like "Field " + fieldName + " is Invalid"
and put it instead of the one we want.
Upvotes: 0
Reputation: 4742
I tried to reproduce this behavior, but everything works as expected:
public class TestClass
{
[TestValidation]
public string TestProp { get; set; }
}
public class TestValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
return new TestResult();
}
}
public class TestResult : ValidationResult
{
public TestResult()
: base("test")
{
}
}
Code for validation:
var instance = new TestClass();
var context = new ValidationContext(instance, null, null);
var results = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(instance, context, results, true);
//Contains one instance of TestResult
var customResults = results.OfType<TestResult>().ToArray();
Upvotes: 3