與MVC 3 - Ajax.BeginForm does a full post back類似,但我已驗證jquery.unobtrusive-ajax.min.js的引用確實存在於我的頁面中。此外,它在IE 9中效果很好,但在Firefox和Chrome中,我只將局部視圖看作完整的網頁,而不是用該局部視圖的內容替換div。在Chrome和Firefox中ajax.beginform的完整回傳
我還是很新的MVC3,所以我敢肯定這很簡單。
簡介:
在我的頁面上有哪些變得像用戶點擊鏈接可見幾個不同的.cshtml文件。在EquipmentData.cshtml文件中,我有一個下拉列表,在發生變化時,會向控制器發送一個ajax回發信息,以將編輯器模板加載到div中。
在該編輯器模板(StorageTankData.cshtml)中,存在一個數據列表並且具有單個項目(StorageTank.cshtml)的編輯模板的佔位符。 StorageTank.cshtml被初始化爲插入一個新的(id爲零);當用戶點擊數據列表中的其中一個項目時,我們再次調用控制器以獲取該特定項目的StorageTank.cshtml局部視圖,並將該html替換爲編輯div。
所有這些都很好。在StorageTank.cshtml模板中,我有一個Ajax.Begin表單,它發佈到不同的控制器操作以保存存儲罐數據,然後調用相同的控制器方法來獲取StorageTankData.cshtml分部視圖。我們的想法是,我們將刷新項目列表並重置編輯窗體以插入模式並將其替換爲div。
在IE中可以正常工作,但在Chrome和Firefox中,我只是在頁面上獲得部分視圖,而不是在整個頁面上進行替換。我認爲這是因爲我的保存回傳到一個不同的控制器方法比生成整個頁面,但我不知道該怎麼做。
我在IE中看到的是URL保持在「/ Edit」(控制整個頁面的動作)並且替換效果很好。在Chrome和FF中,URL改爲我的「/ SaveStorageTank」操作。所以,我認爲這解釋了爲什麼這些瀏覽器在完成時只顯示部分視圖。我不明白的是爲什麼他們不去做替換。
直到重新顯示後,我纔在Firebug或Chrome中看到錯誤。 (當然,他們會被$(document).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: <select id="ddlEquipmentType">
<option value="">--select one--</option>
@foreach (var lookupValue in Model.EquipmentTypes.OrderBy(lv => lv.ShortName))
{
<option value="@lookupValue.LookupValueId">@lookupValue.ShortName</option>
}
</select>
<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:
<br /><br />
@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 <a href="javascript:getEditor(@st.StorageTankID);">Edit</a><br />
}
}
<br /><br />
<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);
}
我們只知道_找出它。我們無法弄清楚爲什麼StorageTank.cshtml中的Ajax.BeginForm完成的表單無法替換局部視圖。 –