.NET,  C#,  Programowanie

ModelState, czyli wstępna walidacja w ASP.NET Web Api

ASP.NET dostarcza nam mechanizmu wstępnej walidacji danych (sprawdzenia czy dane są poprawne), które są przesyłane w żądaniu. Programista nie musi ręcznie sprawdzać czy dane pole nie ma wartości pustej, czy długość ciągu znaków nie przekracza narzuconego limitu, bądź czy liczba mieści się w dozwolonym zakresie. Wystarczy, że użyje techniki opisanej poniżej, która jednocześnie jest bardzo prosta w użyciu.

Poniższy przykład został stworzony w ASP.NET Core 2.1 Web Api.

Zanim zaczniemy, będziemy potrzebować modelu danych, który pomoże zrozumieć zagadnienie. Dobrym przykładem będzie stworzenie klasy związanej z człowiekiem, dlatego też utworzymy detektywa.

public class Detective
{
public string FullName { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
}

 

Detektyw posiada trzy właściwości, jednak nie mają one jeszcze sprecyzowanej dziedziny (co mogą zawierać, a co nie). Żeby dodać wymogi stawiane przez model musimy odpowiednie pola opatrzeć atrybutami dostarczanymi przez DataAnnotations. O DataAnnotations stworzyłem osobny materiał tutaj, jednak na chwilę obecną można powiedzieć, że definiuje ona podstawowe warunki, jakimi musi sprostać model. Po dodaniu atrybutów klasa detektywa wygląda następująco:

using System.ComponentModel.DataAnnotations;
namespace ModelStateCoreWebApi
{

public class Detective
{

[Required]

[MaxLength(50)]

[MinLength(5)]

public string FullName { get; set; }

[Range(1, 120)]

public int Age { get; set; }

public bool Gender { get; set; }
}
}

 

Wiek detektywa musi być z przedziału od 1 do 120, a jego imię wraz z nazwiskiem jest wymagane (nie może dostać wartości null), przy czym otrzymany napis musi składać się z 5-50 znaków.

Skorzystajmy teraz z dostępnej walidacji. Jest ona realizowana przez właściwość ModelState, która dostępna jest z poziomu kontrolerów. Przejdźmy do wygenerowanego wraz z projektem kontrolera ValuesController i usuńmy stamtąd niepotrzebne metody za wyjątkiem metody POST, którą zedytujemy.


// POST api/values
[HttpPost]
public ActionResult<string> Post(Detective model)
{
if (ModelState.IsValid)
{
return "Model ma poprawną wartość";
}
else
return "Niepoprawny model";

}

 

Sama technika sprawdzania poprawności danych jest bardzo prosta. ModelState dostarcza nam właściwości IsValid, która zwróci true, jeżeli model sprosta warunkom narzuconym przez programistę, czyli kiedy dane będą właściwie. Jeżeli jednak model danych będzie nieprawidłowy, będzie łamał zasady narzucone przez atrybuty DataAnnotations, IsValid będzie ustawione na false.

Sprawdźmy działanie w praktyce, wywołując odpowiednie żądanie HTTP POST.

HTTP POST: http://localhost:50938/api/values

 

 

 

 

 

 

 

 

 

 

 

 

Przy normalnie wprowadzonych danych walidacja przechodzi, a my możemy w tamtym miejscu wywoływać kolejne metody realizowane przez system, np. zapis do bazy danych lub integracja z innym systemem. Spróbujmy teraz wprowadzić niewłaściwe dane.

 

Rzeczywiście, dane nie przeszły i dostaliśmy komunikaty, co jest nie tak. Jednak nie to chcieliśmy otrzymać. Powinniśmy dostać stringa o wartości “Nie poprawny model”.

 

Dlaczego tak się dzieje?

W ASP.NET Core twórcy odciążyli nas od potrzeby stosowania ModelState, w naszym kodzie. Sprawdzenie czy ModelState.IsValid było bardzo częstą praktyką, przez co powtarzaliśmy kod. Twórcy zapewnili nam automatyczny mechanizm sprawdzania czy model jest poprawny. Dzieję się tak za sprawą atrybutu dostarczanego do klasy kontrolera [ApiController], który powoduje, że jeżeli ModelState jest niepoprawny zwróci on błąd 400 z komunikatem, co poszło nie tak.

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

 

Jeżeli usuniemy atrybut [ApiController] otrzymamy komunikat zwrotny obsłużony przez nas.

 

 

 

Nie musimy jednak usuwać tego atrybutu. Drugim sposobem na przywrócenie nam sterowania nad nieprawidłowym modelem otrzymanych danych jest zmodyfikowanie ustawień w pliku Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<ApiBehaviorOptions>(options =>
options.SuppressModelStateInvalidFilter = true
);
}

 

W powyższej metodzie ustawiliśmy właściwość SuppressModelStateInvalidFilter na true, co powoduje wyłączenie domyślnego i automatycznego reagowania na niepoprawny model, przez wysyłanie w odpowiedzi 400.

 

Podsumowując

ModelState to bardzo fajna technika, która odciąża programistę od ręcznego sprawdzania poprawności danych. Działa on na warstwie kontrolera i przeprowadza początkowy proces walidacji, operując na DataAnnotations. Jeżeli walidacja nie jest poprawna zwróci nam HTTP 400, z odpowiednim komunikatem, co poszło nie tak (dopiero w ASP.NET Core), lub jeżeli wyłączymy tę opcję możemy ręcznie sterować procesem błędnej walidacji. ModelState jednak nie wyręczy nas całkowicie od sprawdzania czy w aplikacji wszystko działa jak należy, niektóre elementy będziemy musieli nadal sprawdzać sami.

Social media & sharing icons powered by UltimatelySocial