EDIT: I see why it doesn't run twice. I have the "Ajax.BeginForm()" call inside the div that is being wiped out. I moved that to the Partial View. Now it works great in Internet Explorer, but not in Firefox or Chrome. The Part is saved to the db, but the View that is returned is not a Partial View.
I am working on an "edit" page for a "Vehicle." I have a list of Parts that can be added to the Vehicle. The parts are shown in a partial view. The partial view is basically a DropDownList with some javascript.
What I want is for the partial view to update when the user clicks the "Add Part To Vehicle" button. What is happening is that update causes the entire page to be filled with the partial view.
Here are my latest files:
Controller:
[HttpGet]
public ActionResult _AddPartToVehicle(IList<ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel> vehicleEditAddPartToVehicleViewModel)
{
return View(vehicleEditAddPartToVehicleViewModel);
}
[HttpPost]
public ActionResult _AddPartToVehicle(Guid partID, Guid vehicleID)
{
Vehicle vehicle = db.Vehicles.Find(vehicleID);
Part part = db.Parts.Find(partID);
//protect against concurrency (what if someone has deleted this part or this vehicle since the form was loaded?)
try
{
if ((vehicle != null) && (part != null))
{
vehicle.Parts.Add(part);
db.SaveChanges();
ViewBag.VehicleID = vehicleID;
return PartialView(GetPartsForThisVehicle(vehicle));
}
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to add part to vehicle. Try again, and if the problem persists contact your system administrator.");
}
Partial View:
@model IList<ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel>
@section scripts{
}
@using (Ajax.BeginForm("_AddPartToVehicle", new AjaxOptions() { UpdateTargetId = "divAddPartToVehicle", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace }))
{
<fieldset>
<legend>Parts For This Vehicle</legend>
@if (Model != null)
{
if (Model.ToList().Count > 0)
{
<div class="editor-field">
<table>
<tr>
<th>Part</th>
<th></th>
</tr>
@foreach (var part in Model)
{
if (part.OnVehicle)
{
<tr>
<td>
@part.Name
</td>
<td>
@Html.ActionLink("Details", "Edit", "Part", new { id = part.PartID }, null) |
@Html.ActionLink("Remove", "RemoveVehiclePart", new { partID = part.PartID, vehicleID = ViewBag.VehicleID })
</td>
</tr>
}
}
</table>
</div>
}
}
<table class="layouttable">
<tr>
<td>
<div title="" id="tooltip">
@{
IList<ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel> partsNotOnVehicle = new List<ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel>();
foreach (var part in Model)
{
if (!part.OnVehicle)
{
ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel partNotOnVehicle = new ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel();
partNotOnVehicle.Cost = part.Cost;
partNotOnVehicle.Name = part.Name;
partNotOnVehicle.Notes = part.Notes;
partNotOnVehicle.OnVehicle = part.OnVehicle;
partNotOnVehicle.PartID = part.PartID;
partsNotOnVehicle.Add(partNotOnVehicle);
}
}
@Html.DropDownList("partID", partsNotOnVehicle.Select(m => new SelectListItem() { Text = m.Name, Value = m.PartID.ToString() }), new { @class = "dropdown", onchange = "GetDivTitle(this.value)", onmouseover = "GetDivTitle(this.value)" })
}
</div>
</td>
</tr>
<tr>
<td>
<div id="divAddPartToVehicle">
<input type="hidden" name="vehicleID" value="@ViewBag.VehicleID") />
<input type="submit" value="Add Part To Vehicle"/>
</div>
</td>
</tr>
</table>
</fieldset>
}
<script type="text/javascript">
function GetDivTitle(value) {
document.getElementById("tooltip").title = GetDropDownNotes(value);
}
function GetDropDownNotes(value) {
switch (value) {
@foreach (ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel item in Model)
{
<text>
case '@item.PartID.ToString()':
return '@item.Notes.Replace("\'", "").Replace("\"", "").Replace("\n", "").Replace("\r", "")';
break;
</text>
}
}
}
</script>
View:
@section scripts {
@Content.Script("jquery.validate.min.js", Url)
@Content.Script("jquery.validate.unobtrusive.min.js", Url)
@Content.Script("jquery.unobtrusive-ajax.min.js", Url)
}
...
<div id="divAddPartToVehicle">
@Html.Partial("_AddPartToVehicle", (IList<ShopLog.ViewModels.VehicleEditAddPartToVehicleViewModel>)ViewBag.Parts)
</div>
...
Yay! I win! I had all kinds of Form issues. I was putting @Html.BeginForm inside of @Html.BeginForm and the same for Ajax.BeginForm.
Once I fixed those issues, it worked like a charm!