使用POST请求将JSON发送到Jira API时的System.Net.WebException

好吧,伙计们,我已经在这个问题上挣扎了一天左右,没有明确的解决方案。 我将从例外开始:

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 。 (请参阅“/ auth / 1 / session”API的POST请求)

API调用POST请求,其中包含用户凭据的JSON正文。 我已尝试手动构建JSON,以及使用JSON库,结果是相同的。 我发送的json是:

 { "username": "test", "password": "test" } 

我试图将内容类型和编码更改为我能想象的任何内容。 这包括“text / json”,“application / json”,将Encoding.UTF8添加到流编写器等。所有结果都是相同的。

也许这整个考验中最令人沮丧的部分是,我能够立刻用Java for Android编写这个,所以我不认为这是一个API误解,就像Windows Phone 8和/或C#一样误解。

最后要指出的几点:

  • 如果我更改代码以使用GET请求,请指向“http://www.google.com”,并删除请求回调(直接跳到响应),一切正常,我得到了我期望的结果。
  • 我对HttpWebRequest的“BeginX”“EndX”方法感到困惑。 我理解异步任务,但不完全是C#如何管理它。 大多数MSDN文档都不使用这些文档,而是使用“GetRequest()”和“GetResponse()”的方法,这些方法看起来更直接。 我筛选过的最新例子也使用了这些方法。 我假设这些方法已在Windows Phone 8 SDK中删除,以确保可以异步运行的所有内容。
  • 如果我直接从除Wi​​ndows Phone 8模拟器之外的任何浏览器点击JIRA URL,我会得到文档中概述的有效403。 但是,如果我直接在模拟器中点击URL,它会提示我输入登录凭据。 这让我觉得需要基本身份validation,所以我尝试添加,但我得到了相同的结果。

下面是我目前拥有的代码。 我已经取出了我的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 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 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 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; } }