2013-01-31 39 views
35

Perché il parametro è sempre nullo quando chiamo il metodo Post riportato di seguito con ajax?Web Api Parametro sempre nullo

public IEnumerable<string> Post([FromBody]string value) 
{ 
    return new string[] { "value1", "value2", value }; 
} 

Ecco la chiamata al metodo API Web tramite la tecnologia AJAX:

function SearchText() { 
     $("#txtSearch").autocomplete({ 
      source: function (request, response) { 
       $.ajax({ 
        type: "POST", 
        contentType: "application/json; charset=utf-8", 
        url: "api/search/", 
        data: "test", 
        dataType: "text", 
        success: function (data) { 
         response(data.d); 
        }, 
        error: function (result) { 
         alert("Error"); 
        } 
       }); 
      } 
     }); 
    } 

risposta

60
$.ajax({ 
    url: '/api/search', 
    type: 'POST', 
    contentType: 'application/x-www-form-urlencoded; charset=utf-8', 
    data: '=' + encodeURIComponent(request.term), 
    success: function (data) { 
     response(data.d); 
    }, 
    error: function (result) { 
     alert('Error'); 
    } 
}); 

Fondamentalmente si può avere un solo parametro di tipo scalare che è decorato con l'attributo [FromBody] e la vostra richiesta ha bisogno di usare application/x-www-form-urlencoded e il payload POST dovrebbe apparire così:

=somevalue 

Si noti che, contrariamente ai protocolli standard, manca il nome del parametro. Stai inviando solo il valore.

Si può leggere di più su come il modello vincolante nel Api Web funziona in this article.

Ma naturalmente questo hacker in giro è una cosa malata. È necessario utilizzare un modello di vista:

public class MyViewModel 
{ 
    public string Value { get; set; } 
} 

e poi sbarazzarsi dell'attributo [FromBody]:

public IEnumerable<string> Post(MyViewModel model) 
{ 
    return new string[] { "value1", "value2", model.Value }; 
} 

e quindi utilizzare una richiesta JSON:

$.ajax({ 
    url: '/api/search', 
    type: 'POST', 
    contentType: 'application/json; charset=utf-8', 
    data: JSON.stringify({ value: request.term }), 
    success: function (data) { 
     response(data.d); 
    }, 
    error: function (result) { 
     alert('Error'); 
    } 
}); 
+1

Parte molto utile: il carico utile POST per essere in questa forma '= somevalue' ... Sono diventato pazzo cercando di capire perché non funziona per me. L'ho avuto nella forma 'chiave = valore'. Quindi grazie! – Learner

+0

La soluzione superiore con '=' + è un buon compromesso, ma non è necessario specificare il tipo di contenuto perché il tipo di contenuto ajax predefinito è "contentType: 'application/x-www-form-urlencoded; charset = utf-8 ', ":] – dlght

14

Non è possibile utilizzare un tipo semplice per l'attributo [FromBody] con il tipo di contenuto JSON. Sebbene il predefinito in Visual Studio abbia una stringa dal corpo, questo è per il tipo di contenuto application/x-www-form-urlencoded.

Mettere il valore di stringa come una proprietà su una classe del modello di base e la deserialiser funzionerà.

public class SimpleModel() 
{ 
    public string Value {get;set;} 
} 

public IEnumerable<string> Post([FromBody]SimpleModel model) 
{ 
    return new string[] { "value1", "value2", model.Value }; 
} 

Modificare il JSON si sta inviando a:

{"Value":"test"} 
+0

perché Visual Studio utilizza stringa come predefinito, allora? – daniel

+0

Chiarimento aggiunto. I valori funzionerebbero con il tipo di contenuto application/x-www-form-urlencoded ... ma state usando application/json. Il modello –

+0

è ancora nullo, anche con datatype json – daniel

1

ogni volta che chiamiamo web api azione e che prendono [frombody] parametro quindi introdurre prefix parametro con = per esempio

public string GetActiveEvents([FromBody] string XMLRequestString) { 
} 

per chiamare sopra API Web azione

  1. URI

  2. 2.

User-Agent: Fiddler

Content-Type: application/x-www-form-urlencoded

Host: localhost: 54702

Content-Length: 936

  1. corpo richiesta è = dati

Spero che questo dia una chiara idea.

1

Ho appena avuto un bel po 'di tempo con questo e .NET Core Web API. Quindi spero di risparmiare tempo per qualcuno: il vero problema per me era semplice: non stavo convertendo nel tipo corretto (la notifica @Darins answer utilizza una VM piuttosto che una stringa).

Il tipo predefinito nel modello è string. Ho pensato perché stiamo inviando un JSON con stringa, vedremmo una stringa JSON, ma non era così. Ho dovuto renderlo il tipo corretto.

E.g. Questo ha fallito

[EnableCors("AllowAll")] 
[HttpPost] 
public HttpResponseMessage Post([FromBody]string value) 
{ 
    // Do something with the blog here.... 

    var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK); 
    return msg; 

} 

Ma questo ha funzionato.

[EnableCors("AllowAll")] 
[HttpPost] 
public HttpResponseMessage Post([FromBody]Blog value) 
{ 
    // Do something with the blog here.... 

    var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK); 
    return msg; 

} 

Ajax chiamata

function HandleClick() { 

    // Warning - ID's should be hidden in a real application 
    //   - or have covering GUIDs. 
    var entityData = { 
     "blogId": 2, 
     "url": "http://myblog.com/blog1", 
     "posts": [ 
     { 
      "postId": 3, 
      "title": "Post 1-1", 
      "content": "This is post 1 for blog 1", 
      "blogId": 2 
     }, 
     { 
      "postId": 4, 
      "title": "Post 1-2", 
      "content": "This is post 2 for blog 1", 
      "blogId": 2 
     } 
     ] 
    }; 


    $.ajax({ 
     type: "POST", 
     url: "http://localhost:64633/api/blogs", 
     async: true, 
     cache: false, 
     crossDomain: true, 
     data: JSON.stringify(entityData), 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (responseData, textStatus, jqXHR) { 
      var value = responseData; 
     }, 
     error: function (responseData, textStatus, errorThrown) { 
      alert('POST failed.'); 
     } 
    }); 

} 
Problemi correlati