¿Cómo pasar datos json POST al método Web API como un objeto?


ASP.NET La aplicación MVC4 Web API define el método post para guardar al cliente. El cliente se pasa en formato json en el cuerpo de la solicitud POSTERIOR. El parámetro Cliente en el método post contiene valores nulos para las propiedades.

¿Cómo solucionar esto para que los datos publicados se pasen como objeto cliente ?

Si es posible Content-Type: application / x-www-form-urlencoded debe usarse ya que no sé cómo cambiarlo en el método javascript que publica forma.

Controlador:

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

Solicitud:

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

EDITAR : 31/10/2017

El mismo código/enfoque funcionará para Asp.Net Core 2.0 también. La principal diferencia es, En asp.net core, tanto los controladores de api web como los controladores Mvc se fusionan en un solo modelo de controlador. Por lo tanto, su tipo de retorno podría ser IActionResult o una de sus implementaciones (Ex :OkObjectResult)


Use

contentType:"application/json"

Necesitas usar el método JSON.stringify para convertirlo a cadena JSON cuando lo envíes,

Y el modelo binder enlaza los datos json al objeto de clase.

El siguiente código funcionará bien (probado)

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

Resultado

introduzca la descripción de la imagen aquí

contentType propiedad indica al servidor que estamos enviando los datos en formato JSON. Dado que enviamos una estructura de datos JSON, el enlace del modelo se realizará correctamente.

Si inspecciona los encabezados de la solicitud ajax, puede ver que el valor Content-Type se establece como application/json.

Si no especifica ContentType explícitamente, utilizará el tipo de contenido predeterminado que es application/x-www-form-urlencoded;


Editar en noviembre de 2015 para abordar otras posibles cuestiones planteadas en los comentarios

Publicar un objeto complejo

Supongamos que tiene una clase de modelo de vista compleja como parámetro del método de acción de la api web como este

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

Y el punto final de la api web es como

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

En el momento de escribir este artículo, ASP.NET MVC 6 es la última versión estable y en MVC6, tanto Web api controllers como MVC controllers heredan de la clase base Microsoft.AspNet.Mvc.Controller.

Para enviar datos al método desde el lado del cliente, el siguiente código debería funcionar bien

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

El enlace de modelos funciona para algunas propiedades, ¡pero no para todas ! ¿Por qué?

Si no decora el parámetro del método web api con [FromBody] atributo

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

Y enviar el modelo (objeto javascript sin procesar, no en formato JSON) sin especificar el valor de la propiedad ContentType

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

La encuadernación de modelo funcionará para el plano propiedades en el modelo, no las propiedades donde el tipo es complejo / otro tipo. En nuestro caso, las propiedades Id y Name estarán correctamente vinculadas al parámetro m, pero la propiedad Tags será una lista vacía.

El mismo problema ocurrirá si está utilizando la versión corta, $.post que utilizará el tipo de contenido predeterminado al enviar la solicitud.

$.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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-31 21:51:49

Trabajar con POST en webapi puede ser complicado! Quisiera agregar a la respuesta correcta..

Se centrará específicamente en POST ya que tratar con GET es trivial. No creo que muchos estarían buscando para resolver un problema con GET con webapis. De todos modos..

Si su pregunta es - En MVC Web Api, ¿cómo- - Usar nombres de métodos de acción personalizados que no sean los verbos HTTP genéricos? - Realizar múltiples publicaciones? - Post múltiples tipos simples? - Post tipos complejos vía jQuery?

Entonces las siguientes soluciones pueden ayudar:

Primero, para usar Métodos de acción personalizados en Web API, agregue una ruta web api como:

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

Y luego puedes crear métodos de acción como:

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

Ahora, ejecute el siguiente jQuery desde la consola de su navegador

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

Segundo, para realizar múltiples posts, es simple, crear múltiples métodos de acción y decorar con el atributo [HttpPost]. Utilice [ActionName ("MyAction")] para asignar nombres personalizados, sucesivamente. Llegará a jQuery en el cuarto punto a continuación

En tercer lugar, en primer lugar, no es posible publicar múltiples tipos SIMPLES en una sola acción. Además, existe un formato especial para publicar incluso un tipo simple (aparte de pasar el parámetro en la cadena de consulta o el estilo REST). Este fue el punto que me tenía golpeando la cabeza con los clientes de descanso (como Fiddler y Chrome Avanzada de la extensión del cliente de DESCANSO) y la caza alrededor de la web durante casi 5 horas cuando finalmente, la siguiente URL resultó ser de ayuda. Se cita el contenido relevante para el enlace podría resultar muerto!

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

PD: ¿Notó la sintaxis peculiar?

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

De todos modos, superemos esa historia. Continuando:

Cuarto, publicando tipos complejos a través de jQuery, por supuesto, $.ajax () va a llegar rápidamente en el papel:

Let digamos que el método action acepta un objeto Person que tiene un id y un nombre. Entonces, desde 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) }
});

Y la acción se verá como:

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

Todo lo anterior, funcionó para mí!! ¡Salud!

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-03 13:59:31

He estado jugando con esto y descubrí un resultado bastante extraño. Digamos que tienes propiedades públicas en tu clase en C# como esta:

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

Entonces debes hacer el JSON.stringify truco como sugerido por Shyju y llamarlo así:

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

Sin embargo, si define getters y setters en su clase de esta manera:

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

Entonces puedes llamarlo mucho más simple:

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

Esto usa el encabezado HTTP:

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

No estoy muy seguro de lo que está sucediendo aquí, pero parece un error (característica? en el marco. Presumiblemente, los diferentes métodos de enlace están llamando a diferentes "adaptadores", y mientras que el adaptador para application/json uno funciona con propiedades públicas, el otro para datos codificados en forma no lo hace.

Sin embargo, no tengo idea de cuál se consideraría la mejor práctica.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-21 15:49:46

Utilice el JSON.stringify () para obtener la cadena en formato JSON, asegúrese de que al hacer la llamada AJAX pase los atributos mencionados a continuación:

  • Tipo de contenido:'application/json'
  • Tipo de datos: 'json'

A continuación se muestra el código give jquery para hacer una llamada post ajax asp.net api web:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-02 23:36:29

Asegúrese de que su servicio WebAPI espera un objeto fuertemente escrito con una estructura que coincida con el JSON que está pasando. Y asegúrese de que usted stringify el JSON que está publicando.

Aquí está mi JavaScript (usando 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 ()
        {
        });

Y aquí está mi Controlador 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-22 16:07:33

Siguiente código para devolver datos en el formato json ,en lugar de la API xml-Web 2 :-

Ponga la siguiente línea en el Global.archivo 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 13:03:23

Microsoft dio un buen ejemplo de hacer esto:

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

Primero valida la solicitud

if (ModelState.IsValid)

Y luego usar los datos serializados.

Content = new StringContent(update.Status)

Aquí 'Status' es un campo en el tipo complejo. La serialización se realiza por. NET, no hay necesidad de preocuparse por eso.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 13:51:07

1) En el lado del cliente puede enviarle 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) Luego en su controlador de api web puede deserializarlo

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

3) Su clase ApiReceivedListOfObjects debe ser como la siguiente

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

    }

4)asegúrese de que su cadena serializada (IndexInfo aquí) se convierta en la siguiente estructura antes de JsonConvert.Comando DeserializeObject en el paso 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-04 12:37:49