在 .NET 和 C#(我来自Java和Spring框架)中,我是一个新手,我发现以下以正确方式调用API的困难。
我将尝试详细解释我的问题。
我有这个API(已定义到部署到IIS中的项目中。请注意,该项目还包含我正在调用的其他API,没有问题)
[HttpPost]
[Route("api/XXX/InviaAlProtocollo/{siglaIDUor}")]
public string InviaAlProtocollo(MailBuffer mailBuffer, string siglaIDUor)
{
..........................................................................
DO SOMETHING
..........................................................................
}
如您所见,它带有2个输入参数:
尝试传递第一个参数时遇到一些问题。
注意:我无法更改此API的代码,因为它是由其他人制作的,并且可能会对其他事物产生影响。
进入另一个部署在其他地方的项目中,我试图以这种方式(从控制器方法)调用以前的API:
[SharePointContextWebAPIFilter]
[HttpGet]
[ActionName("InviaMailAlProtocollo")]
public IHttpActionResult InviaMailAlProtocollo(string siglaIdUor)
{
Console.WriteLine("INTO InviaAlProtocollo()" + siglaIdUor);
// Ignore self signed certificate of the called API:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// Create the byte array[]
UTF8Encoding encoding = new UTF8Encoding();
byte[] mailContent = encoding.GetBytes("TEST");
// Create the MailBuffer object that have to be passed to the API into the request body:
MailBuffer content = new MailBuffer();
content.Nome = "blablabla";
content.Buffer = mailContent;
string jsonRequest = urlBaseProtocolloApi + "/api/XXX/InviaAlProtocollo/ABC123";
// Setting my credentials:
credCache.Add(new Uri(jsonRequest), "NTLM", myCreds);
HttpWebRequest spRequest = (HttpWebRequest)HttpWebRequest.Create(jsonRequest);
spRequest.Credentials = credCache;
spRequest.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0";
spRequest.Method = "POST";
spRequest.Accept = "application/json;odata=verbose";
spRequest.ContentType = "application/json; charset=UTF-8";
// Create and set the stream:
spRequest.ContentLength = mailContent.Length;
Stream newStream = spRequest.GetRequestStream();
newStream.Write(mailContent, 0, mailContent.Length);
newStream.Close();
// Obtain the response from the API:
HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();
string sResult;
JArray jarray;
// Parse the response:
using (StreamReader sr = new StreamReader(endpointResponse.GetResponseStream()))
{
sResult = sr.ReadToEnd();
jarray = JArray.Parse(sResult);
//JObject jobj = JObject.Parse(sResult);
}
Console.WriteLine(jarray);
return Ok(jarray);
}
问题是,当此方法调用我的API时,收到的 MailBuffer mailBuffer 输入参数为 null (我看到它调试了我的API并调用了它)。
我怀疑问题可能与呼叫的此代码段有关:
// Create and set the stream:
spRequest.ContentLength = mailContent.Length;
Stream newStream = spRequest.GetRequestStream();
newStream.Write(mailContent, 0, mailContent.Length);
newStream.Close();
可能是我尝试将错误的内容附加到请求的正文中( byte [] mailContent ,而不是整个 MailBuffer内容对象)。
注意:要执行此呼叫,我必须使用 HttpWebRequest 。
那么,怎么了?我想念什么?如何解决此问题,将整个 MailBuffer内容对象放入正文请求中,并允许我调用的API将其检索为输入参数?
答案 0 :(得分:4)
另一个项目应确保该请求是使用另一个API期望的正确格式的数据发出的。
现在,您只在请求的正文中发送测试电子邮件的原始字节
//...
// Create the byte array[]
UTF8Encoding encoding = new UTF8Encoding();
byte[] mailContent = encoding.GetBytes("TEST");
// Create the MailBuffer object that have to be passed to the API into the request body:
MailBuffer content = new MailBuffer();
content.Nome = "blablabla";
content.Buffer = mailContent;
//...
Stream newStream = spRequest.GetRequestStream();
newStream.Write(mailContent, 0, mailContent.Length); //<---HERE ONLY SENDING encoding.GetBytes("TEST")
另一个端点期望可以反序列化为MailBuffer
的数据
这是应重构以发送正确数据的代码部分
//...
UTF8Encoding encoding = new UTF8Encoding();
// Create the MailBuffer object that have to be passed to the API into the request body:
var content = new MailBuffer() {
Nome = "blablabla",
Buffer = encoding.GetBytes("TEST")
};
//convert model to JSON using Json.Net
var jsonPayload = JsonConvert.SerializeObject(content);
byte[] mailContent = encoding.GetBytes(jsonPayload); //<---CORRECT CONTENT NOW
spRequest.ContentLength = mailContent.Length;
Stream newStream = spRequest.GetRequestStream();
newStream.Write(mailContent, 0, mailContent.Length);
//...
最后,我建议使用HttpClient
的简单API发出请求。但这完全取决于您的喜好。
以下是使用HttpClient
进行相同呼叫的示例
[SharePointContextWebAPIFilter]
[HttpGet]
[ActionName("InviaMailAlProtocollo")]
public async Task<IHttpActionResult> InviaMailAlProtocollo(string siglaIdUor) {
Console.WriteLine("INTO InviaAlProtocollo()" + siglaIdUor);
// Ignore self signed certificate of the called API:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
string requestUri = urlBaseProtocolloApi + "/api/XXX/InviaAlProtocollo/" + siglaIdUor;
// Setting my credentials:
credCache.Add(new Uri(requestUri), "NTLM", myCreds);
var handler = new HttpClientHandler {
UseDefaultCredentials = true,
Credentials = credCache
};
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("UserAgent", "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json;odata=verbose"));
// Create the MailBuffer object that have to be passed to the API into the request body:
var buffer = new MailBuffer() {
Nome = "blablabla",
Buffer = Encoding.UTF8.GetBytes("TEST")
};
//convert model to JSON using Json.Net
var jsonPayload = JsonConvert.SerializeObject(buffer);
var mailContent = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
// Obtain the response from the API:
var response = await client.PostAsync(requestUri, mailContent);
if (response.IsSuccessStatusCode) {
var jarray = await response.Content.ReadAsAsync<JArray>();
Console.WriteLine(jarray);
return Ok(jArray);
}
return BadRequest();
}
答案 1 :(得分:2)
使用[FromBody]参数。
[HttpPost]
[Route("api/XXX/InviaAlProtocollo/{siglaIDUor}")]
public string InviaAlProtocollo([FromBody]MailBuffer mailBuffer, string siglaIDUor)
{
..........................................................................
DO SOMETHING
..........................................................................
}
还尝试将MailBuffer作为JSON对象传递,当您从正文传递时,它将自动转换为MailBuffer对象。
如果这样做不起作用,请在具有相似对象的方法中切换MailBuffer对象,然后将该对象映射到MailBuffer。
答案 2 :(得分:1)
您可以尝试使用HttpClient (using System.Net.Http)
private static readonly HttpClient client = new HttpClient();
// Create the MailBuffer object that have to be passed to the API into the request body:
MailBuffer content = new MailBuffer();
content.Nome = "blablabla";
content.Buffer = mailContent;
var values = new Dictionary<string, object>
{
{ "mailBuffer", content },
{ "siglaIDUor", siglaIdUor }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("/api/XXX/InviaAlProtocollo/ABC123", content);
var responseString = await response.Content.ReadAsStringAsync();