.net WebAPI 多个放置/发布参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14407458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WebAPI Multiple Put/Post parameters
提问by Normand Bedard
I am trying to post multiple parameters on a WebAPI controller. One param is from the URL, and the other from the body. Here is the url:
/offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/
我正在尝试在 WebAPI 控制器上发布多个参数。一个参数来自 URL,另一个来自正文。这是网址:
/offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/
Here is my controller code:
这是我的控制器代码:
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);
}
The content of the body is in JSON:
正文的内容是 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
}]
}
}]
}
}]
}
}
Any idea why the default binding is not able to bind to the offerPriceParametersargument of my controller? It is always set to null. But I am able to recover the data from the body using the DataContractJsonSerializer.
知道为什么默认绑定无法绑定到offerPriceParameters我的控制器的参数吗?它始终设置为空。但是我能够使用DataContractJsonSerializer.
I also try to use the FromBodyattribute of the argument but it does not work either.
我也尝试使用FromBody参数的属性,但它也不起作用。
回答by Fatih GüRDAL
[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 referance
使用参考
using Newtonsoft.Json.Linq;
Use Request for JQuery Ajax
使用 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);
}
});
回答by Rick Strahl
Natively WebAPI doesn't support binding of multiple POST parameters. As Colin points out there are a number of limitations that are outlined in my blog posthe references.
本机 WebAPI 不支持绑定多个 POST 参数。正如 Colin 指出的那样,我在他引用的博客文章中概述了许多限制。
There's a workaround by creating a custom parameter binder. The code to do this is ugly and convoluted, but I've posted code along with a detailed explanation on my blog, ready to be plugged into a project here:
有一种解决方法是创建自定义参数绑定器。执行此操作的代码既丑陋又复杂,但我已经在我的博客上发布了代码以及详细说明,准备插入这里的项目:
回答by Bryan Rayner
If attribute routing is being used, you can use the [FromUri] and [FromBody] attributes.
如果正在使用属性路由,则可以使用 [FromUri] 和 [FromBody] 属性。
Example:
例子:
[HttpPost()]
[Route("api/products/{id:int}")]
public HttpResponseMessage AddProduct([FromUri()] int id, [FromBody()] Product product)
{
// Add product
}
回答by Bes Ley
We passed Json object by HttpPost method, and parse it in dynamic object. it works fine. this is sample code:
我们通过 HttpPost 方法传递 Json 对象,并在动态对象中解析它。它工作正常。这是示例代码:
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());
...
}
The complex object type could be object, array and dictionary.
复杂的对象类型可以是对象、数组和字典。
ajaxPost:
...
Content-Type: application/json,
data: {"AppName":"SamplePrice",
"AppInstanceID":"100",
"ProcessGUID":"072af8c3-482a-4b1c??-890b-685ce2fcc75d",
"UserID":"20",
"UserName":"Hyman",
"NextActivityPerformers":{
"39??c71004-d822-4c15-9ff2-94ca1068d745":[{
"UserID":10,
"UserName":"Smith"
}]
}}
...
回答by Keith
You can allow multiple POST parameters by using the MultiPostParameterBinding class from https://github.com/keith5000/MultiPostParameterBinding
您可以使用https://github.com/keith5000/MultiPostParameterBinding 中的 MultiPostParameterBinding 类来允许多个 POST 参数
To use it:
要使用它:
1) Download the code in the Sourcefolder and add it to your Web API project or any other project in the solution.
1) 下载Source文件夹中的代码并将其添加到您的 Web API 项目或解决方案中的任何其他项目。
2) Use attribute [MultiPostParameters]on the action methods that need to support multiple POST parameters.
2)在需要支持多个 POST 参数的操作方法上使用属性[MultiPostParameters]。
[MultiPostParameters]
public string DoSomething(CustomType param1, CustomType param2, string param3) { ... }
3) Add this line in Global.asax.cs to the Application_Start method anywhere beforethe call to GlobalConfiguration.Configure(WebApiConfig.Register):
3) 将 Global.asax.cs 中的这一行添加到 Application_Start 方法调用GlobalConfiguration.Configure(WebApiConfig.Register)之前的任何位置:
GlobalConfiguration.Configuration.ParameterBindingRules.Insert(0, MultiPostParameterBinding.CreateBindingForMarkedParameters);
4) Have your clients pass the parameters as properties of an object. An example JSON object for the DoSomething(param1, param2, param3)method is:
4)让您的客户将参数作为对象的属性传递。该DoSomething(param1, param2, param3)方法的示例 JSON 对象是:
{ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }
Example JQuery:
示例 JQuery:
$.ajax({
data: JSON.stringify({ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }),
url: '/MyService/DoSomething',
contentType: "application/json", method: "POST", processData: false
})
.success(function (result) { ... });
Visit the linkfor more details.
访问链接了解更多详情。
Disclaimer: I am directly associated with the linked resource.
免责声明:我与链接的资源直接相关。
回答by Greg Gum
A simple parameter class can be used to pass multiple parameters in a post:
一个简单的参数类可用于在帖子中传递多个参数:
public class AddCustomerArgs
{
public string First { get; set; }
public string Last { get; set; }
}
[HttpPost]
public IHttpActionResult AddCustomer(AddCustomerArgs args)
{
//use args...
return Ok();
}
回答by Anthony De Souza
Nice question and comments - learnt much from the replies here :)
很好的问题和评论 - 从这里的回复中学到了很多:)
As an additional example, note that you can also mix body and routes e.g.
再举一个例子,注意你也可以混合 body 和 routes,例如
[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"
*/
}
}
Calling like this:
像这样调用:
POST /api/test/id/123 HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer x.y.z
Cache-Control: no-cache
username=user1&password=pass1
enter code here
回答by sandiejat
If you don't want to go ModelBinding way, you can use DTOs to do this for you. For example, create a POST action in DataLayer which accepts a complex type and send data from the BusinessLayer. You can do it in case of UI->API call.
如果您不想采用 ModelBinding 的方式,您可以使用 DTO 为您完成此操作。例如,在 DataLayer 中创建一个 POST 操作,它接受复杂类型并从 BusinessLayer 发送数据。您可以在 UI->API 调用的情况下执行此操作。
Here are sample DTO. Assign a Teacher to a Student and Assign multiple papers/subject to the Student.
这是示例 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; }
}
Then the action in the DataLayer can be created as:
然后可以将 DataLayer 中的操作创建为:
[HttpPost]
[ActionName("MyActionName")]
public async Task<IHttpActionResult> InternalName(StudentCurriculumDTO studentData)
{
//Do whatever.... insert the data if nothing else!
}
To call it from the BusinessLayer:
从业务层调用它:
using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", dataof_StudentCurriculumDTO)
{
//Do whatever.... get response if nothing else!
}
Now this will still work if I wan to send data of multiple Student at once. Modify the MyActionlike below. No need to write [FromBody], WebAPI2 takes the complex type [FromBody] by default.
现在,如果我想一次发送多个学生的数据,这仍然有效。修改MyAction如下。无需写[FromBody],WebAPI2默认采用复杂类型[FromBody]。
public async Task<IHttpActionResult> InternalName(List<StudentCurriculumDTO> studentData)
and then while calling it, pass a List<StudentCurriculumDTO>of data.
然后在调用它时,传递一个List<StudentCurriculumDTO>数据。
using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", List<dataof_StudentCurriculumDTO>)
回答by Joanna Derks
What does your routeTemplate look like for this case?
在这种情况下,您的 routeTemplate 是什么样的?
You posted this url:
你发布了这个网址:
/offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/
In order for this to work I would expect a routing like this in your WebApiConfig:
为了使其正常工作,我希望在您的WebApiConfig:
routeTemplate: {controller}/{offerId}/prices/
Other assumptions are:
- your controller is called OffersController.
- the JSON object you are passing in the request body is of type OfferPriceParameters(not any derived type)
- you don't have any other methods on the controller that could interfere with this one (if you do, try commenting them out and see what happens)
其他假设是: - 您的控制器名为OffersController。- 您在请求正文中传递的 JSON 对象属于类型OfferPriceParameters(不是任何派生类型)- 控制器上没有任何其他方法可能会干扰此方法(如果有,请尝试将它们注释掉,看看会发生什么发生)
And as Filip mentioned it would help your questions if you started accepting some answers as 'accept rate of 0%' might make people think that they are wasting their time
正如 Filip 提到的,如果你开始接受一些答案,它会对你的问题有所帮助,因为“0% 的接受率”可能会让人们认为他们在浪费时间
回答by Pradip Rupareliya
Request parameters like
请求参数如
Web api Code be like
Web api 代码就像
public class OrderItemDetailsViewModel
{
public Order order { get; set; }
public ItemDetails[] itemDetails { get; set; }
}
public IHttpActionResult Post(OrderItemDetailsViewModel orderInfo)
{
Order ord = orderInfo.order;
var ordDetails = orderInfo.itemDetails;
return Ok();
}


