Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
307 views
in Technique[技术] by (71.8m points)

javascript - 如何将json POST数据作为对象传递给Web API方法?(How to pass json POST data to Web API method as an object?)

ASP.NET MVC4 Web API application defines post method to save customer.

(ASP.NET MVC4 Web API应用程序定义了保存客户的post方法。)

Customer is passed in json format in POST request body.

(客户在POST请求正文中以json格式传递。)

Customer parameter in post method contains null values for properties.

(post方法中的customer参数包含属性的空值。)

How to fix this so that posted data will passed as customer object ?

(如何解决这个问题,以便发布的数据作为客户对象传递?)

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

(如果可能的话Content-Type:application / x-www-form-urlencoded应该使用,因为我不知道如何在发布表单的javascript方法中更改它。)

Controller:

(控制器:)

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

Request:

(请求:)

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"}
  ask by Andrus translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDIT : 31/10/2017

(编辑 :31/10/2017)

The same code/approach will work for Asp.Net Core 2.0 as well.

(相同的代码/方法也适用于Asp.Net Core 2.0 。)

The major difference is, In asp.net core, both web api controllers and Mvc controllers are merged together to single controller model.

(主要区别在于,在asp.net核心中,web api控制器和Mvc控制器都合并到单个控制器模型中。)

So your return type might be IActionResult or one of it's implementation (Ex : OkObjectResult )

(所以你的返回类型可能是IActionResult或其中一个实现(例如: OkObjectResult ))


Use

(使用)

contentType:"application/json"

You need to use JSON.stringify method to convert it to JSON string when you send it,

(发送时需要使用JSON.stringify方法将其转换为JSON字符串,)

And the model binder will bind the json data to your class object.

(模型绑定器将json数据绑定到您的类对象。)

The below code will work fine (tested)

(以下代码将正常工作(测试))

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

Result

(结果)

在此输入图像描述

contentType property tells the server that we are sending the data in JSON format.

(contentType属性告诉服务器我们正在以JSON格式发送数据。)

Since we sent a JSON data structure,model binding will happen properly.

(由于我们发送了JSON数据结构,因此模型绑定将正确发生。)

If you inspect the ajax request's headers, you can see that the Content-Type value is set as application/json .

(如果检查ajax请求的标头,则可以看到Content-Type值设置为application/json 。)

If you do not specify contentType explicitly, It will use the default content type which is application/x-www-form-urlencoded;

(如果您没有明确指定contentType,它将使用默认的内容类型,即application/x-www-form-urlencoded;)


Edit on Nov 2015 to address other possible issues raised in comments

(2015年11月编辑,以解决评论中提出的其他可能问题)

Posting a complex object(发布复杂对象)

Let's say you have a complex view model class as your web api action method parameter like this

(假设你有一个复杂的视图模型类作为你的web 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;}
}

and your web api end point is like

(和你的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;
    }
}

At the time of this writing, ASP.NET MVC 6 is the latest stable version and in MVC6, Both Web api controllers and MVC controllers are inheriting from Microsoft.AspNet.Mvc.Controller base class.

(在撰写本文时,ASP.NET MVC 6是最新的稳定版本,在MVC6中,Web api控制器和MVC控制器都继承自Microsoft.AspNet.Mvc.Controller基类。)

To send data to the method from client side, the below code should work fine

(要从客户端向方法发送数据,下面的代码应该可以正常工作)

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

Model binding works for some properties, but not all !(模型绑定适用于某些属性,但不是全部!) Why ?(为什么?)

If you do not decorate the web api method parameter with [FromBody] attribute

(如果不使用[FromBody]属性修饰web api方法参数)

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

And send the model(raw javascript object, not in JSON format) without specifying the contentType property value

(并且在不指定contentType属性值的情况下发送模型(原始javascript对象,而不是JSON格式))

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

Model binding will work for the flat properties on the model, not the properties where the type is complex/another type.

(模型绑定适用于模型上的平面属性,而不适用于类型复杂/其他类型的属性。)

In our case, Id and Name properties will be properly bound to the parameter m , But the Tags property will be an empty list.

(在我们的例子中, IdName属性将正确绑定到参数m ,但Tags属性将是一个空列表。)

The same problem will occur if you are using the short version, $.post which will use the default Content-Type when sending the request.

(如果您使用的是简短版本$.post ,在发送请求时将使用默认的Content-Type,则会出现同样的问题。)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...