我有一个ASP.NET应用程序,它包含一个前端,它包含一个表单,我想将数据传递给我的C#后端。为此,我使用JQuery post请求来序列化表单数据并使用JSON将其发送到控制器。下面是我调用控制器路由的Javascript代码;
$(".data-submit").on("click",
function(event) {
var formArray = $("#amend-form").serializeArray();
var json = JSON.stringify(formArray);
$.post(windowLocationOrigin() +
"/Instruction/AmendData",
json,
function (data) {
alert("api endpoint called");
});
});
这是控制器端点被调用
[Route("[controller]/AmendData")]
public IActionResult AmendPortingData([FromBody] string json)
{
return Ok(json);
}
当我通过我的前端提交此表单时,将调用onClick JS事件并发送post请求,但是从不命中控制器端点。我在return Ok(json)
行上有一个断点,在提交表单后永远不会触发。
如果我检查开发人员工具,我会收到500错误消息:POST https://localhost:44358/Instruction/AmendData 500
但是,如果我然后向此url https://localhost:44358/Instruction/AmendData?json=123
提交请求,则会正确命中结束点,并且我可以在调试器中看到值123
。
但是,我希望能够通过邮件请求正文发送我的数据,而不是通过网址发送,因为提交的表单很大并且包含太多要通过GET发送的数据。
我已经尝试将[HttpPost]
属性添加到控制器端点,但这会产生完全相同的行为,除了它不允许GET URL工作。
您的控制器操作:
public IActionResult AmendPortingData(string json)
期待一个名为json
的参数。
当你打电话给:
$.ajax({ url: url, data: "string" });
传递的数据没有参数名称,因此默认的Model Binder无法确定要应用于该参数的数据部分。
这适用于:
http://url?json=string
当你指定参数名称?json=
时,如果你调用了你的动作
http://url/string
然后它再次不会识别“字符串”作为参数“json”而不起作用(虽然可能会给你一个更有用的“找不到参数数据”错误)(假设当然没有额外的路由)。
通过为字符串参数指定名称,默认的Model Binder将能够将字符串与参数名称匹配:
$.ajax({ url: url, data: { json: "string" }});
另一种方法是添加一个Model Binder,它将接受任何POST字符串并将其传递给单个参数 - 但上述内容通常更简洁,更易于维护。
添加[HttpPost]
会将操作限制为该动词(因此,另外,添加[HttpPost][HttpGet]
会使其无法使用,因为它必须是POST且必须是GET)。
如果要从视图模型构建表单,则可以直接在操作中使用该viewmodel:
public ActionResult MyAction(MyViewModel viewmodel)
并直接传递:
$.ajax({ url: url, data: $("form").serialize() });
默认的Model Binder会将输入的名称映射到viewmodel上的属性。