MVC3 - Razor - Transfer Data Between Views or DropDown Lists
I want to let a user select a Seating Area via drop-down list or Venue Map [lets just say drop-down list for now] After the user Selects the seating area and hits the submit button, I would like to load another view with the tables for the seating area they selected.
Here is the part of the Data Model .EDMX for the Seating Area and Table [Tables] (just to show you the relationships are set.)
I tried the MVC3 Futures Serialization - Could not get it to work the way I wanted
I looked into KnockoutJS after seeing this example on their website: http://knockoutjs.com/examples/cartEditor.html and how when you choose a category the products change in the drop-down list next to it. (This method would work for now) but could not figure out from the example how it is pulling the data in)
Ultimately, I want to have 2 Views (or one view that just hides the seating area selection and shows the table choices)
Razor View - User will click [Assign Table] to get to the first view (view #1)
View #1: Choose Seating Area [Controller Code]
public ActionResult AddTableTo(int id)
{
var tableService = id;
var tableServiceName = db.VipServices.Single(x => x.VipServiceId == id);
var venueId = tableServiceName.Event.Venue.VenueId;
ViewData["TablerServiceNameFor"] = tableServiceName.Customer.FullName;
ViewData["TableServiceFor"] = tableService;
ViewBag.SeatingAreaId = new SelectList(db.SeatingAreas.Where(y => y.VenueId == venueId), "SeatingAreaId", "AreaName");
return View();
}
That generates this razor view with a drop-down:
I am going to eventually make this a Map of the venue showing the different levels and seating areas.
After they select the seating area... I want to redirect to a different View retaining the data (SeatingAreaID) from the previous view, or hide seating area selection and show the tables in that seating area.
[Partial Controller Code for View #2]
ViewBag.TableId = new SelectList(db.Tables.Where(y => y.SeatingAreaId == seatingAreaId), "TableId", "TableName");
Please let me know what is the B开发者_高级运维EST way to handel this. I am sure I will be using this more than just this one time. Probably very valuable to know how to do.
This may be a very easy thing to do, but I can not find anything anywhere on how to do this the way I would like. And the SeatingAreaID is not the only variable I will be wanting to transfer between views, I need to keep the VenueID & VipServiceID transferring along also, at the end of the selection of the table the Controller is going to create a Many-To-Many Relationship between the Table and the VipService and redirect back to the VipService Details Page.
Thank you for your time and help. Tim
I went ahead and just did it the only way I know of, probably not the best way, but it worked. If anyone has a better way of accomplishing this let me know.
What I did:
After the user selects the Add Table Button.
[Controller 1a]
public ActionResult AddTableTo(Int64 id)
{
var tableService = id;
var tableServiceName = db.VipServices.Single(x => x.VipServiceId == id);
var venueId = tableServiceName.Event.Venue.VenueId;
ViewData["TablerServiceNameFor"] = tableServiceName.Customer.FullName;
ViewData["TableServiceFor"] = tableService;
ViewBag.SeatingAreaId = new SelectList(db.SeatingAreas.Where(y => y.VenueId == venueId), "SeatingAreaId", "AreaName");
return View();
}
[View #1]
@model ShadowVenue.ViewModels.VipSeatingAreaViewModel
@{
ViewBag.Title = "Select Seating Area";
}
<h2>Select Seating Area For:</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
<fieldset>
<legend>@ViewData.Eval("TablerServiceNameFor")'s Table(s)</legend>
<div class="editor-label">
Select Seating Area
</div>
<div class="editor-field">
@Html.DropDownList("SeatingAreaId", String.Empty)
</div>
@Html.Hidden("VipServiceId", ViewData.Eval("TableServiceFor"))
<p>
<input type="submit" name="nextButton" value="Next" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to Table Service Details", "Details", new { Id = ViewData.Eval("TableServiceFor") })
</div>
[Controller 1b]
[HttpPost]
[Authorize(Roles = "Administrator, SuperUser")]
public ActionResult AddTableTo(VipSeatingAreaViewModel seatingArea, string nextButton)
{
if (nextButton != null)
return RedirectToAction("AddTableToTable", new { sid = seatingArea.SeatingAreaId, vid = seatingArea.VipServiceId });
return View(seatingArea);
}
Controller 1b Redirects to Action AddTableToTable [Controller 2] and sends along the selected SeatingAreaId and the VipServiceId
[Controller 2]
public ActionResult AddTableToTable(Int16 sid, Int64 vid)
{
var tableService = vid;
var tableServiceName = db.VipServices.Single(x => x.VipServiceId == vid);
var seatingAreaId = sid;
var seatingArea = db.SeatingAreas.Single(x => x.SeatingAreaId == sid);
ViewData["TablerServiceNameFor"] = tableServiceName.Customer.FullName;
ViewData["TableServiceFor"] = tableService;
ViewData["SeatingAreaName"] = seatingArea.AreaName;
ViewBag.TableId = new SelectList(db.Tables.Where(y => y.SeatingAreaId == seatingAreaId), "TableId", "TableName");
return View();
}
Renders View #2 [View #2]
@model ShadowVenue.ViewModels.VipTableViewModel
@{
ViewBag.Title = "Select Table";
}
<h2>Select Table For:</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
<fieldset>
<legend>@ViewData.Eval("TablerServiceNameFor")'s VIP Service</legend>
<div class="editor-label">
Select Table in the <b>@ViewData.Eval("SeatingAreaName")</b> Seating Area
</div>
<div class="editor-field">
@Html.DropDownList("TableId", String.Empty)
</div>
@Html.Hidden("VipServiceId", ViewData.Eval("TableServiceFor"))
<p>
<input type="submit" name="backButton" value="Back" />
<input type="submit" name="nextButton" value="Next" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to Table Service Details", "Details", new { Id = ViewData.Eval("TableServiceFor") })
</div>
I give the user the option to go Back to select a different Seating Area or to Select the Table to add to the VIP Service. After they choose the view post to [controller 2b] where it adds a Many-To-Many relationship for the VipService and the Table.
[controller 2b]
[HttpPost]
[Authorize(Roles = "Administrator, SuperUser")]
public ActionResult AddTableToTable(VipTableViewModel model, string backButton)
{
if (backButton != null)
{
return RedirectToAction("AddTableTo", new { id = model.VipServiceId });
}
if (ModelState.IsValid)
{
VipService v = db.VipServices.Single(x => x.VipServiceId == model.VipServiceId);
Table t = db.Tables.Single(x => x.TableId == model.TableId);
v.Tables.Add(t);
db.SaveChanges();
return RedirectToAction("Details", new { id = model.VipServiceId });
}
else
{
return View(model);
}
}
Eventually I am going to make the DropDown List into Visuals of the Venue so the user can just touch (click) the area and tables they want to assign.
Once again, If anyone has a better solution please let me know.
Thank you.
First things first I would highly recommend you to stop using the ViewData dictionary property to pass data from your controllers to views. Any time you can use ViewData you could also use a ViewModel. With the ViewModel you have the compiler helping you rather than just passing keys into the dictionary.
A good read can be found here: http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
After getting comfortable with using the ViewModel pattern you should easily be able to move data from view to view.
精彩评论