Подобный MVC 3 - Аякс. BeginForm делает полную почту назад, но я проверил, что ссылка на jquery.unobtrusive-ajax.min.js действительно существует на моей странице. Плюс, это работает отлично в IE 9, но в Firefox и Хроме, я получаю просто частичное представление как полную веб-страницу вместо того, чтобы заменить отделение содержанием того частичного представления.
Я все еще довольно плохо знаком с MVC3, таким образом, я уверен, что это - что-то простое.
Резюме:
В моей странице есть несколько различных .cshtml файлов, которые становятся видимыми, поскольку пользователи нажимают на ссылки. В файле EquipmentData.cshtml у меня есть dropdown, который, на изменении, делает ajax обратную передачу диспетчеру, чтобы загрузить шаблон редактора в отделение.
В том шаблоне редактора (StorageTankData.cshtml), там список данных и имеет заполнителя для отредактировать шаблона для единственного пункта (StorageTank.cshtml). StorageTank.cshtml инициализируется для вставки новой (с id ноля); когда пользователь щелкает по одному из пунктов в списке данных, мы вызываем диспетчера снова, чтобы получить частичное представление StorageTank.cshtml для того определенного пункта и заменить тот HTML в отредактировать отделение.
Все это работает отлично. В шаблоне StorageTank.cshtml у меня есть Аякс. Начните форму, которая отправляет к различному действию диспетчера, чтобы сохранить данные о резервуаре для хранения, и затем называет тот же самый метод диспетчера, чтобы получить частичное представление StorageTankData.cshtml. Идея состоит в том, что мы освежим список пунктов и перезагрузим отредактировать форму к режиму вставки и заменим это в отделение.
Это хорошо работает в IE, но в Хроме и Firefox я получаю просто частичное представление на странице вместо целой страницы со случаем замены. Я думаю , это - потому что мой экономить обратную передачу идет в различный метод диспетчера, чем тот, который производит всю страницу, но я не уверен, что сделать об этом.
То, что я вижу в IE, - то, что URL остается "/, Редактируют" (действие, которое управляет целой страницей), и замена работает отлично. В Хроме и FF, URL изменяется на мое "/SaveStorageTank" действие вместо этого. Так, я думаю, что это объясняет почему те показ браузера просто частичное представление, когда сделано. То, что я не понимаю, - то, почему они не идут вперед и делают заменение.
Я не вижу ошибок или в Поджигателе или в Хроме до окончания перепоказа. (Конечно, они сбиты с толку на $ (документ) .ready... наполняют, потому что тому частичному представлению не загрузили файлы jQuery). Но, возможно я просто не знаю, где/как искать те ошибки.
Хорошо, жаль о длинной истории. Вот некоторые детали.
EquipmentEdit.cshtml
@model kpa.mko.bll.viewmodels.clientData.ClientDataFormViewModel
<table id="equipment">
<tr class="form-row">
<td class="form-left">Forklift On Site?</td>
<td class="form-right">
@Html.EditorFor(x => x.ForkliftOnSite)
@Html.ValidationMessageFor(x => x.ForkliftOnSite)
</td>
</tr>
<tr class="form-row">
<td class="form-left">Equipment</td>
<td class="form-right">
@Html.HiddenFor(m => m.AccountId)
Equipment Type:
<div id="divEquipmentEdit" style="display: none;">
</div>
</td>
</tr>
</table>
<script type="text/javascript">
$(document).ready(function() {
$("#ddlEquipmentType").change(
function() {
var selection = $("#ddlEquipmentType option:selected").text();
if (selection == "Storage Tanks") {
//Try to get the partial view of the editor template }
$.ajax({
url: '@Url.Action("LoadStorageTankDataEditor")',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ accountId: $('#AccountId').val() }),
dataType: "html",
success: function (view) {
$('#divEquipmentEdit').show();
$('#divEquipmentEdit').html(view);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('error = ' + thrownError);
alert('xhr resp text = ' + xhr.responseText);
}
});
} else {
$('#divEquipmentEdit').hide();
}
}
);
});
</script>
StorageTankData.cshtml
@model kpa.mko.bll.viewmodels.clientData.StorageTankData
@using kpa.mko.dal.Entities;
Existing Tanks:
@Html.HiddenFor(m => m.AccountId)
@if (Model.StorageTanks.Count == 0)
{
<div>No tanks for this account.</div>
}
else
{
foreach (StorageTank st in Model.StorageTanks)
{
@st.ListDescription Edit
}
}
<div id="divTankEditor">
</div>
<script type="text/javascript">
$(document).ready(function() {
getEditor(0);
});
function getEditor(storageTankId) {
//Substitute in the StorageTank editor to the div above.
$.ajax({
url: '@Url.Action("LoadStorageTankEditor")',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ storageTankId: storageTankId, accountId: $('#AccountId').val() }),
dataType: "html",
success: function (view) {
$('#divTankEditor').html(view);
if (storageTankId == 0) {
$('#btnTankDelete').hide();
} else {
$('#btnTankDelete').show();
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert('error = ' + thrownError);
alert('xhr resp text = ' + xhr.responseText);
}
});
}
</script>
StorageTank.cshtml
@model kpa.mko.bll.viewmodels.clientData.StorageTankForEdit
@using kpa.mko.dal.Entities;
@using kpa.mko.bll.factories;
@using (Ajax.BeginForm("SaveStorageTank", "ClientData", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "divEquipmentEdit" }))
{
@Html.HiddenFor(st => st.TankForEdit.StorageTankID)
<div>Tank Placement:@Html.DropDownListFor(m => m.PlacementSelected, Model.Placements)</div>
<div>Department: @Html.DropDownListFor(m => m.DepartmentSelected, Model.Departments)</div>
<div>Volume (gal): @Html.EditorFor(m => m.TankForEdit.VolumeInGallons)</div>
<div>Content of Tank: @Html.DropDownListFor(m => m.StorageTankContentsSelected, Model.StorageTankContents)</div>
<div>Secondary Containment? @Html.EditorFor(m => m.TankForEdit.HasSecondaryContainment)</div>
<div>If so, what type: @Html.EditorFor(m => m.TankForEdit.SecondaryContainmentType)</div>
<div>Tank Has Overfill Alarm? @Html.EditorFor(m => m.TankForEdit.HasOverfillAlarm)</div>
<div>If so, what type: @Html.EditorFor(m => m.TankForEdit.OverfillAlarmType)</div>
<input type="submit" value="Save Tank Data" name="submitButton" /> <input type="submit" value="Delete Tank" id="btnTankDelete" name="submitButton" /> <input type="button" value="Reset" onclick="getEditor(0); return false;" />
}
метод Диспетчера, чтобы спасти
public PartialViewResult SaveStorageTank(string submitButton, string accountId)
{
int acctId = int.Parse(accountId);
StorageTankForEdit stfe = new StorageTankForEdit(acctId);
if (TryUpdateModel(stfe))
{
if (!string.IsNullOrEmpty(submitButton) && submitButton.Equals("Delete Tank"))
{
//Delete the tank already.
StorageTankFactory.Delete(stfe.TankForEdit);
}
else
{
stfe.TankForEdit.DepartmentFk = int.Parse(stfe.DepartmentSelected);
stfe.TankForEdit.Placement = (StorageTankPlacement)Enum.Parse(typeof(StorageTankPlacement), stfe.PlacementSelected);
stfe.TankForEdit.StorageTankContentFk = int.Parse(stfe.StorageTankContentsSelected);
//@^*#$^ NHibernate doesn't bother to get the content class upon re-display, so we don't see the content type.
//I think it's caching this tank, so let's try populating the content here and see if it shows up.
stfe.TankForEdit.StorageTankContent = StorageTankContentFactory.GetById(stfe.TankForEdit.StorageTankContentFk);
StorageTankFactory.Save(stfe.TankForEdit);
}
}
//We decided to reset to the insert state.
return LoadStorageTankDataEditor(acctId);
метод Диспетчера, чтобы получить StorageTankData частичное представление
public PartialViewResult LoadStorageTankDataEditor(int accountId)
{
StorageTankData std = new StorageTankData(accountId);
std.StorageTanks = StorageTankFactory.GetByAccount(accountId);
return PartialView("EditorTemplates/StorageTankData", std);
}
метод Диспетчера, чтобы получить StorageTank частичное представление
public PartialViewResult LoadStorageTankEditor(int storageTankId, int accountId)
{
StorageTankForEdit st = new StorageTankForEdit(accountId);
if (storageTankId > 0)
{
st.TankForEdit = StorageTankFactory.GetById(storageTankId);
}
return PartialView("EditorTemplates/StorageTank", st);
}