Jak przenieść dane JSON POST w metoda Web API jako obiektu?

ASP.NET pomocą MVC4 web aplikacji z API-interfejs określa metodę POST, aby utrzymać klienta. Klient jest przekazywana w formacie json w treści żądania POST. Parametr Customer w metodzie post zawiera zerowe wartości dla właściwości.

Jak to naprawić, aby rozstawione, dane przekazywane jako obiekt klienta ?

Jeśli to możliwe Content-Type: application/x-www-form-urlencoded powinien być używany, ponieważ nie wiem jak zmienić go w metodzie javascript, który publikuje formularz.

:
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"}

EDIT: 31/10/2017

ten sam kod / podejście będzie pracować dla Asp.Net Core 2.0 jak dobrze. Główną różnicą jest to, że asp.net rdzeń, kontrolery sieci web api i kontrolery Mvc łączą się w jeden model kontrolera. W ten sposób twój typ zwrotu może być IActionResult lub jednego z jego realizacji (np.:OkObjectResult)


użyj

contentType:"application/json"

trzeba użyć JSON.stringify metoda konwersji go na ciąg znaków JSON, gdy chodź,

i spoiwa urządzenie modelu połączy dane json do obiektu klasy.

poniższy kod będzie działać dobrze (sprawdzone)

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

wynik

enter image description here

contentType właściwości informuje serwer, że wysyłamy dane w formacie JSON. Ponieważ wysłaliśmy struktury danych JSON, powiązanie modelu nastąpi poprawnie.

jeśli sprawdzisz nagłówki ajax zapytania, zobaczysz, że Content-Type wartość jest ustawiana jako application/json.

jeśli nie podasz contentType wyraźnie, że będzie korzystać z typu zawartości domyślnie, który jest application/x-www-form-urlencoded;


Edit on Nov 2015 do rozwiązywania innych problemów poruszonych w komentarzach

noclegi skomplikowanego obiektu

załóżmy, że masz klasę modelu złożonego pojęcia jako parametr metody działania sieci web api, np.

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;}
}

i twój punkt końcowy sieci web api

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 momencie pisania tego artykułu, ASP.NET MVC 6-najnowsza stabilna wersja, i w MVC6 kontrolery Web api i kontrolery MVC są dziedziczone od Microsoft.AspNet.Mvc.Controller klasa bazowa.

aby wysłać dane do metody ze strony klienta, poniższy kod powinien działać normalnie

//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 :)
});

powiązanie modelu działa dla niektórych właściwości, ale nie wszystkie ! Dlaczego?

jeśli nie украсите parametr metody Web api za pomocą [FromBody] atrybut

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

i wysłać model (bez leczenia 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);
});

powiązanie modelu będzie działać dla płaskich właściwości modelu, a nie do właściwości, gdzie typ złożony/inny typ. W naszym przypadku, Id a Name właściwości będą poprawnie przywiązani do opcji m a Tags właściwość będzie pustą listą.

ten sam problem wystąpi jeśli korzystasz z krótką wersję, $.post który będzie korzystać z typu zawartości domyślnie podczas wysyłania żądania.

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});

praca z POST do webapi może być trudne! Chciałbym dodać do prawidłowej odpowiedzi..

będzie się koncentrować w szczególności na wiadomości, ponieważ praca z GET trywialne. Myślę, że wielu będzie szukać rozwiązania problemu z GET z webapis. W każdym przypadku..

jeśli twoje pytanie - w MVC, Web Api, jak - używać nazwy niestandardowe metody działania, odmienne od ogólnych http czasowników? - Wykonać kilka postów? - Po kilku prostych typów? - Typy poczta złożone przez jQuery?

wtedy mogą pomóc następujące rozwiązania:

po pierwsze, należy użyć celnych metody działania w sieci web API dodaj trasę web api jak:

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

i następnie można utworzyć metody działania, takie jak:

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

teraz uruchom następujący 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, wykonaj kilka wiadomości to po prostu, utwórz kilka metod działania i udekoruj [HttpPost] attrib. Używać [ActionName ("myaction z przeglądarki")], aby przypisać nazw własnych itp. Przyjdzie do jQuery w czwartym akapicie poniżej

po trzecie, przede wszystkim umieszczanie wielu prosty typy w jednej akcji nie jest możliwe. Ponadto, istnieje specjalny format opublikować nawet jeden prosty typu (z wyjątkiem transmisji parametr w wierszu kwerendy lub stylu REST). To było coś, co sprawiło, że walenie głową z klientami Rest (np. Fiddler i Chrome Advanced REST client extension) i polowanie w internecie w ciągu prawie 5 godzin, gdy w końcu następny URL okazał się przydatny. Będzie cytować treści odwołania może być 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łem specyficzna składnia?

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, skończmy z tą historią. Ruszamy dalej:--7-->

czwarty, księgowanie złożonych typów przez jQuery, oczywiście, $.ajax () będzie szybko przyjść w roli:

załóżmy, że metoda działania przyjmuje obiekt Person, który ma identyfikator i nazwę. Tak więc, 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) }
});

i akcja będzie wyglądać tak:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}

wszystkie powyższe, działało na mnie!! Hura!


właśnie grałem z tym i znalazłem dość dziwny wynik. Powiedzmy, że masz publiczne właściwości w swojej klasie W C#, np.:

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

następnie należy zrobić JSON.stringify sztuczka, jak zaproponował Shyju i nazwij go tak:

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

jednak, jeśli można zdefiniować zarówno gettery jak i settery w 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żna nazwać to o wiele łatwiejsze:

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

przy tym wykorzystywany jest protokół HTTP tytuł:

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

nie Jestem do końca pewien, co tu się dzieje, ale to wygląda na błąd (funkcja?) w ramach. Prawdopodobnie różne metody wiązania wywołują różne "adaptery", i choć adapter do application/json współpracuje z publicznymi właściwości, dla danych zakodowanych w formie, nie ma.

nie mam pojęcia, co będzie uznane za najlepszą praktykę.


użyj JSON.przekształcić w ciąg() aby uzyskać ciąg w formacie JSON, upewnij się, że podczas rozmowy AJAX przekazuje następujące atrybuty:

  • contentType: 'application / json'
  • typ danych:'json'

Poniżej znajduje się kod give jquery ajax rozmowy post 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);
    }
});

upewnij się, że usługa do WebAPI czeka silnie typizowanej obiekt o strukturze odpowiedniej JSON, który możesz przekazać. I upewnij się, że stringify JSON, który piszesz.

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 ()
        {
        });

i tu jest mój kontroler do WebAPI:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}

poniższy kod, aby powrócić danych w formacie json zamiast xml Web API 2 : -

umieść następujący wiersz w globalny.plik asax

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

@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")
}

Microsoft dała dobry przykład:

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

najpierw sprawdź, czy zapytanie

if (ModelState.IsValid)

i co używać odcinkach dane.

Content = new StringContent(update.Status)

tutaj "status" - jest to pole typu złożonego. Szeregowania jest wykonywana .NET, nie musisz się o to martwić.


1)po stronie klienta można wysłać http.żądanie post w wierszu, jak pokazano poniżej

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

2) następnie w swoim kontrolerze sieci web api można deserializacji go

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

3) klasa ApiReceivedListOfObjects musi być jak poniżej

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

    }

4) Upewnij się, że twoja сериализованная wiersz (IndexInfo tutaj) staje się jak poniżej struktury przed JsonConvert.Zespół DeserializeObject w kroku 2

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";