我试图在通过AJAX更改字段时将参数发布到控制器操作,但查找第一个参数始终为null。
我想发布的控制器操作是:
public ActionResult Model_GroupCompanyIDChanged(ActionViewModel vm, int oldVal, int newVal)
{
vm.Model.Observation = "Changed from " + oldVal + " to " + newVal;
return Refresh(vm);
}
我的帖子代码序列化了屏幕上的表单,并将其与刚刚更改的字段的旧值和新值一起发布。在操作参数中正确设置旧值和新值参数,但控制器操作中的vm参数始终为null。控制器URL没有问题,因为我可以调试操作并看到它被调用。
function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) {
var origModel = $("form[action='" + formActionUrl + "']").serialize();
var data = {
"oldVal": oldVal
, "newVal": newVal
, "vm": origModel
};
RefreshScreenPassData(ControllerURL, formActionUrl, data);
}
function RefreshScreenPassData(ControllerURL, formActionUrl, data) {
alert(data);
$.ajax({
url: ControllerURL,
type: 'POST',
data: data,
success: function (response) {
RefreshScreenContent(response);
},
error: AjaxError
});
}
在点击某个字段时,IS工作处理的同一屏幕上与以下内容形成对比:
控制器操作:
public ActionResult Model_ActionDateClicked(ActionViewModel vm)
{
vm.Model.Observation = "Clicked";
return Refresh(vm);
}
JavaScript(使用上面的相同RefreshScreenPassData函数进行实际的POST):
function ElementClickedRefresh(ControllerURL, formActionUrl) {
var origModel = $("form[action='" + formActionUrl + "']").serialize();
RefreshScreenPassData(ControllerURL, formActionUrl, $("form[action='" + formActionUrl + "']").serialize());
}
简而言之,第一个更改事件示例首先将参数设置为一个对象,因为有多个参数,并且只有旧的和新的int参数设置为服务器端且ViewModel vm为null。在第二个单击的示例中,使用序列化表单正确设置了vm。
formActionUrl参数对于两者都是相同的并且不是问题,因为我调试了帖子,我可以看到的唯一区别是第一个示例中的请求主体(更改事件)vm参数看起来是URL编码的:< / p>
OLDVAL = 0&安培;的newval = 02&安培; VM = __ RequestVerificationToken%3DoeQx0RyQ-nOPQ1namoIeRuAWRzfVltfPx5ntsdpuaFTSdADuG_eC__Y54hlWmf8AOAigvyH8R_6qP77bJr1Mm5Yag7a7R9oSQse6e9NJMYg1%26ViewMode%3DEdit%26Model.ActionDate%3D11%252F07%252F2013%2B09%253A32%253A08%26Model.Observation%3DClicked%26Model.OriginatorUserID%3D1 %26Model.ActiononUserID%3D0%26Model.ActionStatusID%3D1%26Model.ActionTypeID%3D0%26Model.ClientID%3D23%26Model.ClientContactID%3D0%26Model.PriorityID%3D0%26Model.CloseOutDate%3D%26Model.ActionNotes%3D%26Model .ProgressNotes%3D%26Model.Comments%3D%26Model.BusinessUnitID%3D0%26Model.GroupCompanyID%3D02%26Model.Confidential%3Dfalse%26Model.Id%3D1%26Model.Archived%3Dfalse%26Model.AddedUserID%3D1%26Model.AddedDateTime %3D11%252F07%252F2013%2B09%253A32%253A19%26Model.ModifiedUserID%3D1%26Model.ModifiedDateTime%3D11%252F07%252F2013%2B09%253A32%253A19
但是对于正在运行的第二个点击事件,它不是:
__ RequestVerificationToken = oeQx0RyQ-nOPQ1namoIeRuAWRzfVltfPx5ntsdpuaFTSdADuG_eC__Y54hlWmf8AOAigvyH8R_6qP77bJr1Mm5Yag7a7R9oSQse6e9NJMYg1&安培; VIEWMODE =编辑&安培; Model.ActionDate = 11%2F07%2F2013 + 09%3A32%3A08&安培; Model.Observation =更改&安培; Model.OriginatorUserID = 1&安培; Model.ActiononUserID = 0&安培; Model.ActionStatusID = 1&安培; Model.ActionTypeID = 0&安培; Model.ClientID = 23&安培; Model.ClientContactID = 0&安培; Model.PriorityID = 0&安培; Model.CloseOutDate =安培; Model.ActionNotes =安培; Model.ProgressNotes =安培; Model.Comments =安培; Model.BusinessUnitID = 0&安培; Model.GroupCompanyID = 0&安培; Model.Confidential =假安培; Model.Id = 1&安培; Model.Archived =假安培; Model.AddedUserID = 1&安培; Model.AddedDateTime = 11%2F07%2F2013 + 09%3A32 %3A19&安培; Model.ModifiedUserID = 1&安培; Model.ModifiedDateTime = 11%2F07%2F2013 + 09%3A32%3A19
我尝试通过将javascript更改为:
手动设置我的参数字符串function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) {
var origModel = $("form[action='" + formActionUrl + "']").serialize();
var data = "oldVal=" + oldVal + "&newVal=" + newVal + "&vm=" + origModel
RefreshScreenPassData(ControllerURL, formActionUrl, data);
}
并且POST请求正文更改为
OLDVAL = 02&安培;的newval = 023&安培; VM = __ RequestVerificationToken = xiYEcz53UNPVoGZ3RQGO_HFn54LIu0bTjQB-PB13tTEWZ7vUHMbsW25s7rI7D7lBLtACutEpynoNnk66jxijzSzFMCBO_nDoXf_FqsR9Cc81&安培; VIEWMODE =编辑&安培; Model.ActionDate = 11%2F07%2F2013 + 09%3A32%3A08&安培; Model.Observation =已点击&安培; Model.OriginatorUserID = 1和; Model.ActiononUserID = 0&安培; Model.ActionStatusID = 1&安培; Model.ActionTypeID = 0&安培; Model.ClientID = 23&安培; Model.ClientContactID = 0&安培; Model.PriorityID = 0&安培; Model.CloseOutDate =安培; Model.ActionNotes =安培;模型.ProgressNotes =安培; Model.Comments =安培; Model.BusinessUnitID = 0&安培; Model.GroupCompanyID = 023&安培; Model.Confidential =假安培; Model.Id = 1&安培; Model.Archived =假安培; Model.AddedUserID = 1&安培; Model.AddedDateTime = 11%2F07%2F2013 + 09%3A32%3A19&安培; Model.ModifiedUserID = 1&安培; Model.ModifiedDateTime = 11%2F07%2F2013 + 09%3A32%3A19
但它仍然没有绑定视图模型参数。
我做错了什么,当它来自JavaScript对象时没有设置参数?
更新1
我尝试过手动调用JSON stringify以尝试使其正常工作,但它仍然不起作用:
function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) {
var origModel = $("form[action='" + formActionUrl + "']").serialize();
var data = "oldVal=" + oldVal + "&newVal=" + newVal + "&vm=" + JSON.stringify(origModel)
RefreshScreenPassData(ControllerURL, formActionUrl, data);
}
更新2
以下是为我工作的地方,它将旧的和新的val添加到表单中,但是需要再次删除它们,否则下次它们最终会以不止一次的形式结束,这会使新旧val发生错误:
function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) {
var $myForm = $("form[action='" + formActionUrl + "']");
$myForm.append("<input type='hidden' name='oldVal' value='" + oldVal + "' id='oldVal' />");
$myForm.append("<input type='hidden' name='newVal' value='" + newVal + "' id='newVal' />");
var origModel = $myForm.serialize();
RefreshScreenPassData(ControllerURL, formActionUrl, origModel);
$('#oldVal').remove();
$('#newVal').remove();
}
最好不要将元素添加到DOM中,但至少它只是一小段代码而且不是CPU密集型的。我仍然希望再次尝试使用Gordatron的一个解决方案,看看我是否可以使其工作但可能没有时间。
答案 0 :(得分:1)
方法1
似乎篡改表单数据对您不起作用。
您如何尝试以下
function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) {
var $myForm = $("form[action='" + formActionUrl + "']");
$myForm.append("<input type='hidden' name='oldVal' value='" + oldVal + "' />");
$myForm.append("<input type='hidden' name='newVal' value='" + newVal + "' />");
var origModel = $myForm.serialize();
RefreshScreenPassData(ControllerURL, formActionUrl, origModel);
}
方法2
虽然上述解决方案适用于您的情况(因为它与我的情况类似),但还有另一种方法可以做到这一点。
将数据发布到服务器有两种格式。一种是表单编码,您使用$("form[action='" + formActionUrl + "']").serialize()
实现,另一种是使用JSON。
在上面的问题中,您使用了两者的混合
var data = {
"oldVal": oldVal,
"newVal": newVal,
"vm": origModel
};
即。在JSON对象中,您要将序列化表单添加为vm
。这就是为什么在vm
和oldVal
被正确填充的情况下,您在newVal
中获得空值的原因。
我建议如果你不想在我的回答中使用上面提供的解决方案,你应该采用JSON方法。即使用您的表单值创建一个JSON对象并使用
发布$.ajax({
type: 'POST',
url: ControllerURL,
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
RefreshScreenContent(response);
},
error: AjaxError
});
注意:contentType: "application/json"
我知道使用id / names获取表单的所有值并创建一个JSON对象会有点令人筋疲力尽,但幸运的是,我写了一些小toJSON plugin,这对你来说就是这样。
您需要做的就是关注
var form = $("form[action='" + formActionUrl + "']").toJSON();
var data = {
"oldVal": oldVal,
"newVal": newVal,
"vm": form
};
希望这有帮助
答案 1 :(得分:1)
我做了一点测试,看看我是否可以重新创建你的问题。我成功了,我设法让它上班,但我不知道它是最好的方式来做它或你想要的。
要重新创建它,我创建了一个测试应用并添加了模型:
public class Item {
public string id {get;set;}
public string name { get; set; }
}
观点:
<h2>Test</h2>
@using(Html.BeginForm()){
@Html.EditorFor(Model => Model.id)
@Html.EditorFor(Model => Model.name)
}
使用js:
$(function () {
var origModel = $("form").serialize();
var data = {
"oldVal": 'old'
, "newVal": 'new'
, "vm": origModel
};
RefreshScreenPassData("/Home/Test", data);
});
function RefreshScreenPassData(ControllerURL, data) {
alert(data);
$.ajax({
url: ControllerURL,
type: 'POST',
data: data,
dataType:'json',
success: function (response) {
RefreshScreenContent(response);
},
error: AjaxError
});
}
function AjaxError(e) {
alert(e);
}
控制器:
[HttpGet]
public ActionResult Test() {
return View(new Item() { id = "1", name = "name" });
}
[HttpPost]
public ActionResult Test(Item vm, string oldVal,string newval) {
return View(new Item() { id = vm.id+"oo", name = vm.name+"000" });
}
我发现了什么:
手动提交此不起作用
$.ajax({
url: ControllerURL,
type: 'POST',
data: {
"oldVal": 'old'
, "newVal": 'new'
, "vm": {"id":"1","name":"name"}
},
success: function (response) {
RefreshScreenContent(response);
},
error: AjaxError
});
你对动作的第一个参数不是null但是它的属性是null(即vm不是null但是vm.id和vm.name是)
这工作:
$.ajax({
url: ControllerURL,
type: 'POST',
data: {
"oldVal": 'old'
, "newVal": 'new'
, "id": "1"
, "name": "name"
},
success: function (response) {
RefreshScreenContent(response);
},
error: AjaxError
});
下一个问题:
表单上的.serialise方法返回url参数类型字符串:
id=1&name=name
不是json。所以我很快就找到了一种方法来获得json形式的表格并找到了这个(Convert form data to JavaScript object with jQuery)..所以我随后一起捏造了这个:
jQuery(function () {
var data = {
"oldVal": 'old'
, "newVal": 'new'
};
var o = {};
var a = $("form").serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
jQuery.extend(data, o);
RefreshScreenPassData("/Home/Test", data);
});
function RefreshScreenPassData(ControllerURL, data) {
alert(JSON.stringify(data));
$.ajax({
url: ControllerURL,
type: 'POST',
data: data,
success: function (response) {
alert(response);
},
error: AjaxError
});
}
它只是将表单转换为对象,然后使用extend将其与要传回的其他属性“合并”。
这不是你问题的真正解决方案,但我希望它足以让你继续前进。
答案 2 :(得分:0)
其他选项不发送json ..只是序列化。
模型:
public class Item {
public string id {get;set;}
public string name { get; set; }
}
视图模型:
public class ViewModel {
public Item model { get; set; }
public String CapsName { get { return this.model.name.ToUpper(); } }
public String OtherField { get; set; }
}
控制器:
[HttpGet]
public ActionResult Test2() {
return View("ViewModelTest",new ViewModel() {
model = new Item() {
id = "1"
, name = "name"
}
, OtherField="bubba"});
}
[HttpPost]
public ActionResult Test2(ViewModel vm, string oldVal, string newval) {
return View(new Item() {
id = vm.model.id + "oo"
, name = vm.model.name + "000"
});
//pointless code to allow me to put in a break point
}
查看:
@using(Html.BeginForm()){
@Model.CapsName<br />
@Html.EditorFor(m => m.model.id)
@Html.EditorFor(m => m.model.name)
@Html.EditorFor(m=>m.OtherField)
}
JS:
jQuery(function () {
var data = {
"oldVal": 'old'
, "newVal": 'new'
};
RefreshScreenPassData("/Home/Test2",
$.param(data) + "&"
+ $("form").serialize());
});
function RefreshScreenPassData(ControllerURL, data) {
alert(data);
$.ajax({
url: ControllerURL,
type: 'POST',
data: data,
success: function (response) {
alert(response);
},
error: AjaxError
});
}
此帖发布的数据为:
oldVal=old&newVal=new&model.id=1&model.name=name&OtherField=bubba
然后断点被击中我有一个完整的viewmodel,模型以及预期的旧值和新值。