HttpClient 传递多个简单参数
Posted
技术标签:
【中文标题】HttpClient 传递多个简单参数【英文标题】:HttpClient pass multiple simple parameters 【发布时间】:2014-10-16 11:46:52 【问题描述】:我正在尝试从一个controller
到另一个controller
执行POST
。两个controller
都来自不同的项目。一个项目用于模拟表示层(我将这里称为测试项目)。
从测试项目中,我尝试将 2 个简单的 string
参数传递给另一个我将调用该过程的控制器。
var values = new List<KeyValuePair<string, string>>();
values.Add(new KeyValuePair<string, string>("id", param.Id.Value));
values.Add(new KeyValuePair<string, string>("type", param.Type.Value));
var content = new FormUrlEncodedContent(values);
using (var client = new HttpClient())
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("nl-NL"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string token = param.token.Value;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = client.PostAsync("/api/Process/Product", content).Result;
if (response.IsSuccessStatusCode)
var result = response.Content.ReadAsStringAsync().Result;
return Request.CreateResponse(HttpStatusCode.OK, result);
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "fail");
在进程控制器中,我试图像这样接收它:
[HttpPost]
public HttpResponseMessage Product(string id, string type)
return null;
但它永远不会到达这个controller
。我总是收到“未找到状态码”。
那么如何使用HttpClient()
传递两个简单的参数?
【问题讨论】:
为什么不使用 GetAsync?意味着将您的动词从 Post 更改为 Get。 因为我只能通过GET
传递1个参数。虽然我尝试了你的解决方案,但没有奏效。进程中没有出现controller
【参考方案1】:
对简单类型参数使用 Get 而不是 Post。
using (var client = new HttpClient())
BaseAddress = new Uri(url);
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("nl-NL"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string token = param.token.Value;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// New code:
var response = await client.GetAsync( string.format("api/products/id=0&type=1",param.Id.Value,param.Id.Type) );
if (response.IsSuccessStatusCode)
var result = response.Content.ReadAsStringAsync().Result;
return Request.CreateResponse(HttpStatusCode.OK, result);
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "fail");
在 API 端你可以这样做。
[HttpGet]
public HttpResponseMessage Product(string id, string type)
return null;
【讨论】:
我需要对属性中的路由做一些事情吗?就像他们在这篇文章中描述的那样:asp.net/web-api/overview/web-api-routing-and-actions/… 是的,你使用属性路由或者你可以更新你的路由配置来适应这个。 或者你可以试试product/id=value&type=value 你最后的评论成功了,请更新你的答案,以便我标记它。 很好的答案@NMK。太疯狂了,它没有内置的构建参数,它们让你自己格式化,但不管怎样,这都是关键!【参考方案2】:接收帖子时,必须在参数中指定 [FromBody] 以调用方法
[HttpPost]
public HttpResponseMessage Product([FromBody]string id, [FromBody]string type)
return null;
【讨论】:
这行不通...您不能拥有多个 [FromBody] 属性 docs.microsoft.com/en-us/aspnet/web-api/overview/…【参考方案3】:我不确定我是否完全爱上了它,但我过去使用匿名类型和动态来处理这个......(注意使用 PostAsJsonAsync() 的配置差异。我最初忘记了这些。)
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.PostAsJsonAsync("api/User/UpdateLastLogin", new UserId = userId, ApplicationId = applicationId );
接收控制器:
[HttpPost]
public void UpdateLastLogin([FromBody]dynamic model)
_userRepository.UpdateLastLogin((int)model.UserId, (int)model.ApplicationId);
在 WebApiConfig.Register() 中:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
我传递的另一种方法是为每个调用创建一组全新的强类型模型。我不想这样做,因为我有很多东西要用于 WebAPI。
【讨论】:
也尝试了您的解决方案,但也没有用。它永远不会在进程controller
中遇到断点。
你在调试这两个应用程序吗?
是的。在进程controller
中带有断点的所有其他方法都会被命中。只是这个没有。 Fiddler 也将 url 标记为红色。但是在检查它时,它没有显示任何可以告诉我问题可能是什么的东西。
如果你还没有听说过,这是一个在调试这种情况下非常有用的工具。 getpostman.com
这样,您应该能够使用两个参数(id、类型)进行发布以验证路由等。但是,您将无法使用两个参数离开该控制器。您将需要使用单个强类型对象或动态对象。【参考方案4】:
这是另一个可用于WinForms
、WPF
或Console
应用的示例
客户端代码
async Task<CalendarView> GetData(int month, int year, int deviceTypeID)
var result = new MSOCommon.CalendarView();
try
HttpClient client = new HttpClient();
var calendarRequest = new CalendarRequest()
Month = month,
Year = year,
DeviceTypeID = deviceTypeID,
UserInfo = Program.UserInfo
;
var url = Properties.Settings.Default.ServerBaseUrl + string.Format("/api/calendar/Calendar");
HttpResponseMessage response = await client.PostAsync(url, calendarRequest.AsJson());
if (response.IsSuccessStatusCode) // Check the response StatusCode
var serSettings = new JsonSerializerSettings()
TypeNameHandling = TypeNameHandling.All
;
string responseBody = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<MSOCommon.CalendarView>(responseBody, serSettings);
else
logger.Error(Properties.Resources.DATACannotGetCalendar);
catch (Exception ex)
logger.Error(Properties.Resources.DATACannotGetCalendar + " " + ex.Message);
logger.Error(ex);
return result;
控制器服务器端代码
[HttpPost()]
public CalendarView Calendar(CalendarRequest calendarRequest)
logger.Info(string.Format("Get calendar for month 0 and year 1 ", calendarRequest.Month, calendarRequest.Year));
// TODO Check username
var result = new CalendarView();
using (var db = new MSOnlineEntities())
result = db.Calendars.Include("CalendarDetails")
.Where(x => x.CMonth == calendarRequest.Month && x.CYear == calendarRequest.Year && x.CDeviceTypeID == calendarRequest.DeviceTypeID).ToList()
.ConvertAll(x => new CalendarView
ID = x.ID,
CMonth = x.CMonth,
CYear = x.CYear,
CDays = x.CDays,
CDeviceTypeID = x.CDeviceTypeID,
ClosedAtTime = x.ClosedAtTime,
ClosedByUser = x.ClosedByUser,
IsClosed = x.IsClosed,
CalendarDetails = x.CalendarDetails.ToList().ConvertAll(d => new CalendarDetailView
ID = d.ID,
CalendarID = d.CalendarID,
MachineID = d.MachineID,
MachineName = d.DATA_MACHINE.Name,
D1 = d.D1 ?? -1,
D2 = d.D2 ?? -1,
D3 = d.D3 ?? -1,
D4 = d.D4 ?? -1,
D5 = d.D5 ?? -1,
D6 = d.D6 ?? -1,
D7 = d.D7 ?? -1,
D8 = d.D8 ?? -1,
D9 = d.D9 ?? -1,
D10 = d.D10 ?? -1,
D11 = d.D11 ?? -1,
D12 = d.D12 ?? -1,
D13 = d.D13 ?? -1,
D14 = d.D14 ?? -1,
D15 = d.D15 ?? -1,
D16 = d.D16 ?? -1,
D17 = d.D17 ?? -1,
D18 = d.D18 ?? -1,
D19 = d.D19 ?? -1,
D20 = d.D20 ?? -1,
D21 = d.D21 ?? -1,
D22 = d.D22 ?? -1,
D23 = d.D23 ?? -1,
D24 = d.D24 ?? -1,
D25 = d.D25 ?? -1,
D26 = d.D26 ?? -1,
D27 = d.D27 ?? -1,
D28 = d.D28 ?? -1,
D29 = d.D29 ?? -1,
D30 = d.D30 ?? -1,
D31 = d.D31 ?? -1
)
).FirstOrDefault();
return result;
【讨论】:
【参考方案5】:在服务器上使用[HttpGet]
而不是[HttpPost]
HttpResponseMessage response =
await client.GetAsync(string.format("api/product?id=0&type=1",param.Id.Value,param.Id.Type);
我的答案和 NMK 接受的答案之间的区别是 ?
而不是 /
这对我有用
【讨论】:
以上是关于HttpClient 传递多个简单参数的主要内容,如果未能解决你的问题,请参考以下文章