【发布时间】:2016-09-25 16:26:31
【问题描述】:
我正在使用 ajax 调用动作控制器,但是当动作控制器接收到它时,我使用 data 属性传递的参数始终为空...
这里会发生什么?
jQuery 函数:
function PostOrder()
{
var id = $(".aslink").data("customerid");
var url = $("#btnAddOrderPost").data("url_add_order");
$.ajax({
type:"post",
url: url,
data: JSON.stringify( { orderVM: $("#frmCreatePV").serialize()}),
datatype: "json",
contentType: "application/json",
success: function () {
alert("it was inserted");
}
})
}
动作控制器:
[HttpPost]
// [ValidateAntiForgeryToken]
public ActionResult CreatePV(OrderVM orderVM)
{
if (ModelState.IsValid)
{
List<string> top = new List<string>();
decimal tempPrice = 0M;
for (int i = 0; i < orderVM.Toppings.Count; i++)
{
if (orderVM.Toppings[i].IsSelected == true)
{
top.Add(orderVM.Toppings[i].SpecificTopping);
tempPrice += orderVM.Toppings[i].Price;
}
}
Order order = new Order
{
Toppings = top,
TotalPrice = tempPrice
};
db.Orders.Add(order);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(orderVM);
}
这是我使用这种类型参数的 OrderVM ViewModel:
public class OrderVM
{
public virtual List<ToppingVM> Toppings { get; set; }
public decimal TotalPrice { get; set; }
}
这是包含在部分视图中的表单:
@using (Html.BeginForm(null,null,FormMethod.Post, htmlAttributes: new { @id="frmCreatePV"}))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@{
for (int i = 0; i < Model.Toppings.Count; i++)
{
<div class="col-xs-4">
@Html.HiddenFor(model => model.Toppings[i].SpecificTopping)
@Html.CheckBoxFor(model => model.Toppings[i].IsSelected, htmlAttributes: new { data_price = Model.Toppings[i].Price, @id = "chbkPrice" })
@Html.HiddenFor(model => model.Toppings[i].Price)
@Html.LabelFor(model => model.Toppings[i].IsSelected , Model.Toppings[i].SpecificTopping)
<p>Price: @Model.Toppings[i].Price</p>
</div>
}
}
</div>
<div class="form-group">
<div class="col-md-10">
<input type="button" value="Add order" id="btnAddOrderPost" class="btn btn-primary"
data-url_add_order="@Url.Action("CreatePV", "Orders")" />
</div>
</div>
</div>
}
更新
最后这就是 Action Controller 的样子:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult CreatePV(OrderVM orderVM)
{
int id = Convert.ToInt32(TempData["License"]);
if (ModelState.IsValid)
{
List<string> top = new List<string>();
decimal tempPrice = 0M;
for (int i = 0; i < orderVM.Toppings.Count; i++)
{
if (orderVM.Toppings[i].IsSelected == true)
{
top.Add(orderVM.Toppings[i].SpecificTopping);
tempPrice += orderVM.Toppings[i].Price;
}
}
Order order = new Order
{
Customer = db.Customers.Where(c => c.LicenseNumber == id).First(),
LicenseNumber = id,
Toppings = top,
TotalPrice = tempPrice
};
db.Orders.Add(order);
db.SaveChanges();
return Json(new { success= true, JsonRequestBehavior.AllowGet});
}
return Json(new { success = false, JsonRequestBehavior.AllowGet});
}
还有 JQuery 函数,注意我使用了 serializeArray() 向未绑定到 html 表单的数据中添加了一个元素:
function PostOrder()
{
var orderVM = {};
id = $(".aslink").data("customerid");
alert($("#btnGetOrderAdd").data("customerid"));
var url = $("#btnAddOrderPost").data("url_add_order");
var datavar = $("#frmCreatePV").serializeArray();
datavar.push({name: "LicenseNumber" ,value : id})
$.ajax({
type:"post",
url: url,
data: datavar,
datatype: "json",
success: function () {
alert("it was inserted");
}
})
}
【问题讨论】:
-
尝试删除 contentType。并尝试使用控制台进行调试,它确实在传递给 ajax 之前出现在 jquery 上
-
@Loading.. 我删除了 contentType,现在可以工作了,为什么?您可以发布答案,我会接受的
-
删除
contentType选项不可能工作,除非您也将data选项更改为data: $("#frmCreatePV").serialize(),并删除datatype: "json",(并将其更改为dataType: "html")。不知道为什么您接受了一个似乎与 PHP 有关的错误答案。而return RedirectToAction("Index");不可能工作 - 你进行 ajax 调用并且 ajax 调用永远不会重定向。 -
因为您在编辑之前的代码返回的是视图 (html) 而不是 json。但是既然您返回了
JsonResult,那么您可以将其保留为datatype:"json" -
请注意,您应该避免使用
.serializeArray()(如果您在视图中使用了CheckBoxFor(),它将无法正常工作)。最好使用.serialize(),如果你想添加其他值,你可以使用$.param()(例如参考this answer)或者你可以简单地为LicenseNumber添加一个隐藏的输入,所以它会被序列化
标签: c# jquery ajax asp.net-mvc razor