Jak przekazać dane JSON POST do metody Web API jako obiekt?

ASP.NET aplikacja MVC4 Web API definiuje metodę post do zapisania klienta. Klient jest przekazywany w formacie json w treści żądania POST. Parametr klienta w metodzie post zawiera wartości null dla właściwości.

Jak to naprawić, aby opublikowane dane były przekazywane jako obiekt klienta ?

If possible Content-Type: application / x-www-form-urlencoded should used since I dont know how to change it in javascript method which posts forma.

Kontroler:

public class CustomersController : ApiController {

  public object Post([FromBody] Customer customer)
        {
            return Request.CreateResponse(HttpStatusCode.OK,
            new
            {
                customer = customer
            });
        }
    }
}

public class Customer
    {
        public string company_name { get; set; }
        public string contact_name { get; set; }
     }

Zapytanie:

POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

{"contact_name":"sdfsd","company_name":"ssssd"}
Author: Liam, 2013-11-26

9 answers

Edytuj : 31/10/2017

Ten sam kod / podejście będzie działać dla Asp.Net Core 2.0 również. Główną różnicą jest to, że w asp.net core, zarówno Kontrolery web api, jak i kontrolery Mvc są połączone ze sobą w jeden model kontrolera. Więc twój typ powrotu może być IActionResult lub jedną z jego implementacji (Ex :OkObjectResult)


Użycie

contentType:"application/json"

Musisz użyć metody JSON.stringify, Aby przekonwertować go na łańcuch JSON, gdy go wysyłasz,

A segregator modelowy będzie powiązać dane json z obiektem klasy.

Poniższy kod będzie działał poprawnie (testowany)

$(function () {
    var customer = {contact_name :"Scott",company_name:"HP"};
    $.ajax({
        type: "POST",
        data :JSON.stringify(customer),
        url: "api/Customer",
        contentType: "application/json"
    });
});

Wynik

Tutaj wpisz opis obrazka

contentType property informuje serwer, że wysyłamy dane w formacie JSON. Ponieważ wysłaliśmy strukturę danych JSON, powiązanie modelu stanie się prawidłowe.

Jeśli sprawdzisz nagłówki żądania ajax, zobaczysz, że wartość Content-Type jest ustawiona jako application/json.

Jeśli nie podasz jawnie contentType, użyje on domyślny typ zawartości, który jest application/x-www-form-urlencoded;


Edycja na Listopad 2015, aby rozwiązać inne możliwe problemy poruszone w komentarzach

Umieszczanie obiektu złożonego

Załóżmy, że masz złożoną klasę modelu widoku jako parametr metody działania web api, taki jak ten

public class CreateUserViewModel
{
   public int Id {set;get;}
   public string Name {set;get;}  
   public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
  public int Id {set;get;}
  public string Code {set;get;}
}

A twój punkt końcowy API jest jak

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewMode Save([FromBody] CreateUserViewModel m)
    {
        // I am just returning the posted model as it is. 
        // You may do other stuff and return different response.
        // Ex : missileService.LaunchMissile(m);
        return m;
    }
}

W chwili pisania tego tekstu, ASP.NET MVC 6 to najnowsza stabilna wersja, A W MVC6 zarówno sterowniki Web api jak i sterowniki MVC są dziedziczone z Microsoft.AspNet.Mvc.Controller klasy bazowej.

Aby wysłać dane do metody od strony klienta, poniższy kod powinien działać poprawnie

//Build an object which matches the structure of our view model class
var model = {
    Name: "Shyju",
    Id: 123,
    Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};

$.ajax({
    type: "POST",
    data: JSON.stringify(model),
    url: "../product/save",
    contentType: "application/json"
}).done(function(res) {       
    console.log('res', res);
    // Do something with the result :)
});

Wiązanie modeli działa dla niektórych właściwości, ale nie dla wszystkich ! Dlaczego ?

Jeśli nie ozdobisz parametru metody web api atrybutem [FromBody]

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}

I wysłać model (surowy obiekt javascript, Nie w formacie JSON) bez podania wartości właściwości contentType

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});

Oprawa modelarska sprawdzi się w mieszkaniu właściwości w modelu, a nie Właściwości, w których typ jest złożony/inny typ. W naszym przypadku właściwości Id i Name będą odpowiednio powiązane z parametrem m, ale właściwość Tags będzie pustą listą.

Ten sam problem wystąpi, jeśli używasz skróconej wersji $.post, która użyje domyślnego typu zawartości podczas wysyłania żądania.

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});
 464
Author: Shyju,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 21:51:49

Praca z postem w webapi może być trudna! Chciałbym dodać do już poprawnej odpowiedzi..

Skupi się na poście, ponieważ radzenie sobie z GETEM jest trywialne. Nie sądzę, aby wielu szukało rozwiązania problemu z GET with webapis. W każdym razie..

Jeśli twoje pytanie dotyczy-w MVC Web Api, jak - - używać niestandardowych nazw metod akcji innych niż ogólne czasowniki HTTP? - Wykonać kilka postów? - Po wielu prostych typów? - Po złożeniu typów poprzez jQuery?

W takim razie pomocne mogą być następujące rozwiązania:

Po pierwsze, aby użyć własnych metod działania W Web API, dodaj trasę web api jako:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}");
}

I wtedy można tworzyć metody akcji takie jak:

[HttpPost]
public string TestMethod([FromBody]string value)
{
    return "Hello from http post web api controller: " + value;
}

Teraz odpal poniższy jQuery z konsoli przeglądarki

$.ajax({
    type: 'POST',
    url: 'http://localhost:33649/api/TestApi/TestMethod',
    data: {'':'hello'},
    contentType: 'application/x-www-form-urlencoded',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

Po drugie, aby wykonać wiele postów , jest to proste, utworzyć wiele metod akcji i udekorować za pomocą [HttpPost] attrib. Użyj [ActionName("MyAction")], aby przypisać własne nazwy, itd. Pojawi się w jQuery w czwartym punkcie poniżej

Po trzecie, po pierwsze, umieszczanie wielu typów prostych w jednej akcji nie jest możliwe. Ponadto istnieje specjalny format do wysyłania nawet pojedynczego prostego typu (poza przekazaniem parametru w łańcuchu zapytania lub stylu REST). To był punkt, który sprawił, że walnąłem się w głowę z Klientami Rest (takimi jak Fiddler i rozszerzenie Advanced Rest client Chrome) i polowałem po Internecie przez prawie 5 godzin kiedy w końcu, poniższy URL okazał się pomocny. Zacytuje odpowiednią treść Dla linku może okazać się martwy!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"[email protected]"}

PS: zauważyłeśosobliwą składnię ?

Http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

W każdym razie, zapomnijmy o tej historii. Idąc dalej:

Czwarty, wysyłanie typów złożonych przez jQuery, ofcourse,$.ajax() wkrótce pojawi się w roli:

Niech mówimy, że metoda akcji akceptuje obiekt Person, który ma id i nazwę. Tak, z javascript:

var person = { PersonId:1, Name:"James" }
$.ajax({
    type: 'POST',
    url: 'http://mydomain/api/TestApi/TestMethod',
    data: JSON.stringify(person),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

A akcja będzie wyglądała następująco:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}
[6]}wszystkie powyższe, zadziałały dla mnie!! Zdrowie!
 61
Author: Vaibhav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-03 13:59:31

Po prostu bawiłem się tym i odkryłem dość dziwny wynik. Powiedzmy, że masz publiczne właściwości na swojej klasie w C# w ten sposób:

public class Customer
{
    public string contact_name;
    public string company_name;
}
Więc musisz zrobić JSON.stringify trick zgodnie z sugestią Shyju i nazywaj go tak:
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});

Jeśli jednak zdefiniujesz gettery i settery na swojej klasie w następujący sposób:

public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}

Wtedy możesz nazwać to znacznie prościej:

$.ajax({
    type: "POST",
    data :customer,
    url: "api/Customer"
});

Używa nagłówka HTTP:

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

Nie jestem do końca pewien, co tu się dzieje, ale to wygląda jak bug (feature?) w ramach. Prawdopodobnie różne metody wiązania wywołują różne "adaptery" i podczas gdy adapter dla aplikacji/json działa z właściwościami publicznymi, ten dla zakodowanych danych nie działa.]} Nie mam pojęcia, co można by uznać za najlepszą praktykę.

 11
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 15:49:46

Użyj JSON.stringify () aby uzyskać ciąg znaków w formacie JSON, upewnij się, że podczas wykonywania wywołania AJAX przekazujesz niżej wymienione atrybuty:

  • contentType: 'application / json'
  • dataType: 'json'

Poniżej znajduje się kod give jquery do wywołania ajax post do asp.net web api:

var product =
    JSON.stringify({
        productGroup: "Fablet",
        productId: 1,
        productName: "Lumia 1525 64 GB",
        sellingPrice: 700
    });

$.ajax({
    URL: 'http://localhost/api/Products',
    type: 'POST',
    contentType: 'application/json',
    dataType: 'json',
    data: product,
    success: function (data, status, xhr) {
        alert('Success!');
    },
    error: function (xhr, status, error) {
        alert('Update Error occurred - ' + error);
    }
});
 1
Author: Dilip Nannaware,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-02 23:36:29

Upewnij się, że usługa WebAPI oczekuje silnie wpisanego obiektu o strukturze pasującej do JSON, który przekazujesz. I upewnij się, że dodajesz JSON, który publikujesz.

Oto Mój JavaScript (za pomocą AngluarJS):

$scope.updateUserActivity = function (_objuserActivity) {
        $http
        ({
            method: 'post',
            url: 'your url here',
            headers: { 'Content-Type': 'application/json'},
            data: JSON.stringify(_objuserActivity)
        })
        .then(function (response)
        {
            alert("success");
        })
        .catch(function (response)
        {
            alert("failure");
        })
        .finally(function ()
        {
        });

A oto mój Kontroler WebAPI:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}
 0
Author: scott janson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 16:07:33

Poniższy kod zwraca dane w formacie json, zamiast XML-Web API 2 :-

Umieść następującą linię w globalnym.plik asax

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
 0
Author: UJS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 09:19:54
@model MVCClient.Models.ProductDetails

@{
    ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">

    $(document).ready(function () {
        $("#Save").click(function () {
            var ProductDetails = new Object();
            ProductDetails.ProductName =  $("#txt_productName").val();
            ProductDetails.ProductDetail = $("#txt_desc").val();
            ProductDetails.Price= $("#txt_price").val();
            $.ajax({
                url: "http://localhost:24481/api/Product/addProduct",
                type: "Post",
                dataType:'JSON',
                data:ProductDetails, 

                success: function (data) {
                    alert('Updated Successfully');
                    //window.location.href = "../Index";
                },
                error: function (msg) { alert(msg); }
            });
        });
    });
    </script>
<h2>ProductDetails</h2>

<form id="form1" method="post">
    <fieldset>
        <legend>ProductDetails</legend>


        <div class="editor-label">
            @Html.LabelFor(model => model.ProductName)
        </div>
        <div class="editor-field">

            <input id="txt_productName" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductDetail)
        </div>
        <div class="editor-field">

            <input id="txt_desc" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductDetail)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">

            <input id="txt_price" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.Price)
        </div>



        <p>
            <input id="Save" type="button" value="Create" />
        </p>
    </fieldset>

</form>
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>

</form>



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
 0
Author: Debendra Dash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-07 13:03:23

Microsoft dał dobry przykład:

Https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-1

Najpierw Zatwierdź żądanie

if (ModelState.IsValid)

A następnie użyć danych seryjnych.

Content = new StringContent(update.Status)

Tutaj 'Status' jest polem typu complex. Serializacja jest wykonywana przez. Net, nie musisz się o to martwić.

 0
Author: FrankyHollywood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 13:51:07

1) Po stronie klienta możesz wysłać http.post request in string like below

var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}

2) Następnie w kontrolerze web api możesz go deserializować

public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
    {
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}

3) twoja klasa ApiReceivedListOfObjects powinna być taka jak poniżej

public class ApiReceivedListOfObjects<T>
    {
        public List<T> element { get; set; }

    }

4)Upewnij się, że Twój serializowany łańcuch znaków (IndexInfo tutaj) będzie podobny do poniższej struktury przed JsonConvert.Polecenie DeserializeObject w Kroku 2

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";
 0
Author: Mahdi ghafoorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-04 12:37:49