2013-04-17 19 views
5

korzysta z .NET MVC i kodu-pierwszego EF do realizacji żądanej funkcjonalności. Obiekty biznesowe są względnie złożone i używam System.ComponentModel.DataAnnotations.IValidatableObject do sprawdzania poprawności obiektu biznesowego.
Teraz próbuję znaleźć sposób, w jaki sposób wyświetlić wynik sprawdzania poprawności z obiektu biznesowego, używając MVC ValidationSummary bez użycia adnotacji danych. Na przykład (bardzo uproszczony): Object.NET MVC Niestandardowa walidacja (bez adnotacji danych)

działalności:

public class MyBusinessObject : BaseEntity, IValidatableObject 
    { 
     public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
     { 
      return Validate(); 
     } 
     public IEnumerable<ValidationResult> Validate() 
     { 
      List<ValidationResult> results = new List<ValidationResult>(); 

      if (DealType == DealTypes.NotSet) 
      { 
       results.Add(new ValidationResult("BO.DealType.NotSet", new[] { "DealType" })); 
      } 

      return results.Count > 0 ? results.AsEnumerable() : null; 
     } 
    } 

Teraz w moim kontroler MVC mam coś takiego:

public class MyController : Controller 
    { 
     [HttpPost] 
     public ActionResult New(MyModel myModel) 
     { 
      MyBusinessObject bo = GetBoFromModel(myModel); 
      IEnumerable<ValidationResult> result = bo.Validate(); 
      if(result == null) 
      { 
       //Save bo, using my services layer 
       //return RedirectResult to success page 
      } 

      return View(myModel); 
     } 
    } 

Biorąc mam Html.ValidationSummary();.
Jak mogę przekazać IEnumerable<ValidationResult> do ValidationSummary?

Próbowałem znaleźć odpowiedź przez google, ale wszystkie przykłady znalazłem opisuje, jak wyświetlić podsumowania sprawdzania poprawności za pomocą adnotacji danych w modelu, a nie w obiekcie Business.

Dzięki

+0

MyBusinessObject nie może być modelem, ponieważ jest bardziej złożony niż model i wykonuje znacznie więcej weryfikacji. Nie chcę wyrzucać wyjątków z EF, a następnie przekierować do strony błędów, chcę tylko pokazać w widoku, które pola są nieprawidłowe w BusinessObject. –

+0

Clarify - implementacja IValidatableObject musi być w viewmodel mianowicie w klasie MyModel. Przekazałeś firmie Viewmodel obawy (walidacja danych wejściowych użytkownika) - nie jest to poprawne. – vladimir77

+0

@ vladimir77 Według http://msdn.microsoft.com/en-us/data/gg193959.aspx nie znalazłem niczego niepoprawnego, używając IValidatableObject z kodem-pierwszym. –

Odpowiedz

11

Dodaj Rzeczowe powiedzieć BusinessError w modelu

w widoku wykonaj następujące czynności

@Html.ValidationMessageFor(model => model.BusinessError) 

wówczas w kontrolerze gdy masz błąd wykonać następujące

ModelState.AddModelError("BussinessError", your error) 
+0

Ale w ten sposób powinienem przejrzeć IEnumerable pisząc "foreach" lub coś takiego ? –

+2

W morzu zamieszania i śmierdzącego kodu, to jest latarnia morska Alex, powinieneś podążać za tym przykładem, jest to najbardziej zgrabny sposób dodawania błędów do Modelstate do wyświetlania w Valida Podsumowanie. –

+0

@ Moby'sStuntDouble, dzięki za punkt ... Brakowało mi ModelState w odpowiedzi, muszę to zbadać, wygląda na to, że potrzebuję :) –

0

Jednym ze sposobów przekazania zawartości IEnumerate i k eep korzystające z Html.ValidationSummary jest przez aktualizację ModelState.

Możesz znaleźć dobrą dyskusję na temat aktualizacji ModelState here.

2

Chciałbym rzucić okiem na FluentValidation. Jest to framework do sprawdzania poprawności bez irytacji danych. Używałem go z wielkim sukcesem w niektórych projektach do złożonego sprawdzania poprawności i można go również wykorzystywać poza projektem MVC.

Oto przykładowy kod z ich strony:

using FluentValidation; 

public class CustomerValidator: AbstractValidator<Customer> { 
    public CustomerValidator() { 
    RuleFor(customer => customer.Surname).NotEmpty(); 
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name"); 
    RuleFor(customer => customer.Company).NotNull(); 
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount); 
    RuleFor(customer => customer.Address).Length(20, 250); 
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode"); 
    } 

    private bool BeAValidPostcode(string postcode) { 
    // custom postcode validating logic goes here 
    } 
} 

Customer customer = new Customer(); 
CustomerValidator validator = new CustomerValidator(); 
ValidationResult results = validator.Validate(customer); 

bool validationSucceeded = results.IsValid; 
IList<ValidationFailure> failures = results.Errors; 
1

Entity Framework powinny rzucać DbEntityValidationException jeśli istnieją błędy sprawdzania poprawności. Następnie można użyć wyjątku, aby dodać błędy do ModelState.

try 
{ 
    SaveChanges(); 
} 
catch (DbEntityValidationException ex) 
{ 
    AddDbErrorsToModelState(ex); 
} 
return View(myModel); 

protected void AddDbErrorsToModelState(DbEntityValidationException ex) 
{ 
    foreach (var validationErrors in ex.EntityValidationErrors) 
    { 
      foreach (var validationError in validationErrors.ValidationErrors) 
      { 
       ModelState.AddModelError(validationError.PropertyName, validationError.ErrorMessage); 
      } 
    } 
} 
Powiązane problemy