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":{ "39c71004-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>)