@ Ajax.ActionLink работает, но $ .ajax нет - PullRequest
0 голосов
/ 26 апреля 2018

Я новичок в MVC и Ajax, но обладаю хорошими рабочими знаниями и опытом работы с C #.

В качестве теста я создал ApiController с 4 методами, 2 с помощью GET и 2 с помощью POST.

Все 4 метода прекрасно работают с @ Ajax.ActionLink, но (насколько мне известно) эквивалентный вызов $ .ajax не проходит POST (но проходит GET).

Вот мой ApiController:

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 = "Error\n" + 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 = "Error\n" + 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 = "Error\n" + 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 = "Error\n" + 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 (щелкните правой кнопкой мыши -> Inspect, затем вкладка Network), я вижу, что ActionLink отправляет параметры как Query String Parameters, тогда как вызов $.ajax делает это как Request Payload или Form Data в зависимости от того, что именно я передаю параметру data. В обоих случаях пара имя / значение параметра является правильной, но ApiController в C #, похоже, игнорирует это значение (я также пробовал атрибут [FromBody]).

Я проверил другие сообщения здесь и на других сайтах, но не могу понять, почему данные передаются по-другому

Edit:

По запросу вывод 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>

1 Ответ

0 голосов
/ 27 апреля 2018

По умолчанию, если параметр вашего веб-API-метода является простым типом, таким как string или int, Web API пытается получить значение из URI.

Если вы отправляете строку в теле запроса, вам следует явно использовать декоратор атрибута FromBody, чтобы веб-API знал, что он должен читать данные из тела запроса. При наличии атрибута FromBody веб-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);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...