@Ajax.ActionLink有效,但$.ajax不起作用



我是MVC和Ajax的新手,但有很好的C#工作知识和经验。

作为测试,我创建了一个具有 4 种方法的 ApiController,其中 2 种使用 GET,2 种使用 POST。

所有 4 种方法都可以在 @Ajax.ActionLink 上运行良好,但(据我所知)等效的 $.ajax 调用无法进行 POST(但通过 GET)。

这是我的 API 控制器:

public class ValuesController : ApiController
{
[HttpGet] // GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpGet] // GET api/values/5
public string Get(int id)
{
return $"id={id}, ~id={~id}";
}
[HttpPost] // POST api/values
public string PostData(string value="123")
{
var x = Request;
return new string(value.Reverse().ToArray());
}
[HttpPost] // POST api/values
public JsonResult<object> PostData(string value, int i)
{
return Json((object)new { s=new string(value.Reverse().ToArray()), i });
}
}

以及来自 .cshtml 文件的相应调用:

@Ajax.ActionLink("Click me for Get()", "Get", "api/Values", null, new AjaxOptions() { HttpMethod = "GET", OnSuccess = "res0", OnFailure = "fail0", UpdateTargetId = "status0" })
<script language="javascript">
function res0(res) {
$('#status00')[0].innerText = "Result: " + res;
}
function fail0(a, b, c) {
$('#status000')[0].innerText = "Errorn" + b + 'n' + c;
}
</script>
<form action="" id="form0">
<input type="submit" />
</form>
<div id="status0"></div>
<div id="status00"></div>
<div id="status000"></div>
@Ajax.ActionLink("Click me for Get(5)", "Get", "api/Values", new { id = 5 }, new AjaxOptions() { HttpMethod = "GET", OnSuccess = "res1", OnFailure = "fail1", UpdateTargetId = "status1" })
<script language="javascript">
function res1(res) {
$('#status11')[0].innerText = "Result: " + res;
}
function fail1(a, b, c) {
$('#status111')[0].innerText = "Errorn" + b + 'n' + c;
}
</script>
<form action="" id="form1">
<input type="submit" />
</form>
<div id="status1"></div>
<div id="status11"></div>
<div id="status111"></div>
@Ajax.ActionLink("Click me for PostData('Hello')", "PostData", "api/Values", new { value = "Hello" }, new AjaxOptions() { HttpMethod = "POST", OnSuccess = "res2", OnFailure = "fail2", UpdateTargetId = "status2" })
<script language="javascript">
function res2(res) {
$('#status22')[0].innerText = "Result: " + res;
}
function fail2(a, b, c) {
$('#status222')[0].innerText = "Errorn" + b + 'n' + c;
}
</script>
<form action="" id="form2">
<input type="submit" />
</form>
<div id="status2"></div>
<div id="status22"></div>
<div id="status222"></div>
@Ajax.ActionLink("Click me for PostData("Hello", 3)", "PostData", "api/Values", new { value = "Hello", i = 3 }, new AjaxOptions() { HttpMethod = "POST", OnSuccess = "res3", OnFailure = "fail3", UpdateTargetId = "status3" })
<script language="javascript">
function res3(res) {
$('#status33')[0].innerText = "Result: " + JSON.stringify(res);
}
function fail3(a, b, c) {
$('#status333')[0].innerText = "Errorn" + b + 'n' + c;
}
</script>
<form action="" id="form3">
<input type="submit" />
</form>
<div id="status3"></div>
<div id="status33"></div>
<div id="status333"></div>
<script language="javascript">
document.getElementById('form0').onsubmit = function (e) { e.preventDefault(); form0_submit(); };
document.getElementById('form1').onsubmit = function (e) { e.preventDefault(); form1_submit(); };
document.getElementById('form2').onsubmit = function (e) { e.preventDefault(); form2_submit(); };
document.getElementById('form3').onsubmit = function (e) { e.preventDefault(); form3_submit(); };
function form0_submit() {
$.ajax({
type: 'GET',
url: '/api/Values/Get',
success: function (res) {
$('#status0')[0].innerText = res;
},
error: function (jqXHR, tStatus, errThrown) {
$('#status00')[0].innerText = tStatus;
$('#status000')[0].innerText = errThrown;
}
});
}
function form1_submit() {
$.ajax({
type: 'GET',
url: '/api/Values/Get',
data: {id:@DateTime.Now.TimeOfDay.Seconds},
success: function (res) {
$('#status1')[0].innerText = res;
},
error: function (jqXHR, tStatus, errThrown) {
$('#status11')[0].innerText = tStatus;
$('#status111')[0].innerText = errThrown;
}
});
}
function form2_submit() {
$.ajax({
type: 'POST',
url: '/api/Values/PostData',
data: JSON.stringify({ value: "Test string" }),
contentType: 'application/json; charset=UTF-8',
dataType: 'json',
success: function (res) {
$('#status2')[0].innerText = res;
},
error: function (jqXHR, tStatus, errThrown) {
$('#status22')[0].innerText = tStatus;
$('#status222')[0].innerText = errThrown;
}
});
}
function form3_submit() {
// not implemented yet, need to get form2_submit() working
}
</script>

我曾经收到一个404 - Not found错误,直到public string PostData(string value="123")value了一个可选参数。 现在,该函数是使用默认的"123"值调用的,而不是我传递的值。form2_submit(),我尝试了data参数的不同组合。

使用 Chrome 开发人员工具(右键单击>检查,然后Network选项卡)分析响应,我可以看到ActionLink将参数作为Query String Parameters发送,而$.ajax调用则以Request PayloadForm Data的形式进行,具体取决于我传递给data参数的内容。在这两种情况下,参数名称/值对都是正确的,但 C# ApiController 似乎忽略了该值(我也尝试过 [FromBody] 属性)。

我已经在这里和其他网站上查看了其他帖子,但无法弄清楚为什么数据传输方式不同

编辑:

根据要求,Get-Package的输出:

PM> Get-Package
Id                                  Versions         ProjectName
--                                  --------         -----------
Antlr                               {3.4.1.9004}     WebApplication1
bootstrap                           {3.0.0}          WebApplication1
jQuery                              {1.10.2}         WebApplication1
Microsoft.ApplicationInsights       {2.2.0}          WebApplication1
Microsoft.ApplicationInsights.Ag... {2.0.6}          WebApplication1
Microsoft.ApplicationInsights.De... {2.2.0}          WebApplication1
Microsoft.ApplicationInsights.Pe... {2.2.0}          WebApplication1
Microsoft.ApplicationInsights.Web   {2.2.0}          WebApplication1
Microsoft.ApplicationInsights.Wi... {2.2.0}          WebApplication1
Microsoft.ApplicationInsights.Wi... {2.2.0}          WebApplication1
Microsoft.AspNet.Mvc                {5.2.3}          WebApplication1
Microsoft.AspNet.Razor              {3.2.3}          WebApplication1
Microsoft.AspNet.Web.Optimization   {1.1.3}          WebApplication1
Microsoft.AspNet.WebApi             {5.2.3}          WebApplication1
Microsoft.AspNet.WebApi.Client      {5.2.3}          WebApplication1
Microsoft.AspNet.WebApi.Core        {5.2.3}          WebApplication1
Microsoft.AspNet.WebApi.HelpPage    {5.2.3}          WebApplication1
Microsoft.AspNet.WebApi.WebHost     {5.2.3}          WebApplication1
Microsoft.AspNet.WebPages           {3.2.3}          WebApplication1
Microsoft.CodeDom.Providers.DotN... {1.0.8}          WebApplication1
Microsoft.jQuery.Unobtrusive.Ajax   {3.2.5}          WebApplication1
Microsoft.Net.Compilers             {2.4.0}          WebApplication1
Microsoft.Web.Infrastructure        {1.0.0.0}        WebApplication1
Modernizr                           {2.6.2}          WebApplication1
Newtonsoft.Json                     {6.0.4}          WebApplication1
Respond                             {1.2.0}          WebApplication1
WebGrease                           {1.5.2}          WebApplication1
PM>

默认情况下,如果 Web api 方法的参数是简单类型(如stringint),则 Web API 会尝试从 uri 中获取值。

如果要在请求正文中发送字符串,则应显式使用FromBody属性修饰器,以便 Web API 知道它应该从请求正文读取数据。当存在FromBody属性时,Web API 将使用content-type标头值来选取将处理它收到的内容的格式化程序。

[HttpPost] // POST api/values
public string PostData([FromBody]string value)
{
if (value == null) value = "some non null";
var x = Request;
return new string(value.Reverse().ToArray());
}

现在,在客户端,请确保发送要发送的字符串的 JSON 字符串版本,同时将内容类型指定为application/json

$.ajax({
type: 'POST',
url: '/api/Values/PostData',
data: JSON.stringify("My Test string"),
contentType: 'application/json',
success: function (res)
{
console.log(res);
},
error: function (jqXHR, tStatus, errThrown)
{
console.log(errThrown);
}
});

最新更新