Pull to refresh

Создаем первое приложение на NancyFX. Часть четвертая. Продолжаем работу с модулями

Reading time4 min
Views6.6K
В предыдущей статье Создаем первое приложение на NancyFX. Часть третья. Модули Nancy. мы познакомились с модулями Nancy. В данной статье мы продолжим их изучение.


Как я упоминал в предыдущей статье Nancy использует свойство запроса Request.Form. Form — это DynamicDictionary значения которого берутся из тела запроса. Для того чтобы Nancy корректно распарсило значения передаваемые в теле запроса нужно верно задать Content-Type: application/x-www-form-urlencoded. Если Content-Type был задан не верно, не удивляйтесь если в качестве значений Вам будут приходить nullы. Автоматически Nancy парсит только данные в формате x-www-form-urlencoded. И так давайте попробуем создать модуль обрабатывающий Post запрос. Для начала создадим следующий класс:

namespace NancyFxApplication
{
    public class Dish
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsSpicy { get; set; }
    }
}


и класс

using System.Collections.Generic;

namespace NancyFxApplication
{
    public static class DishesRepository
    {
        public static List<Dish> Dishes = new List<Dish>
                {
                    new Dish { Id=1, Name = "Porridge", IsSpicy = false},
                    new Dish {Id = 2, Name = "Chili", IsSpicy = true},
                    new Dish {Id = 3, Name = "Icecream", IsSpicy = false}
                };

        public static List<Dish> GetAllDishes()
        {
            return Dishes;
        }

        public static void AddDish(Dish dish)
        {
            Dishes.Add(dish);
        }
    }
}


далее определим новый модуль Nancy

using Nancy;

namespace NancyFxApplication
{
    public class DishModule : NancyModule
    {
        public DishModule() : base("/Dish")
        {
            Post["/Add"] = ctx =>
                {
                    var dish = new Dish {Id = Request.Form.Id, Name = Request.Form.Name, IsSpicy = Request.Form.IsSpicy};
                    DishesRepository.AddDish(dish);
                    return new Response { StatusCode = HttpStatusCode.Accepted };
                };

            Get["/GetAll"] = ctx => Response.AsJson(DishesRepository.GetAllDishes());

        }
    }
}


Теперь после запуска приложения и перехода по роуту Dish/GetAll получаем следующий результат
[
    {"Id":1,"Name":"Porridge","IsSpicy":false},
    {"Id":2,"Name":"Chili","IsSpicy":true},
    {"Id":3,"Name":"Icecream","IsSpicy":false}
]


Теперь воспользуемся фиддлером и сделаем запрос Post к роуту Dish/Add



И снова делаем Get запрос о роуту Dish/GetAll и получаем
[
    {"Id":1,"Name":"Porridge","IsSpicy":false},
    {"Id":2,"Name":"Chili","IsSpicy":true},
    {"Id":3,"Name":"Icecream","IsSpicy":false},
    {"Id":1,"Name":"Borsh","IsSpicy":false}
]


Как видите все работает. Однако x-www-form-urlencoded хорош только для простых форматов данных. Но для сложных данных он не подходит. Для передачи сложных форматов данных на помогут JSON и XML. Давайте модифицируем класс Dish следующим образом:

public class Dish
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsSpicy { get; set; }
        public List<Ingridients> Ingridientses { get; set; }
    }


Добавим в наш проект класс:
public class Ingridients
    {
        public int Id { get; set; }
        public string Name { get;set; }
    }


Nancy включает в себя два дессериализатора для двух семейств контент типов. Для JSONа(«application/json», «text/json», «application/vnd...+json») и XML(«application/xml»,«text/xml», «application/vnc...+xml»). Nancy также может быть расширена для работы с другими типами контентов, такими как Protocol Buffers, CSV и т.д. Вы даже можете написать свой собственный дессериализатор для своего типа контента.
И так давайте модифицируем наш модуль таким образом чтобы он мог принимать данные в формате JSON

using Nancy;
using Nancy.ModelBinding;

namespace NancyFxApplication
{
    public class DishModule : NancyModule
    {
        public DishModule() : base("/Dish")
        {
            Post["/Add"] = ctx =>
                {
                    var dish = this.Bind<Dish>();
                    DishesRepository.AddDish(dish);
                    return new Response { StatusCode = HttpStatusCode.Accepted };
                };

            Get["/GetAll"] = ctx => Response.AsJson(DishesRepository.GetAllDishes());

        }
    }
}


Метод Bind — экстеншен методкоторый находится в пространстве имен Nancy.ModelBinding. Он позволяет Вам маппить ваш JSON на Ваш бизнес объект. Теперь если вы запустите приложение и выполните в фиддлере следующий запрос POST на роут "/Add"



А потом выполним Dish/GetAl то получим
[
{"Id":1,"Name":"Porridge","IsSpicy":false,"Ingridientses":null},
{"Id":2,"Name":"Chili","IsSpicy":true,"Ingridientses":null},
{"Id":3,"Name":"Icecream","IsSpicy":false,"Ingridientses":null},
{"Id":12,"Name":"Salad","IsSpicy":false,
"Ingridientses":[{"Id":1,"Name":"Salad"}]}
]


Как видите наша модель принимается приложением и записывается в наш фейковый репозиторий.
В завершении хочется оговорится про дессириализацию формата XML. Для использования Bind свойства бизнес объекта необходимо промаркировать атрибутами как мы это делаем при обычной XML сериализации. При этом у нас будет гарантия что объект будет распасен корректно.

В следующей статье мы рассмотрим с Вами графический движок Super Simple View Engine. Жду от Вас Комментариев и вопросов.
Tags:
Hubs:
+5
Comments5

Articles