Reputation: 660
I am displaying an list of Items for a given Order. When a user clicks Add Item I redirect to the Item / Create page. This page collects that necessary input but also needs to know the order id that the item belongs to. What is the appropriate way to pass the OrderID to the Item / Create so that it survives the form post when the newly created item is saved.
I've played with TempData and writing the id out on the detail page via Html.Encode(). It gets me part of the way there in that the id shows up on the item form but the value is lost when the form submits and posts. I suppose because its not part of the formcollection. I am guessing my workaround is not the best way and would like to know if anyone can point out the proper way to do this in asp.net mvc.
Upvotes: 5
Views: 4790
Reputation: 13837
I do this by creating a new route for the Item controller that includes the OrderId. It doesn't make sense to have an Item without an Order, so the OrderId is required using the constraints parameter.
routes.MapRoute(
"OrderItems",
"Item/{action}/{orderId}/{id}",
new { controller = "Item" },
new { orderId = @"d+" }
);
So the url would look like http://<sitename>/Item/Create/8
, where 8 is the OrderId for which to create an item. Something similar could be done for Delete action routes with http://<sitename>/Item/Delete/8/5
, where 8 is the OrderId and 5 is the ItemId.
Your Action methods would look like this:
public ActionResult Create(int orderId)
public ActionResult Delete(int orderId, int id)
You could also set it up so that the urls looked like http://<sitename>/Order/8/Item/Create
and http://<sitename>/Order/8/Item/Delete/5
if that seems to more clearly show what's going on.
Then the route would look like this:
routes.MapRoute(
"OrderItems",
"Order/{orderId}/Item/{action}/{id}",
new { controller = "Item" },
new { orderId = @"d+" }
);
Upvotes: 3
Reputation: 180787
To round-trip a field that's not part of the normal data entry, I generally use a hidden field in the view, like this:
<%= Html.Hidden("OrderID", Model.OrderID) %>
It looks like a form field, acts like a form field, but the user cannot see it. Make sure you push the correct OrderID into your model from the controller.
Upvotes: 0
Reputation: 9580
I've used this sequence (sorry if there are mistakes, I took this from a working example and modified it for your question):
1) In the Order.Details view (assume Model is of type Order):
...
<%= Html.ActionLink("Create New Item", "Create", "OrderItem", new { orderId = Model.ID }, null)%>
...
2) In the OrderItem.Create action:
public ActionResult Create(int orderId)
{
ViewData["orderId"] = orderId;
return View();
}
3) In the OrderItem.Create view:
...
<% using (Html.BeginForm(new { orderId = ViewData["orderId"] }))
...
4) In the OrderItem.Create POST action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(int orderId)
{
// omitted code to create item, associated with orderId
return RedirectToAction("Details", "Order", new { orderId = orderId });
}
If anyone can think of how to improve on this, or of a better way altogether, please chime in, I'm sort of new to this myself so I'd like to improve.
Upvotes: 0