WebAPI多个Put / Post参数

我想在WebAPI控制器上发布多个参数。 一个参数来自URL,另一个来自主体。 这里是url: /offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

这是我的控制器代码:

 public HttpResponseMessage Put(Guid offerId, OfferPriceParameters offerPriceParameters) { //What!? var ser = new DataContractJsonSerializer(typeof(OfferPriceParameters)); HttpContext.Current.Request.InputStream.Position = 0; var what = ser.ReadObject(HttpContext.Current.Request.InputStream); return new HttpResponseMessage(HttpStatusCode.Created); } 

该机构的内容是在JSON中:

 { "Associations": { "list": [ { "FromEntityId":"276774bb-9bd9-4bbd-a7e7-6ed3d69f196f", "ToEntityId":"ed0d2616-f707-446b-9e40-b77b94fb7d2b", "Types": { "list":[ { "BillingCommitment":5, "BillingCycle":5, "Prices": { "list":[ { "CurrencyId":"274d24c9-7d0b-40ea-a936-e800d74ead53", "RecurringFee":4, "SetupFee":5 }] } }] } }] } } 

任何想法为什么默认绑定不能绑定到我的控制器的offerPriceParameters参数? 它始终设置为空。 但是我能够使用DataContractJsonSerializer从正文中恢复数据。

我也尝试使用参数的FromBody属性,但它也不起作用。

编辑:如果你正在使用WebAPI 2(并希望你是如果你正在阅读这个编辑完成后),请参阅http://www.asp.net/web-api/overview/formats-and-model-绑定/参数绑定在aspnet-web-api中; 。

你不能用WebAPI来做到这一点。 请参阅http://www.west-wind.com/weblog/posts/2012/May/08/Passing-multiple-POST-parameters-to-Web-API-Controller-Methods详细了解它,以及一些有用的解决方法。;

如果你search“从身体”,你也会发现一个特别处理你的替代尝试的评论。

原生WebAPI不支持绑定多个POST参数。 正如科林所指出的那样,我在他的博客文章中提到了一些限制。

有一个解决方法是创build一个自定义参数联编程序。 这样做的代码是丑陋的,令人费解的,但我已经在我的博客上发布了代码和详细的解释,准备插入到这里的项目:

将多个简单的POST值传递给ASP.NET Web API

 [HttpPost] public string MyMethod([FromBody]JObject data) { Customer customer = data["customerData"].ToObject<Customer>(); Product product = data["productData"].ToObject<Product>(); Employee employee = data["employeeData"].ToObject<Employee>(); //... other class.... } 

使用参考

 using Newtonsoft.Json.Linq; 

使用Request for JQuery Ajax

 var customer = { "Name": "jhon", "Id": 1, }; var product = { "Name": "table", "CategoryId": 5, "Count": 100 }; var employee = { "Name": "Fatih", "Id": 4, }; var myData = {}; myData.customerData = customer; myData.productData = product; myData.employeeData = employee; $.ajax({ type: 'POST', async: true, dataType: "json", url: "Your Url", data: myData, success: function (data) { console.log("Response Data ↓"); console.log(data); }, error: function (err) { console.log(err); } }); 

我们通过HttpPost方法传递Json对象,并将其parsing为dynamic对象。 它工作正常。 这是示例代码:

 ajaxPost: ... Content-Type: application/json, data: {"AppName":"SamplePrice", "AppInstanceID":"100", "ProcessGUID":"072af8c3-482a-4b1c‌​-890b-685ce2fcc75d", "UserID":"20", "UserName":"Jack", "NextActivityPerformers":{ "39‌​c71004-d822-4c15-9ff2-94ca1068d745":[{ "UserID":10, "UserName":"Smith" }] }} ... 

的WebAPI:

 [HttpPost] public string DoJson2(dynamic data) { //whole: var c = JsonConvert.DeserializeObject<YourObjectTypeHere>(data.ToString()); //or var c1 = JsonConvert.DeserializeObject< ComplexObject1 >(data.c1.ToString()); var c2 = JsonConvert.DeserializeObject< ComplexObject2 >(data.c2.ToString()); string appName = data.AppName; int appInstanceID = data.AppInstanceID; string processGUID = data.ProcessGUID; int userID = data.UserID; string userName = data.UserName; var performer = JsonConvert.DeserializeObject< NextActivityPerformers >(data.NextActivityPerformers.ToString()); ... } 

复杂的对象types可以是对象,数组和字典。

如果正在使用属性路由,则可以使用[FromUri]和[FromBody]属性。

例:

 [HttpPost()] [Route("api/products/{id:int}")] public HttpResponseMessage AddProduct([FromUri()] int id, [FromBody()] Product product) { // Add product } 

一个简单的参数类可以用来传递一个post中的多个参数:

 public class AddCustomerArgs { public string First { get; set; } public string Last { get; set; } } [HttpPost] public IHttpActionResult AddCustomer(AddCustomerArgs args) { //use args... return Ok(); } 

您可以使用https://github.com/keith5000/MultiPostParameterBinding中的MultiPostParameterBinding类来允许多个POST参数;

要使用它:

1)下载Source文件夹中的代码 ,并将其添加到您的Web API项目或解决scheme中的任何其他项目。

2)在需要支持多个POST参数的动作方法上使用属性[MultiPostParameters]

 [MultiPostParameters] public string DoSomething(CustomType param1, CustomType param2, string param3) { ... } 

3)将Global.asax.cs中的此行添加到调用GlobalConfiguration.Configure(WebApiConfig.Register) 之前的任何位置的Application_Start方法:

 GlobalConfiguration.Configuration.ParameterBindingRules.Insert(0, MultiPostParameterBinding.CreateBindingForMarkedParameters); 

4)让你的客户作为一个对象的属性传递参数。 DoSomething(param1, param2, param3)方法的示例JSON对象是:

 { param1:{ Text:"" }, param2:{ Text:"" }, param3:"" } 

示例JQuery:

 $.ajax({ data: JSON.stringify({ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }), url: '/MyService/DoSomething', contentType: "application/json", method: "POST", processData: false }) .success(function (result) { ... }); 

访问链接了解更多详情。

免责声明:我直接与链接资源相关联。

你的routeTemplate在这种情况下看起来像什么?

你发布这个url:

 /offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/ 

为了这个工作,我期望在你的WebApiConfig这样的路由:

 routeTemplate: {controller}/{offerId}/prices/ 

其他假设是: – 您的控制器被称为OffersController 。 – 在请求主体中传递的JSON对象的types为OfferPriceParameters (不是任何派生types) – 控制器上没有任何其他方法可能会干扰这个方法(如果是这样,请尝试将其注释掉并查看怎么了)

正如菲利普提到,如果你开始接受一些答案,“接受率为0%”可能会使人们认为他们正在浪费时间

很好的问题和意见 – 从这里的答复了解很多:)

作为一个额外的例子,请注意,你也可以混合正文和路线例如

 [RoutePrefix("api/test")] public class MyProtectedController { [Authorize] [Route("id/{id}")] public IEnumerable<object> Post(String id, [FromBody] JObject data) { /* id = "123" data.GetValue("username").ToString() = "user1" data.GetValue("password").ToString() = "pass1" */ } } 

这样调用:

 POST /api/test/id/123 HTTP/1.1 Host: localhost Accept: application/json Content-Type: application/x-www-form-urlencoded Authorization: Bearer xyz Cache-Control: no-cache username=user1&password=pass1 enter code here 

如果你不想去ModelBinding的方式,你可以使用DTO来为你做这个。 例如,在DataLayer中创build一个接受复杂types并从BusinessLayer发送数据的POST操作。 您可以在UI-> API调用的情况下执行此操作。

这里是示例DTO。 指定一名教师给学生,并分配多份文件/受学生的约束。

 public class StudentCurriculumDTO { public StudentTeacherMapping StudentTeacherMapping { get; set; } public List<Paper> Paper { get; set; } } public class StudentTeacherMapping { public Guid StudentID { get; set; } public Guid TeacherId { get; set; } } public class Paper { public Guid PaperID { get; set; } public string Status { get; set; } } 

然后DataLayer中的动作可以被创build为:

 [HttpPost] [ActionName("MyActionName")] public async Task<IHttpActionResult> InternalName(StudentCurriculumDTO studentData) { //Do whatever.... insert the data if nothing else! } 

从BusinessLayer调用它:

 using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", dataof_StudentCurriculumDTO) { //Do whatever.... get response if nothing else! } 

现在,如果我想一次发送多个学生的数据,这仍然可以工作。 像下面一样修改MyAction 。 无需编写[FromBody],WebAPI2默认使用复杂types[FromBody]。

 public async Task<IHttpActionResult> InternalName(List<StudentCurriculumDTO> studentData) 

然后在调用它时传递一个List<StudentCurriculumDTO>的数据。

 using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", List<dataof_StudentCurriculumDTO>)