Temat: ASP.NET MVC2 Validate

Witam!
Mam pytanko odnosnie walidacji w asp.net mvc2, otoz:

mam sobie powiedzmy klase ( jest to klasa znajdujaca sie w class library ):
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}

i teraz chce sa zwalidowac z poziomu mvc2.

Jak moge ja rozszerzyc o metadane typu Required etc.. ?
Oczywiscie klasa jest tylko przykladowa, moze miec dziesiatki tych pol do walidacji :)
Kamil Boś

Kamil Boś .NET/SharePoint
Developer

Temat: ASP.NET MVC2 Validate

Jak wiadomo walidacja danych powinna mieć miejsce w modelu którego będziemy wykorzystywać w wielu miejscach aplikacji, a więc:

public class Person
{
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name must be under 50 characters")]
public string Name { get; set; }
[Required(ErrorMessage = "Surname is required")]
public string Surname { get; set; }
}

a następnie w controlerze sprawdzamy stan modelu czyli czy podane dane są zgodne z ustawieniami jakie wprowadziliśmy w modelu, czyli, np:

[HttpPost]
public ActionResult Create(Models.Person p)
{
if (!ModelState.IsValid) // sprawdzanie walidacji
{
return View("Create", p);
}

_IServiceProvider.Create(p);

return RedirectToAction("Index");
}

Oczywiście atrybutów walidacyjnych jak wiesz można ustawić więcej, plus oczywiście budowanie atrybutów walidacyjnych na wyłącznie własne potrzeby.

Temat: ASP.NET MVC2 Validate

yhm, okej chyba troszke zle sprecyzowalem pytanie ;)
Chodzi bardziej o to ze dostaje klase Person i ona jest powiedzmy wykorzystywana w projekcie konsolowym. Nie moge w nia integrowac. I teraz chce ja wykorzystac w projekcie asp.net mvc 2. Teraz robie to tak:

public class PersonValidate : Person
{
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name must be under 50 characters")]
public string NameValid { set { this.Name = value; } }
...
}

i dziala, ale to rozwiazanie wydaje mi sie takie "na brutala" :)

konto usunięte

Temat: ASP.NET MVC2 Validate

Ninja zrobiłby to tak...o ile mógłby niepostrzeżenie udekorować klasę atrybutem MetadataType :)


[MetadataType(typeof(Person_Metadata))]
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}

internal class Person_Metadata
{
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name must be under 50 characters")]
public string Name { get; set; }

// ...
}
Jarosław D. edytował(a) ten post dnia 26.11.10 o godzinie 22:10
Piotr S.

Piotr S. Vice President &
Chief Geek @
Proligence / .NET
junkie / ...

Temat: ASP.NET MVC2 Validate

Trochę ładniejszym rozwiązaniem (z punktu widzenia SoC) byłoby utworzenie osobnej, niezależnej klasy PersonViewModel (zamiast tworzyć klasę pochodną od Person). Obiekty tej klasy pośredniczyłyby w "komunikacji" między kontrolerem a widokiem (i vice versa) i zawierałyby tylko i wyłącznie informacje, które chcesz wyświetlić. Ją dopiero udekorowałbyś atrybutami.

To podejście przydaje się w szczególności, gdy obiekty, które dostajemy (Person w Twoim przypadku) są
1. duże, i/lub
2. musimy ich zawartość przygotować do wyświetlenia.
W obu przypadkach zyskujemy na wydajności. W 2. dodatkowo zmniejszamy liczbę operacji na danych w widoku (za co odpowiada warstwa Modelu) tym samym zmniejszając objętościowo sam widok (i zwiększając własną wygodę;)

Męczące może być jedynie przepisywanie właściwości (jeśli jest ich sporo), ale od czego mamy AutoMapper'a (albo ValueInjecter - oba dostępne na Codeplex'ie):)

Pozdrawiam

Temat: ASP.NET MVC2 Validate

Piotr Szmyd:
Trochę ładniejszym rozwiązaniem (z punktu widzenia SoC) byłoby utworzenie osobnej, niezależnej klasy PersonViewModel (zamiast tworzyć klasę pochodną od Person). Obiekty tej klasy pośredniczyłyby w "komunikacji" między kontrolerem a widokiem (i vice versa) i zawierałyby tylko i wyłącznie informacje, które chcesz wyświetlić. Ją dopiero udekorowałbyś atrybutami.

To podejście przydaje się w szczególności, gdy obiekty, które dostajemy (Person w Twoim przypadku) są
1. duże, i/lub
2. musimy ich zawartość przygotować do wyświetlenia.
W obu przypadkach zyskujemy na wydajności. W 2. dodatkowo zmniejszamy liczbę operacji na danych w widoku (za co odpowiada warstwa Modelu) tym samym zmniejszając objętościowo sam widok (i zwiększając własną wygodę;)

Męczące może być jedynie przepisywanie właściwości (jeśli jest ich sporo), ale od czego mamy AutoMapper'a (albo ValueInjecter - oba dostępne na Codeplex'ie):)

Pozdrawiam

Aha, czyli chodzi o coś mniej więcej w tym stylu?

public class PersonViewModel
{
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name must be under 50 characters")]
public string Name { get; set; }

[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name must be under 50 characters")]
public string Surname { get; set; }

public Person CreatePerson()
{
Person p = new Person();
p.Name = this.Name;
p.Surname = this.Surname;
return p;
}
}


Czy ciagle błądze? ;)

A co do wypowiedzi Jarka myślałem o udokorowaniu Person'a [MetadataType(typeof(Person_Metadata))], ale się nie da użyć tego atrybutu poza mvc2
Kamil Boś

Kamil Boś .NET/SharePoint
Developer

Temat: ASP.NET MVC2 Validate

A co do wypowiedzi Jarka myślałem o udokorowaniu Person'a [MetadataType(typeof(Person_Metadata))], ale się nie da użyć tego atrybutu poza mvc2

W tym przypadku należy skorzystać z własnego metadata provider'a wykorzystując do tego celu TypeDescriptor. Dla technologii takich jak MVC czy ASP.NET DynamicData można skorzystać z atrybutu MetadataType, natomiast w przypadku aplikacji konsolowych czy zwykłego asp.net ten atrybut po prostu nie zadziała.

Do tego celu poprawnie będzie zastosować wspomniany TypeDescriptor:


TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(
typeof(Person),
typeof(Person_Metadata)),
typeof(Person));


gdzie jak widać utworzona jest instancja klasy AssociatedMetadataTypeTypeDescriptionProvider, która poszerza namespace System.ComponentModel.DataAnnotations i która zarejestruje zastosowany atrybut [MetadataType], natomiast standardowo przestrzeń dostarcza szeregu atrybutów dla MVC czy Dynamic Data Controls takich własnie jak [MetadataType] a którego w takim zastosowaniu nie ma.
Dodatkowo w celu przeprowadzenia testów (Unit Test) dla stworzonego projektu MVC musisz zastosować ten sam mechanizm.Kamil Boś edytował(a) ten post dnia 29.11.10 o godzinie 00:22

Następna dyskusja:

ASP.NET MVC2 oraz Area




Wyślij zaproszenie do