Пример MVC3 SportsStore: должен ли AddToCart быть помечен как HttpPost? - PullRequest
0 голосов
/ 22 февраля 2012

Я читаю книгу Free ASP.NET MVC3 Framework от Freeman и Sanderson и у меня есть вопрос по поводу некоторого кода. Это может быть вопрос новичка, но я нашел полезными вопросы людей относительно примеров в этой книге.

Контроллер Cart в примере SportsStore помечает действие Checkout как HttpPost, но ни действия AddToCart, ни RemoveFromCart не помечаются как HttpPost. Но они оба получают отправленные формы и изменяют основную модель корзины. Разве это не определение того, когда использовать HttpPost?

Конечно, изменения модели не сохраняются в базе данных в этом примере, но только для простоты. Модель изменяется в действиях AddToCart и RemoveFromCart столько же, сколько и действие Checkout.

Кстати - код работает одинаково с HttpPost или без него. Так что это в основном вопрос о лучших практиках.

Ниже приведен последний класс контроллера из книги:

namespace SportsStore.WebUI.Controllers
{
    public class CartController : Controller
    {
        private IProductRepository repository;
        private IOrderProcessor orderProcessor;

        public CartController(IProductRepository repo, IOrderProcessor proc)
        {
            repository = repo;
            orderProcessor = proc;
        }

        public RedirectToRouteResult AddToCart(Cart cart, int productID, string returnUrl) {
            Product product = repository.Products
                .FirstOrDefault(p => p.ProductID == productID);

            if (product != null) {
                cart.AddItem(product, 1);
            }
            return RedirectToAction("Index", new {returnUrl});
        }


        public RedirectToRouteResult RemoveFromCart(Cart cart, int productId, string returnUrl)
        {
            Product product = repository.Products
                .FirstOrDefault(p => p.ProductID == productId);

            if (product != null)
            {
                cart.RemoveLine(product);
            }
            return RedirectToAction("Index", new { returnUrl });
        }

        public ViewResult Index(Cart cart, string returnUrl)
        {
            return View(new CartIndexViewModel
            {
                Cart = cart,
                ReturnUrl = returnUrl
            });
        }

        public ViewResult Summary(Cart cart)
        {
            return View(cart);
        }

        [HttpPost]
        public ViewResult Checkout(Cart cart, ShippingDetails shippingDetails)
        {
            if (cart.Lines.Count() == 0)
            {
                ModelState.AddModelError("", "Sorry your cart is empty");
            }

            if (ModelState.IsValid)
            {
                orderProcessor.ProcessOrder(cart, shippingDetails);
                cart.Clear();
                return View("Completed");
            }
            else
            {
                return View(shippingDetails);
            }
        }

        public ViewResult Checkout()
        {
            return View(new ShippingDetails());
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 22 февраля 2012

Я считаю, что оформление ActionResult в вашем коде оформлено с помощью [HttpPost], так как есть также действие, доступное в CartController , которое по умолчанию установлено в HttpGet

    public ViewResult Checkout()
    {
        return View(new ShippingDetails());
    }

также действия AddToCart и RemoveFromCart не помечаются как HttpPost, поскольку они не будут доступны через HttpGet из-за привязки модели.

0 голосов
/ 22 февраля 2012

В моем ограниченном опыте я бы сказал, что они должны быть помечены как [HttpPost] для согласованности. В других примерах в книге встречаются ситуации, когда два метода действия имеют одно и то же имя, например

public ActionResult Edit(intId)
{
...
}

[HttpPost]
public ActionResult Edit(EditViewModel model)
{
...
}

Таким образом, маркировка метода HttpPost как такового позволит легко называть методы. В приведенном вами примере есть только 1 метод AddToCart, поэтому, вероятно, не было необходимости проводить различие.

0 голосов
/ 22 февраля 2012

Если я вспомню из книги, Sanderson & pal использует специальный ModelBinder для доступа к объекту Cart на основе сеанса ... не так ли?

Технически реализация в книге не является неправильной, поскольку действия не влияют на основное приложение. Сеансное хранилище является изменчивым, поэтому действия не должны представлять постоянное изменение.

Реальное приложение может использовать идемпотентные HttpPut и HttpDelete (или неидемпотентный HttpPost) для действий добавления / удаления элемента корзины. Однако реальное приложение, вероятно, не будет хранить эти вещи в энергозависимом хранилище сеансов.

Я думаю, что книга просто пытается показать вам примеры приложений без создания тонны таблиц хранения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...