Nano Hash - криптовалюты, майнинг, программирование

Как передать данные json POST в метод веб-API в виде объекта?

Приложение веб-API ASP.NET MVC4 определяет метод публикации для спасения клиента. Клиент передается в формате json в теле запроса POST. Параметр клиента в методе post содержит значения NULL для свойств.

Как исправить это, чтобы опубликованные данные передавались как объект клиента?

Если возможно, следует использовать Content-Type: application / x-www-form-urlencoded, поскольку я не знаю, как изменить его в методе javascript, который формирует сообщения.

Контроллер:

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

Запрос:

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

Ответы:


1

РЕДАКТИРОВАТЬ: 31.10.2017

Тот же код / ​​подход будет работать и для Asp.Net Core 2.0. Основное различие заключается в том, что в ядре asp.net и контроллеры веб-API, и контроллеры Mvc объединены в модель с одним контроллером. Таким образом, ваш тип возврата может быть IActionResult или одной из его реализаций (Пример: OkObjectResult)


Использовать

contentType:"application/json"

Вам нужно использовать метод JSON.stringify, чтобы преобразовать его в строку JSON при отправке,

И связыватель модели свяжет данные json с вашим объектом класса.

Приведенный ниже код будет работать нормально (проверено)

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

Результат

введите описание изображения здесь

contentType сообщает серверу, что мы отправляем данные в формате JSON. Поскольку мы отправили структуру данных JSON, привязка модели произойдет правильно.

Если вы проверите заголовки запроса ajax, вы увидите, что значение Content-Type установлено как application/json.

Если вы не укажете contentType явно, он будет использовать тип содержимого по умолчанию, равный application/x-www-form-urlencoded;.


Отредактируйте ноябрь 2015 г., чтобы устранить другие возможные проблемы, поднятые в комментариях

Размещение сложного объекта

Допустим, у вас есть класс модели сложного представления в качестве параметра метода действия веб-API, подобного этому

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

и ваша конечная точка веб-API похожа на

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewModel 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;
    }
}

На момент написания этой статьи ASP.NET MVC 6 является последней стабильной версией, а в MVC6 и веб-контроллеры api, и контроллеры MVC наследуются от базового класса Microsoft.AspNet.Mvc.Controller.

Чтобы отправить данные в метод со стороны клиента, приведенный ниже код должен работать нормально.

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

Привязка модели работает для некоторых свойств, но не для всех! Почему ?

Если вы не украшаете параметр метода веб-API атрибутом [FromBody]

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

И отправьте модель (необработанный объект javascript, а не в формате JSON) без указания значения свойства contentType

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

Привязка модели будет работать для плоских свойств модели, а не для свойств, для которых тип является сложным / другим типом. В нашем случае свойства Id и Name будут правильно привязаны к параметру m, но свойство Tags будет пустым списком.

Та же проблема возникнет, если вы используете короткую версию $.post, которая будет использовать Content-Type по умолчанию при отправке запроса.

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});
26.11.2013
  • Не уверен, что я сделал, но я вернулся сегодня утром и вернулся в той же лодке. Объект в контроллере равен нулю. вот и мы снова лол 01.10.2014
  • хорошо, 2 часа, и я не могу понять это. В моем случае только для тестирования я отправляю сообщения от скрипачей. У меня установлен тип контента Content-Type: application / json. У меня есть модель просмотра, в которой я тоже пытаюсь привязать данные. Я дошел до изменения модели представления, чтобы она содержала только один элемент, {\ AssetName \: \ testname \}, и мой контроллер выглядит так, как этот [HttpPost] общедоступный HttpResponseMessage LogValidation ([FromBody] myViewModel myviewmodel) {сообщение попадает контроллер, но myviewmodel всегда имеет значение null. 01.10.2014
  • @Grayson, можете ли вы опубликовать минимизированный образец решения, чтобы я мог посмотреть? 01.10.2014
  • убедитесь, что тип контента написан Content-Type: application / json, пока вы используете скрипач. Ваше здоровье! 07.01.2015
  • Ты просто решил мне день работы !!! Эта крошечная функция JSON.stringify (data) сделала это! 01.02.2015
  • @Shyju, какое программное обеспечение вы использовали для отображения этой информации? 26.03.2015
  • Имейте в виду, что если вы сделаете это (измените заголовок Content-Type) и сделаете запрос CORS, jQuery начнет добавлять предварительные запросы OPTIONS перед вашим POST, которые сервер должен будет обработать. 16.06.2015
  • @Grayson - Я знаю, что это год спустя, но у меня такая же действительно отягчающая проблема. Использование правильного типа содержимого application / json; используя значения json, соответствующие классу. Но в функции веб-API параметр отображается как null. Еще больше расстраивает - у меня есть еще одна функция api, где другой класс отлично работает! Я использую почтальон, поэтому могу построить звонок именно так, как он должен быть. Нет заметной разницы между двумя способами, которые работают и не работают. 23.11.2015
  • Из-за проблемы со сложными типами я думаю, что есть привычка просто указывать contentType: application / json; и json преобразовывают объект js в строку, и тогда нет необходимости использовать атрибут [FromBody]. 14.02.2016
  • В моем случае некоторые параметры модели опускаются парсером без причины! Поля модели типа DateTime? не анализируются из строк «yyyy-MM-dd» в POST, но анализируются в GET с [FromUri], установленным для модели. 24.02.2016
  • Если у кого-то возникают такие же проблемы с анализом некоторых параметров модели: атрибут [JsonConverter(typeof (YourCustomConverter))] - решение для таких полей. 24.02.2016
  • Как передать некоторые простые типы и сложный тип? 02.06.2016
  • @Shavais, AFAIK, это невозможно (по умолчанию). Просто объедините все данные в один DTO. 05.08.2016
  • @Shavais Не могли бы вы проверить мой вопрос? Я не могу решить эту проблему: stackoverflow.com/questions/40545603/ 11.11.2016
  • Я получаю эту ошибку: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 26.01.2017
  • Я должен тебе тусовщик 01.05.2018
  • И каждые два года нам придется заново продумывать, как это сделать. 07.06.2018

  • 2

    Работа с POST в webapi может быть сложной задачей! Хочу добавить к уже правильному ответу ..

    Особое внимание уделим POST, поскольку работа с GET тривиальна. Я не думаю, что многие будут искать решение проблемы с GET с помощью webapis. В любом случае..

    Если ваш вопрос - в MVC Web Api, как - - использовать имена методов настраиваемых действий, отличные от общих HTTP-глаголов? - Выполнять несколько постов? - Опубликовать несколько простых типов? - Публиковать сложные типы через jQuery?

    Тогда могут помочь следующие решения:

    Во-первых, чтобы использовать настраиваемые методы действий в веб-API, добавьте маршрут веб-API как:

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

    А затем вы можете создать такие методы действий, как:

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

    Теперь запустите следующий jQuery из консоли браузера

    $.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) }
    });
    

    Во-вторых, чтобы выполнить несколько сообщений, просто создайте несколько методов действий и украсьте атрибутом [HttpPost]. Используйте [ActionName ("MyAction")] для назначения пользовательских имен и т. Д. Перейдем к jQuery в четвертом пункте ниже.

    В-третьих, во-первых, размещение нескольких типов ПРОСТОЙ в одном действии невозможно. Более того, существует специальный формат для публикации даже одного простого типа (помимо передачи параметра в строке запроса или стиле REST). Это был момент, который заставил меня биться головой о Rest Clients (например, Fiddler и расширенное клиентское расширение REST в Chrome) и искать в Интернете почти 5 часов, когда в конечном итоге следующий URL-адрес оказался полезным. Процитирую релевантный контент по ссылке может стать мертвой!

    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: Заметили своеобразный синтаксис?

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

    В любом случае, давайте закончим эту историю. Двигаемся дальше:

    В-четвертых, отправка сложных типов через jQuery, конечно же, тут же вступит в эту роль $ .ajax ():

    Допустим, метод действия принимает объект Person, у которого есть идентификатор и имя. Итак, из 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) }
    });
    

    И действие будет выглядеть так:

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

    Все вышеперечисленное у меня сработало !! Ваше здоровье!

    19.03.2014
  • Кажется, я сталкиваюсь с этой проблемой каждые несколько месяцев, в большинстве случаев я ее решаю, но на этот раз я сдался. Ни один из приведенных выше советов не решает эту проблему для меня, поэтому я решил отбросить это как подход. Если это ТАК сложно понять, зачем? В любом случае это всего лишь удобство - просто возьмите содержимое в виде строки и используйте newtonsoft для его преобразования. Выполнено. Потребовалось, вероятно, 30 секунд, чтобы решить ее сложным путем, после примерно часа попыток решить ее простым способом. Я не в восторге от такого подхода, но есть ли в нем фундаментальная проблема? 20.10.2015
  • PS: В WebApi2 теперь мы можем использовать декораторы маршрутов. Так что в первую очередь решается этот вопрос. asp.net/web-api/overview/web-api-routing-and-actions/ 05.08.2016
  • Хотел бы добавить наблюдение. Иногда причина сбоя привязки модели (null) на стороне WebAPI при передаче сложного типа (например, DTO) заключается в том, что одно или несколько свойств в модели несовместимы (или не могут быть проанализированы). Например. Свойству Guid назначен недопустимый идентификатор GUID. В этом случае попробуйте использовать значения по умолчанию / пустые значения для всех свойств объекта и повторите попытку. 29.12.2016

  • 3

    Я просто играл с этим и обнаружил довольно странный результат. Скажем, у вас есть общедоступные свойства вашего класса на C #, например:

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

    тогда вы должны выполнить трюк с JSON.stringify, как предлагает Shyju, и назвать его так:

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

    Однако, если вы определяете геттеры и сеттеры в своем классе следующим образом:

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

    тогда вы можете назвать это намного проще:

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

    Здесь используется заголовок HTTP:

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

    Я не совсем уверен, что здесь происходит, но это похоже на ошибку (особенность?) Во фреймворке. Предположительно, разные методы привязки вызывают разные «адаптеры», и хотя адаптер для application / json работает с общедоступными свойствами, другой - для данных, закодированных в форме, - нет.

    Я понятия не имею, что можно было бы считать лучшей практикой.

    21.04.2015
  • Свойства и поля - вот почему все по-другому. Недвижимость - лучшая практика. То, что вы называете свойствами в первом примере, на самом деле является полями. Когда вы накладываете на них get / set, у них появляется автоматически созданное резервное поле, которое делает их свойствами. 15.05.2015
  • Это так верно и странно. Обычные классы только с полями не привязываются к формированию сообщений, но свойства будут. BTW: Все еще не объясняет, почему это так ...? Я могу только догадываться, что внутренняя логика будет только связывать данные JSON с полями и формировать данные публикации для свойств, и это просто ...? 28.04.2016
  • Дело в том, что код ищет только свойства. Поскольку использование общедоступных полей является не лучшей практикой, команда MS решила не допускать не сценариев передовой практики, что, по-моему, довольно веская причина. 13.06.2016

  • 4

    Используйте JSON.stringify (), чтобы получить строку в формате JSON, убедитесь, что при выполнении вызова AJAX вы передаете указанные ниже атрибуты:

    • contentType: 'приложение / json'

    Ниже приведен код jquery для выполнения вызова ajax post для веб-api asp.net:

    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',
        data: product,
        success: function (data, status, xhr) {
            alert('Success!');
        },
        error: function (xhr, status, error) {
            alert('Update Error occurred - ' + error);
        }
    });

    02.10.2015
  • dataType не требуется. 13.06.2016

  • 5

    Убедитесь, что ваша служба WebAPI ожидает строго типизированный объект со структурой, соответствующей передаваемому вами JSON. И убедитесь, что вы структурируете JSON, который вы публикуете.

    Вот мой JavaScript (с использованием 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 ()
            {
            });
    

    А вот и мой контроллер WebAPI:

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

    6

    Следующий код для возврата данных в формате json вместо xml -Web API 2: -

    Поместите следующую строку в файл Global.asax

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

    7

    Microsoft привела хороший пример этого:

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

    Сначала подтвердите запрос

    if (ModelState.IsValid)
    

    и чем использовать сериализованные данные.

    Content = new StringContent(update.Status)
    

    Здесь «Статус» - это поле сложного типа. Сериализация выполняется .NET, не беспокойтесь об этом.

    22.06.2017

    8

    1) На стороне клиента вы можете отправить запрос http.post в строке, как показано ниже.

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

    2) Затем в своем веб-контроллере api вы можете десериализовать его

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

    3) Ваш класс ApiReceivedListOfObjects должен быть таким, как показано ниже

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

    4) убедитесь, что ваша сериализованная строка (здесь IndexInfo) становится похожей на структуру ниже перед командой JsonConvert.DeserializeObject на шаге 2

    var resp = @"
        {
            ""element"": [
            {
                ""A"": ""A Jones"",
                ""B"": ""500015763""
            },
            {
                ""A"": ""B Smith"",
                ""B"": ""504986213""
            },
            {
                ""A"": ""C Brown"",
                ""B"": ""509034361""
            }
            ]
        }";
    
    04.03.2018
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..