我正在阅读Freeman和Sanderson的Pro ASP.NET MVC3框架书,对一些代码有疑问。这可能是一个新手问题,但我发现人们对本书中的例子有用的问题很有用。
SportsStore示例中的Cart控制器将Checkout操作标记为HttpPost,但AddToCart和RemoveFromCart操作都未标记为HttpPost。但他们都收到表单提交并修改底层的Cart模型。难道没有定义什么时候使用HttpPost?
当然,在此示例中,模型更改不会保留在数据库中,但这只是为了简单起见。该模型在AddToCart和RemoveFromCart操作中的更改与Checkout操作一样多。
btw - 无论有没有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());
}
}
}
答案 0 :(得分:0)
如果我记得这本书,Sanderson& pal使用特殊的ModelBinder来访问基于会话的Cart对象......不是吗?
从技术上讲,本书中的实现并不正确,因为这些操作不会影响底层应用程序。基于会话的存储是易变的,因此动作不代表永久性的变化。
真正的应用程序可能会使用幂等HttpPut和HttpDelete(或非幂等HttpPost)来添加/删除购物车项目操作。但是,真正的应用程序可能不会将这些内容保存在易失性会话存储中
我认为本书只是试图向您展示应用程序的示例,而不会创建大量的存储表。
答案 1 :(得分:0)
我相信你的代码中的结帐ActionResult是用[HttpPost]修饰的,因为CartController中还有一个默认为HttpGet
的Action public ViewResult Checkout()
{
return View(new ShippingDetails());
}
此外,AddToCart和RemoveFromCart操作都没有标记为HttpPost,因为由于模型绑定,它们无法通过HttpGet获得。
答案 2 :(得分:-1)
在我有限的经验中,为了保持一致,我会说它们应该被标记为[HttpPost]。在本书的其他示例中,有两种动作方法具有相同的名称,例如
public ActionResult Edit(intId)
{
...
}
[HttpPost]
public ActionResult Edit(EditViewModel model)
{
...
}
因此,将HttpPost方法标记为可以轻松命名方法。在你给出的例子中,只有一个AddToCart方法,所以可能没有必要区分。