locked
System.Net.WebException when sending JSON using POST request to a Jira API RRS feed

  • Question

  • Alright guys, I am very new to Windows Phone development (about a week old) and I have been wrestling with this issue for a day or so with no clear resolution. I will start with the exception:

    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)

    I am attempting to connect to the JIRA rest API for logging in a user. Our JIRA system is currently running 4.4.1, and the API information I am attempting to hit is documented here: https://developer.atlassian.com/static/rest/jira/4.4.1.html. (See the POST request for the "/auth/1/session" API)

    The API calls for a POST request, with a JSON body for the user credentials. I have tried both building the JSON manually, as well as using a JSON library, and the results were the same. The json I am sending is:

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

    I have attempted to change the content type and encoding to anything I can imagine. This includes "text/json", "application/json", adding Encoding.UTF8 to the stream writer, etc. All the results are the same.

    Perhaps the most frustrating part of this entire ordeal, is that I was able to write this in Java for Android in no time at all, so I do not believe it is an API misunderstanding as so much as a Windows Phone 8 and/or C# misunderstanding.

    A few final things to point out:

    • If I change the code to use a GET request, point to "http://www.google.com", and remove the request callback (skipping directly to the response), everything works and I get the result I expect.
    • I am confused by the "BeginX" "EndX" methods for the HttpWebRequest. I understand asynchronous tasks, but just not exactly how C# manages this. Most of the MSDN documentation does not use these, and instead has methods for "GetRequest()" and "GetResponse()" which seem far more straight forward. And most recent examples I have sifted through also use these methods. I am under the assumption that these methods were removed in the Windows Phone 8 SDK to ensure everything that can run asynchronously does.
    • If I hit the JIRA URL directly from any browser except the Windows Phone 8 emulator, I get a valid 403 as outlined by the documentation. However, if I hit the URL directly in the emulator, it prompts me for login credentials. This made me think that basic auth was required, so I have tried adding that but I get the same results.

    Below is the code as I currently have it. I have taken out my Jira host name

    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;
        }
    }
    Thank you all for taking time with this.
    Thursday, January 17, 2013 3:02 PM

All replies

  • Andy's sample and the videos might help you. I found the series on Channel9 very interesting.

    http://code.msdn.microsoft.com/wpapps/Windows-Phone-8-JumpStart-7b3fea2d

    Thursday, January 17, 2013 3:20 PM
  • I will check this code out at some point today, thank you for sharing, I did not see this example before.
    Thursday, January 17, 2013 3:29 PM
  • So a brief update. I have managed to cast the WebException to an HttpWebException and have pulled that actual response code. It is HttpStatusCode.UnsupportedMediaType. This helps me a great deal.
    Thursday, January 17, 2013 6:13 PM
  • I guess you could use Fiddler or similar to proxy the traffic from a working client and see what works.

    Did you get it working? I'd like to see a Jira client :)

    Thursday, January 17, 2013 11:31 PM