使用POST请求向Jira API发送JSON时出现异常
本文关键字:JSON 异常 发送 API POST 请求 Jira 使用 | 更新日期: 2023-09-27 17:54:07
好了,伙计们,我已经纠结这个问题一天左右了,没有明确的解决方案。我将从例外开始:
The remote server returned an error: NotFound.
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
我正在尝试连接到JIRA rest API以登录用户。我们的JIRA系统目前运行的是4.4.1版本,我试图访问的API信息记录在这里:https://developer.atlassian.com/static/rest/jira/4.4.1.html。(见POST请求的"/auth/1/session" API)
API调用POST请求,使用JSON主体表示用户凭据。我尝试过手动构建JSON,也尝试过使用JSON库,结果是一样的。我发送的json是:
{
"username": "test",
"password": "test"
}
我已经尝试将内容类型和编码更改为我可以想象的任何内容。这包括"text/json","application/json",添加了Encoding。UTF8到流写入器,等等。所有的结果都是一样的
也许这整个考验中最令人沮丧的部分是,我能够在短时间内用Java为Android编写这篇文章,所以我不认为这是API的误解,而是Windows Phone 8和/或c#的误解。
最后几件要指出的事情:
- 如果我改变代码使用GET请求,指向"http://www.google.com",并删除请求回调(直接跳转到响应),一切工作,我得到我期望的结果。
- 我对HttpWebRequest的"BeginX"EndX"方法感到困惑。我理解异步任务,但不太清楚c#是如何管理它的。大多数MSDN文档都没有使用这些方法,而是使用了"GetRequest()"answers"GetResponse()"方法,这些方法看起来更加直接。我筛选的最近的例子也使用了这些方法。我假设这些方法在Windows Phone 8 SDK中被删除,以确保所有可以异步运行的东西都可以。
- 如果我从除Windows Phone 8模拟器以外的任何浏览器直接点击JIRA URL,我会得到一个有效的403,如文档所述。但是,如果我在模拟器中直接点击URL,它会提示我输入登录凭据。这让我认为基本的授权是必需的,所以我试着添加,但我得到相同的结果。
下面是我目前拥有的代码。我已经取出了我的Jira主机名
class LoginService
{
public static UserSession login(string aUsername, string aPassword)
{
String loginUrl = "http://{myjiraurl}/rest/auth/1/session/";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(loginUrl);
string jsonBody = JsonHelper.GenerateLoginJson(aUsername, aPassword);
RequestInformation requestInfo = new RequestInformation();
requestInfo.request = request;
requestInfo.JsonBody = jsonBody;
requestInfo.request.Method = "POST";
requestInfo.request.ContentType = "text/json";
requestInfo.request.ContentLength = (long)jsonBody.Length;
request.BeginGetRequestStream(new AsyncCallback(LoginRequestCallback), requestInfo);
return null;
}
private static void LoginRequestCallback(IAsyncResult result)
{
RequestInformation requestInfo = (RequestInformation)result.AsyncState;
HttpWebRequest webRequest = requestInfo.request;
// End the Asynchronus request.
Stream requestSream = webRequest.EndGetRequestStream(result);
StreamWriter requestWriter = new StreamWriter(requestSream);
requestWriter.Write(requestInfo.JsonBody);
requestWriter.Flush();
requestWriter.Close();
requestSream.Close();
webRequest.BeginGetResponse(new AsyncCallback(LoginResponseCallback), requestInfo);
}
private static void LoginResponseCallback(IAsyncResult result)
{
RequestInformation requestInfo = (RequestInformation)result.AsyncState;
HttpWebRequest webRequest = requestInfo.request;
try
{
HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(result);
if (response.StatusCode == HttpStatusCode.OK)
{
Stream streamResponse = response.GetResponseStream();
string responseResult = StreamHelper.ReadStreamToString(streamResponse);
streamResponse.Close();
}
response.Close();
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
System.Diagnostics.Debug.WriteLine(e.StackTrace);
}
}
}
public class RequestInformation
{
// This class stores the request state of the request and any necessary information for the request body
public HttpWebRequest request;
public string JsonBody { get; set; }
public string Result { get; set; }
public RequestInformation()
{
request = null;
}
}
编辑:为了澄清一些问题,当试图在这一行生成响应对象时,代码失败了…
HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(result);
更新1:我发现我可以将WebException
的响应转换为HttpWebResponse
。这让我看到确切的状态代码是什么,这是HttpStatusCode.UnsupportedMediaType
或415。现在,这直接指向了发送到服务器的JSON编码的问题。
你们可能会认为我是个疯子,但是从下午3点开始,我已经得到了预期的结果。
一旦我稍微重构一下,我会用更新后的代码编辑这个答案。
更新后的工作代码:
public static async Task<HttpWebResponse> SendHttpPostRequest(string url, string content, string contentType, string acceptType)
{
HttpWebRequest request = HttpWebRequest.CreateHttp(new Uri(url, UriKind.Absolute));
HttpWebResponse response = new HttpWebResponse();
string responseText = "";
request.Method = "POST";
request.ContentType = contentType;
request.Accept = acceptType;
Task<Stream> requestTask = Task.Factory.FromAsync(request.BeginGetRequestStream, asyncResult => request.EndGetRequestStream(asyncResult), (object)null);
await requestTask.ContinueWith(t =>
{
using (Stream stream = requestTask.Result)
using (StreamWriter requestWriter = new StreamWriter(stream))
{
requestWriter.Write(content);
}
});
Task<WebResponse> responseTask = Task.Factory.FromAsync(request.BeginGetResponse, asyncResult => request.EndGetResponse(asyncResult), (object)null);
await responseTask.ContinueWith(t =>
{
try
{
response = (HttpWebResponse)responseTask.Result;
}
catch (AggregateException ae)
{
foreach (Exception e in ae.InnerExceptions)
{
if (e is WebException)
{
response = (HttpWebResponse)((WebException)e).Response;
System.Diagnostics.Debug.WriteLine(e.Message);
System.Diagnostics.Debug.WriteLine(e.StackTrace);
}
}
}
});
return response;
}
}