Trabajando con entidades y validaciones en NancyFx (II)
En la entrada anterior, preparamos nuestro proyecto de ASP.NET con NancyFx.
Cargamos los paquetes de NuGet que íbamos a utilizar, y preparamos nuestra aplicación para albergar las entidades, validaciones y los módulos de NancyFx.
También creamos una entidad y una validación.
Nos quedamos pendientes por lo tanto, de preparar nuestro módulo de NancyFx y de ver como funciona el proceso de validación de la entidad.
Antes de ponernos con el módulo de NancyFx, vamos a preparar un par de clases para simular una persistencia de datos en memoria, que haga un fake de funcionalidad para poder jugar con la información que enviaremos y recibiremos de la API REST.
Crearé una clase a la que ha llamada PeopleInMemory.
namespace Blog_DotNet_NancyFx_Entities_and_Validations { using System.Collections.Generic; using System.Linq; using Blog_DotNet_NancyFx_Entities_and_Validations.Entities; public class PeopleInMemory { private object _lock = new object(); private List<PersonEntity> _people; public PeopleInMemory() { _people = new List<PersonEntity>(); } public void RebuildLocalizations() { lock (_lock) { _people = new List<PersonEntity>(); } } public void Add(PersonEntity personEntity) { lock (_lock) { _people.Add(personEntity); } } public List<PersonEntity> GetAll() { return _people.ToList(); } } }
También crearé una clase Singleton que instancie la clase anterior con la que trabajaremos para añadir registros y para obtener todos los registros que tenemos almacenados en memoria.
La clase SingletonPeopleInMemory queda de la siguiente manera:
namespace Blog_DotNet_NancyFx_Entities_and_Validations { using System; public class SingletonPeopleInMemory { private static volatile PeopleInMemory instance; private static Object syncRootObject = new Object(); public static PeopleInMemory Instance { get { if (instance == null) { lock (syncRootObject) { if (instance == null) { instance = new PeopleInMemory(); } } } return instance; } } } }
Ahora sí, vamos a ponernos con el módulo de NancyFx.
Crearemos una clase que alojaremos en el directorio Modules y cuyo nombre es PersonModule.
namespace Blog_DotNet_NancyFx_Entities_and_Validations.Modules { using Blog_DotNet_NancyFx_Entities_and_Validations.Entities; using Nancy; using Nancy.ModelBinding; using Nancy.Validation; using System; using System.Collections.Generic; using System.Threading.Tasks; public class PersonModule : NancyModule { public PersonModule() { Get[@"/person/list", runAsync: true] = async (_, cancellationToken) => { List<PersonEntity> people = await GetPeopleAsync(); return Response.AsJson<List<PersonEntity>>(people); }; Post["/person", runAsync: true] = async (_, cancellationToken) => { var personEntity = this.Bind<PersonEntity>(); var validationResult = this.Validate(personEntity); if (!validationResult.IsValid) { var errors = String.Empty; foreach (var error in validationResult.Errors) { errors += error.Value[0].ErrorMessage + Environment.NewLine; } var response = (Response)errors; response.StatusCode = HttpStatusCode.BadRequest; return response; } return await PostPeopleAsync(personEntity); }; } private async Task<List<PersonEntity>> GetPeopleAsync() { return await Task.FromResult(SingletonPeopleInMemory.Instance.GetAll()); } private async Task<HttpStatusCode> PostPeopleAsync(PersonEntity personEntity) { try { SingletonPeopleInMemory.Instance.Add(personEntity); return await Task.FromResult(HttpStatusCode.Created); } catch (Exception) { return await Task.FromResult(HttpStatusCode.InternalServerError); } } } }
Si observamos nuestro módulo detenidamente, veremos que tenemos una petición GET en /person/list, y una petición POST en /person.
La petición GET, devuelve un JSON tal y como puede verse, gracias a Response.AsJson<>.
Por otra parte, cuando hacemos una llamada POST, validamos los datos que han entrado.
Si son correctos, llamamos al Singleton para persistir la información que se recibe.
Si no son correctos, en este caso devolvemos un Bad Request junto con los mensajes de error.
Veamos esto en tiempo de ejecución con Fiddler.
He realizado dos peticiones POST para meter un par de datos en memoria:
De forma adicional, y con un navegador Web (podríamos hacerlo con Fiddler también), he realizado una petición GET para obtener los datos que he introducido.
Como podemos observar, nuestra API REST funciona perfectamente.
Ahora vamos a pasar a introducir algún dato que no sea válido para forzar la validación y obtener la respuesta correspondiente por parte de NancyFx.
Para ello y desde Fiddler, he realizado la siguiente petición que nos devuelve un 400 Bad Request (tal y como teníamos pensado inicialmente):
La respuesta que obtenemos es de esta forma:
Si prestamos atención a la parte señalada en rojo, veremos que la validación no se ha producido correctamente y que la información que obtenemos nos puede ayudar a ajustar nuevamente nuestra petición para enviarla de forma adecuada.
Con esto, hemos terminado esta parte de trabajo con entidades.
Para obtener más información sobre NancyFx y FluentValidation, accede a la Wiki oficial de NancyFx.
Podrás acceder al código fuente de este ejemplo en mi repo de GitHub, en este enlace.
¡Happy Coding!
2 Responsesso far
Gran noticia,Jorge, festival de posts veraniegos!! Gracias, después de más de dos años sin posts y sin MVP, es una alegría vuelva a la comunidad.
Hablando desde la ignorancia, no veo aún NancyFx.
Con ASP.NET MVC – WebApi podemos crear API Rest, no? Y hostear en IIS ?
Qué aporta NancyFx ? es como un NodeJs?
Más allá, cómo securizar ese tipo de servicios.
sin duda, un ejemplo real world con código fuente, una aplicación real donde sea la potencia de nancyfx, eso clarificaría.
Saludos.
¿Y cuando se maneja un objeto VIEW, como se usaria la validación de campos con este componente en NancyFx?