I am new to Asp.net MVC and am having problems with the following code.
@model SportsStore.Domain.Entities.ShippingDetails
@{
ViewBag.Title = "SportsStore: Checkout";
}
<h2>Check out now</h2>
Please enter your details and we'll send your goods right away!
@using (Html.BeginForm("Checkout", "Cart"))
{
@Html.ValidationSummary()
<h3>Ship to</h3>
<div>Name: @Html.EditorFor(x => x.Name)</div>
<h3>Address</h3>
<div>Line 1: @Html.EditorFor(x => x.Line1)</div>
<div>Line 2: @Html.EditorFor(x => x.Line2)</div>
<div>Line 3: @Html.EditorFor(x => x.Line3)</div>
<div>City: @Html.EditorFor(x => x.City)</div>
<div>State: @Html.EditorFor(x => x.State)</div>
<div>Zip: @Html.EditorFor(x => x.Zip)</div>
<div>Country: @Html.EditorFor(x => x.Country)</div>
<h3>Options</h3>
<label>
@Html.EditorFor(x => x.GiftWrap)
Gift wrap these items
</label>
<p align="center">
<input class="actionButtons" type="submit" value="Complete order"/>
</p>
}
I expect the input of type submit to call the Post version Checkout action from my controller, shown below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using SportsStore.WebUI.Models;
namespace SportsStore.WebUI.Controllers
{
public class CartController : Controller
{
private IProductsRepository repository;
private IOrderProcessor orderProcessor;
public CartController(IProductsRepository repo, IOrderProcessor proc)
{
repository = repo;
orderProcessor = proc;
}
[HttpPost]
public ViewResult Checkout(ShippingDetails shippingDetails, Cart cart)
{
var test = Request.Form["Line1"];
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 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);
}
[HttpGet]
public ViewResult Checkout()
{
return View(new ShippingDetails());
}
private Cart GetCart()
{
Cart cart = (Cart)Session["Cart"];
if (cart == null)
{
cart = new Cart();
Session["Cart"] = cart;
}
return cart;
}
}
}
However, whenever I press this input button, nothing happens.
Could anybody please tell me what is wrong? I thought an input button of type submit would call the post version of the action, but apparently this is not working.
Edit:
I tried disabling all javascript in the browser, but this does not solve the problem.
Here is my routing info:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(null,"", // Only matches the empty URL (i.e. /)
new
{
controller = "Product",
action = "List",
category = (string)null,
page = 1
}
);
routes.MapRoute(null, "Page{page}", new { Controller = "Product", action = "List" });
routes.MapRoute(null,"{category}", // Matches /Football or /AnythingWithNoSlash
new { controller = "Product", action = "List", page = 1 });
routes.MapRoute(null,
"{category}/Page{page}", // Matches /Football/Page567
new { controller = "Product", action = "List" }, // Defaults
new { page = @"\d+" } // Constraints: page must be numerical
);
routes.MapRoute(null, "{controller}/{action}");
}
And here is my ApplicationStart method in Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
}
I don’t really know what else to do. If anybody has any ideas, please let me know.
Why do you expect something like that? You don’t seem to have indicated it on your form:
If you do not explicitly specify the action and controller name to be called when rendering the form, then the same action as the one that rendered this view will be called with HttpPost. So for example if this view was rendered from the
Indexaction, then if you useHtml.BeginForm, ASP.NET MVC will look for an Index action with HttpPost on the same controller.For example:
That’s the convention. If you don’t want to follow the convention you need to use the overload of Html.BeginForm which allows you to specify the action and controller that you want to be invoked.