Question

I've run into a bit of an issue with the iPhone simulator when trying to access a WCF REST service. I've asked the question on the Xamarin forums, but no joy.

Some context:

When testing

  • I can access the service fine from a browser on the dev machine.
  • I can access it fine using a console application going via the PCL.
  • I can access it fine via the app, from a real android device on the WiFi network of the same corporate network.
  • I can access it fine from Safari on the build Mac.
  • I can access it fine from Safari on the iPhone simulator on the build Mac.

The issue is, as soon as I try to access the service via the app on the iPhone simulator, I get a 407, Proxy Access Denied error.

Here is the code I'm using to set up the connection:

private static HttpRequestMessage PrepareRequestMessage(HttpMethod method, string baseUri, 
    string queryParameters, out HttpClient httpClient, string bodyContent)
{
    var finalUri = new Uri(baseUri + queryParameters);

    var handler = new HttpClientHandler();

    httpClient = new HttpClient(handler);  

    var requestMessage = new HttpRequestMessage(method, finalUri);

    if (handler.SupportsTransferEncodingChunked())
    {
        requestMessage.Headers.TransferEncodingChunked = true;
    }

    if (method == HttpMethod.Post || method == HttpMethod.Put)
    {
        requestMessage.Content = 
            new StringContent(bodyContent, Encoding.UTF8, "application/json");
    }

    return requestMessage;
}

That code gives me the 407 error.

I have tried setting the proxy by using various combinations of SupportsProxy and SupportsUseProxy. (Both returning false from the simulator.) I've tried forcing the proxy settings regardless. I've tried setting the credentials on the handler itself. I've tried playing with the UseDefaultCredentials and UseProxy flags. I've also tried setting the IfModifiedSince value in the message header. I've tried using the PortableRest package as well.

All of that only seemed to make things worse. Where I was initially getting the 407 error, the call to httpClient.GetAsync would just immediately return null.

I am at a bit of a loss here, so any help would be greatly appreciated.

PS. For completeness, the rest of the surrounding code that makes the call: (please forgive crappy exception handling, I'm still playing around with the errors)

public static async Task<T> SendRESTMessage<T>(HttpMethod method, string baseUri, 
    string queryParameters, T contentObject)
{
    HttpClient httpClient;

    var payload = string.Empty;
    if (contentObject != null)
    {
        payload = JsonConvert.SerializeObject(contentObject);
    }
    var requestMessage = 
        PrepareRequestMessage(method, baseUri, queryParameters, out httpClient, payload);

    HttpResponseMessage responseMessage = null;
    try
    {
        if (method == HttpMethod.Get)
        {
            responseMessage = await httpClient.GetAsync(requestMessage.RequestUri);                    
        }
        else
        {
            responseMessage = await httpClient.SendAsync(requestMessage);
        }
    }
    catch (HttpRequestException exc)
    {
        var innerException = exc.InnerException as WebException;
        if (innerException != null)
        {
            throw new Exception("Unable to connect to remote server.");
        }
    }

    return await HandleResponse<T>(responseMessage);
}

private static async Task<T> HandleResponse<T>(HttpResponseMessage responseMessage)
{
    if (responseMessage != null)
    {
        if (!responseMessage.IsSuccessStatusCode)
        {                                       
            throw new Exception("Request was unsuccessful");
        }

        var jsonString = await responseMessage.Content.ReadAsStringAsync();
        var responseObject = JsonConvert.DeserializeObject<T>(jsonString);
        return responseObject;
    }                

    return default(T);
}        

This was my attempt at implementing IWebProxy quick and dirty, which I think could have made things worse:

public class MyProxy : IWebProxy
{
    private System.Net.ICredentials creds;        

    public ICredentials Credentials
    {
        get
        {
            return creds;
        }
        set
        {
            creds = value;
        }
    }

    public Uri GetProxy(Uri destination)
    {
        return new Uri("proxy addy here");
    }

    public bool IsBypassed(Uri host)
    {
        return true;
    }
}

Thanks again for taking the time to read my question.

Was it helpful?

Solution

So I finally got it working.

Turns out it was something really stupid, but being new to iOS mobile dev and the fact that the service worked via Safari on the simulator threw me for a loop.

I read that the simulator uses the proxy settings as defined on the Mac. So I went to the network settings and added the service address to the proxy bypass list.

Works like a charm now.

If anybody feels there is a better way to do this, please add your opinions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top