使用 MVC 从数据主体调用 post API
Posted
技术标签:
【中文标题】使用 MVC 从数据主体调用 post API【英文标题】:Call post API from-data body using MVC 【发布时间】:2020-10-12 08:49:36 【问题描述】:如何使用 MVC 客户端调用在正文消息中使用表单数据的 post API。
API 正文在表单数据中有两个属性,即消息,另一个是附件:
我尝试了一些方法,但由于格式错误而返回错误。这是我的代码:
var client = new HttpClient();
string APIUrl = "https://mynewuploadapi.azurewebsites.net/api/v1/customers/discount";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoxNTkzMzYyMTYwLCJpc3MiOiJQbHVzbWlsZXNBUEkifQ.DC42fI7dmKCTwzXPyrI5vs6Sxp0FMrOgvvr_uECzJ7Q");
client.BaseAddress = new Uri("https://mynewuploadapi.azurewebsites.net/api/v1/customers/discount");
client.Timeout = TimeSpan.FromMilliseconds(1000000);
var converter = new javascriptSerializer().Serialize(model);
var formContent = new FormUrlEncodedContent(new[]
new KeyValuePair<string, string>("message", @converter),
new KeyValuePair<string, string>("attachements", null)
);
var HTTPcontent = new StringContent(@converter, Encoding.UTF8, "multipart/form-data");
var response = await client.PostAsync(APIUrl, HTTPcontent);
它在邮递员上工作,如下图所示:
这是我的控制器上的另一个尝试,它也是返回码:500
#region New Try 26Jun
var newclient = new HttpClient();
newclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoxNTkzMzYyMTYwLCJpc3MiOiJQbHVzbWlsZXNBUEkifQ.DC42fI7dmKCTwzXPyrI5vs6Sxp0FMrOgvvr_uECzJ7Q");
newclient.Timeout = TimeSpan.FromMilliseconds(1000000);
var dict = new Dictionary<string, string>
"message", jsonDeserilizeFromModel,
"attachements", null
;
var values = new FormUrlEncodedContent(dict);
var newresponse = await newclient.PostAsync(APIUrl, values);
newresponse.EnsureSuccessStatusCode();
#endregion
详细邮递员电话如下:
网址 - https://mynewuploadapi. azurewebsites.com/api/v1/customers/discount
标题:
授权:Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoxNTkzNDIzNzg2LCJpc3MiOiJQbHVzbWlsZXNBUEkifQ.MWa-pbYneOUKvO0_dVVXVFENwBrpU3eGWc47j1YpcmQ
身体。方法(表单-发布) 留言:
"tx_type": "Kad Perjalanan",
"applicant_type": "Pekerja/Pelajar",
"reg_type": "Permohonan Baharu",
"ic_type": "NRIC",
"ic_no": "821210-10-1010",
"title": "Encik",
"ic_name": "Ali",
"dob": "1982-12-10",
"gender": "Lelaki / Male",
"mailing_address": "",
"state": "Selangor",
"postcode": "40000",
"city": "Subang",
"email": "ali@plusti.my",
"mobile_no": "01020202020",
"v_make": "Proton",
"v_model": "Saga",
"v_year": "2009",
"v_grant": "12345",
"v_plateno": "BTP2021VC",
"co_name": "PLUSTI",
"co_address": "Tepi PLUSTI Highway",
"co_postcode": "40000",
"co_state": "Selangor",
"co_phone": "0375525251",
"tngcardno": "1234554321",
"tngcard_expiry": null,
"rfidtagno": null,
"v_owner": "Y",
"discount_type":"JPP"
表单后正文示例截图:
有人可以帮我解决这个问题吗?谢谢
【问题讨论】:
你能告诉我们控制器签名和完整的错误信息吗? 响应结果的消息是错误代码500。 邮递员没有发送用户名和密码。标头中的不记名 JWT 令牌。和源代码中的一样 @HoomanBahreini 我只是用控制器上的代码更新我的问题 我要求的是控制器代码(服务器端)而不是客户端... 【参考方案1】:我对此进行了测试,它确实有效:
var client = new HttpClient();
string APIUrl = "https://localhost:44398/api/values/test1";
client.Timeout = TimeSpan.FromMilliseconds(1000000);
var dict = new Dictionary<string, string>
"message", "message" ,
"attachements", null
;
var values = new FormUrlEncodedContent(dict);
var response = await client.PostAsync(APIUrl, values);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
【讨论】:
我刚刚更新了我的问题,附上邮递员成功【参考方案2】:成功了:
using (var response = await Task.Run(() => httpClient.PostAsync(httpClient.BaseAddress, httpContent)))
var bodyString = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
return new HttpResponseResult<T>()
StatusCode = response.StatusCode,
Body = JsonConvert.DeserializeObject<T>(bodyString),
ContentType = response.Content.Headers.ContentType?.MediaType
;
【讨论】:
【参考方案3】:这对我有用
var baseUrl = "https://mynewuploadapi.azurewebsites.net/api/v1/customers/discount";
var token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoxNTkzMzYyMTYwLCJpc3MiOiJQbHVzbWlsZXNBUEkifQ.DC42fI7dmKCTwzXPyrI5vs6Sxp0FMrOgvvr_uECzJ7Q";
using (var httpClient = new HttpClient())
using (var formData = new MultipartFormDataContent())
formData.Add(new JsonContent(message), "message");
formData.Add(new JsonContent(fileContent), "attachements");
httpClient.Timeout = TimeSpan.FromMilliseconds(1000000);
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var response = await httpClient.PostAsync(baseUrl, formData);
if (!response.IsSuccessStatusCode)
//ErrorEventArgs handling here
【讨论】:
【参考方案4】:首先,这是您代码中HttpClient.BaseAddress
的误用。你必须像这样使用它:
string APIUrl = "https://mynewuploadapi.azurewebsites.net/api/v1";
client.BaseAddress = new Uri(APIUrl);
//then call api with the following
var response = await client.PostAsync("/customers/discount", content);
其次,根据target api期望参数发送给他的方式,你应该弄清楚请求结构,这里你不知道它,除非尝试执行一些测试。所以让我们专注于代码的重要部分:
授权
您采用了正确的方式发送授权承载,即:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token");
数据
您第一次尝试序列化然后编码两次使用FormUrlEncodedContent
和StringContent
看起来不寻常。您的第二次尝试在 Dictionary
中使用 jsonDeserilizeFromModel 作为 string
,而这不是合并模型的方法。根据目标 API 中的预期请求表单,您可以使用以下解决方案之一:
解决方案 A(当您可以从 模型 中创建 Dictionary<string, string>
时):
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent file = new StringContent("file to upload as StreamContent");
HttpContent msgItems = new FormUrlEncodedContent(model.ToDictionary());//<string, string>
form.Add(file, "attachements");
form.Add(msgItems, "message");
var response = await client.PostAsync("/customers/discount", form);
解决方案 B 创建一个包含 消息 模型和 附件 的新 model
(例如 unitModel
):
var json = JsonConvert.SerializeObject(unitModel);// or JavaScriptSerializer().Serialize
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/customers/discount", data);
解决方案 C 以 Json 身份发布:
//'unitModel' is a class containing both 'message' & 'attachements'
var result = await client.PostAsJsonAsync("/customers/discount", unitModel);
我们不知道哪一个可以帮助您,因为我们无法重现您的问题。考虑到任何额外的操作,例如编码或绑定请求正文 可能是目标API返回错误的原因.
【讨论】:
以上是关于使用 MVC 从数据主体调用 post API的主要内容,如果未能解决你的问题,请参考以下文章
NodeJ使用请求承诺来调用外部API,从响应主体中保存数据
使用表单主体的 Spring MVC Controller 方法映射
在 POST 数据中从 Api 控制器重定向到 MVC 控制器