6

On my ASP.NET MVC 3 project, I have implemented the repository pattern inside a seperate class library project.

Also I am using EF as ORM. I have also implemented some model validation with IValidatableObejct interface. Here is how it looks like :

[MetadataType(typeof(AccommPropertySeasonPeriodAlias.MetaData))]
public partial class AccommPropertySeasonPeriodAlias : IValidatableObject {

    private class MetaData {

        [StringLength(5), Required]
        [Display(Name = "Period Alias Name")]
        public string AccommPropertySeasonPeriodAlias1 { get; set; }
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {

        var repo = new AccommPropertySeasonPeriodAliasRepository();

        if (repo.GetAll(this.AccommPropertySeasonID).
            Where(x => x.AccommPropertySeasonPeriodAlias1 == this.AccommPropertySeasonPeriodAlias1) != null)

            yield return new ValidationResult("Alias Name needs to be unique");
    }
}

As you see, from now on, my model completely tightly-coupled because I have used AccommPropertySeasonPeriodAliasRepository class directly instead of using IAccommPropertySeasonPeriodAliasRepository.

What is the way of doing this right so that my model can be, well, (not sure if this is the right word) fake-able for unit testing?

tugberk
  • 57,477
  • 67
  • 243
  • 335

3 Answers3

4

Uniquiness constraint is outside the scope of that entity. You should validate this constraint when adding a new entity, from outside. This validation shouldn't belong to the entity itself. This depends on the context the entity is in, and not just on that entity alone.

driushkin
  • 3,531
  • 1
  • 24
  • 25
  • So, you say that there is no way to inject the repository inside this scope? – tugberk Nov 10 '11 at 16:24
  • I am also validating the uniqueness of the value inside my database with unique constraint and there is no way for my app to insert the same data to my db but my purpose here is to provide nice feedback to user what went wrong. – tugberk Nov 10 '11 at 16:28
  • 1
    I guess you could use property injection ( http://social.msdn.microsoft.com/Forums/en-CA/adodotnetentityframework/thread/c20f0a5e-0b2b-4a10-8c12-b99a69ae434b ). But this is a wrong thing to do, your entity should not depend on repository at all. – driushkin Nov 10 '11 at 18:08
4

Validation logic can be injected using MVC's built in resolver.

See the usage with the ModelValidatorProvider which is resolved using the registered container in MVC.

ASP.NET MVC 3: Validating model when information external to the model is required

Community
  • 1
  • 1
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
1

You can use the GetService(Type serviceType) method on ValidationContext - see here: https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.validationcontext.getservice?view=net-5.0#System_ComponentModel_DataAnnotations_ValidationContext_GetService_System_Type_

It's a service locator pattern but much simpler than some more complex implementations using DataAnnotationsModelValidator. Sometimes the downside of a simple solution (using a ServiceLocator pattern) outweighs the cost of a complex one IMO.

Dave Black
  • 7,305
  • 2
  • 52
  • 41