Read json from url using IPv6 Xamarin.iOS

I'll try to keep it simple.

I'm trying to consume a rest web api (Hosted on Azure) which is only IPv4 and I'm using the url to do so (since I sent params along in the url). Apple requires that I only utilize IPv6 connections and Azure is only IPv4.

Microsoft's and Xamarin's solutions do not help me at all either:

https://blogs.msdn.microsoft.com/appserviceteam/2016/07/18/azure-mobile-supporting-ipv6-and-the-apple-submission-process/
https://blog.xamarin.com/making-your-ios-apps-ipv6-ready/
How would I be able to read JSON from an url in IPv4 using HttpWebRequest or WebClient?

Here's the basic code I use to read JSON from all my rest api calls:

` // Request JSON from an URL //
public static string getJSON(string url)
{
string strLine = "";

    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);


        request.ServicePoint.BindIPEndPointDelegate = delegate (
        ServicePoint servicePoint,
        IPEndPoint remoteEndPoint,
        int retryCount)
        {

            if (remoteEndPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
                return new IPEndPoint(IPAddress.IPv6Any, 0);
            else 
                return new IPEndPoint(IPAddress.Any, 0);
        };

        request.Method = "GET";
        request.Accept = "application/json";
        request.ContentType = "application/json; charset=utf-8";

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            if (response.StatusCode == HttpStatusCode.OK)
            {
                StreamReader st = new StreamReader(response.GetResponseStream());
                strLine = st.ReadToEnd();
            }
        }
    }
    catch (Exception exe) 
    {
        throw new Exception (string.Format("Error getting JSON from {0} - {1} {2}", url, exe.Message, exe.InnerException));
    }

    return strLine;
}`

Best Answers

Answers

  • It seems, Apple was being kind of picky. Thanks DaveHunt!

  • ChristianHoefleChristianHoefle USUniversity ✭✭

    Hey, how have you been able to solve this problem? We have exactly the same problem, trying to connect from our Xamarin.iOS App to an Azure service, and the App was rejected with the comment that IPv6 connectivity wasn't given.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    @ChristianHoefle - Have you tested your app using the MacOS DNS64/NAT64 internet sharing configuration? If so, what was the result? Are you connecting via an API that uses the hostname or are you using an IP address? Have you read through Avoiding Common Networking Mistakes, specifically Avoid Resolving DNS Names Before Connecting to a Host?

  • I'm currently in the process of setting up my Mac to Test on DNS64/NAT64, althought I'm using the same code I shared and Apple rejected it attaching this screenshot:

    I seriously have no solution so far but I'll keep experimenting.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    The code you shared is attempting to figure out which address type to use. If you're connecting via host name, you shouldn't need to worry about doing any of that. Step one should be testing your code without any IPv4/IPv6 manipulation and see what happens. From there, you can figure out what isn't working and determine what to do about it. You shouldn't start out assuming you'll have a problem. Otherwise, you could just be creating a problem when there was none to begin with.

  • My web api is hosted on Azure. I've found examples on how to get the Hostname from Azure however I haven't been able to find any examples on how to consume a RESTful web api or even use the URL with parameters on a hostname. That's where I'm currently blocked.

    Xamarin says that by utilizing the classes I'm using in the shared code (where I have another simplified code by using WebClient and it's still the same result), I wouldn't need to modify anything. However, If you see the error from the screenshot, it's an end point issue. iOS Device (IPv6) to Azure (IPv4). I need a way to resolve https://apiname.azurewebsites.net/api/Controler?param=ans and consume the rest in an IPv6 manner =/

    From this: http://stackoverflow.com/questions/23207147/programmatically-retrieve-the-site-url-from-inside-an-azure-website/23207697#23207697

    I can get the hostname utilizing Step 2. But now what? =/

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    There is no "consume the rest in an IPv6 manner". The first URL you provided is all you should need. It contains the hostname, so no IP manipulation to deal with.

    You should not need any of that BindIPEndpointDelegate code at all. The underlying HttpWebRequest implementation will have received a synthesized IPv6 address from DNS64, will use that address when making your connection, and the NAT64 will automatically intercept that synthesized IPv6 address and forward it via IPv4 to your Azure server.

  • ChristianHoefleChristianHoefle USUniversity ✭✭

    We tested it with apple's guide on hot wo setup a NAT64/DNS64 environment, and the app worked there.

  • ChristianHoefleChristianHoefle USUniversity ✭✭

    After we resubmitted the app it got rejected again.

    How is it possible that our test via macOS NAT64/DNS64 was successful but Apple still says that the app didn't work in their IPv6 environment?

    @DaveHunt You stated that usually you don't have to care about that as long as your app doesn't have hardcoded IPv4 addresses or uses low-level networking APIs. But it seems that Azure is just not accessible via from IPv6 networks...

  • I'm in the same boat, we resubmitted the app, assuring Apple that it was tested and we're using a website as well, no hard coded IP addresses. Did Apple gave you a screenshot with an error?

  • ChristianHoefleChristianHoefle USUniversity ✭✭

    Sure, they gave us a screenshot were the networking error was shown. We are now doing a video showing apple that it's working with the macOS testing mechanism.

  • If they end up rejecting the application on our end, this is going to be though to resolve, I have no idea.

    In this post: https://blog.xamarin.com/making-your-ios-apps-ipv6-ready/

    Xamarin claims we don't have to do nothing if we use HttpClient, then I don't know if this could be a bug in Xamarin or Apple doing something on their end that's preventing the apps to connect...

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    @ChristianHoefle - Apple is supposed to be testing for IPv6 with DNS64/NAT64 compatibility. That means if you're connecting to an IPv4 server, the NAT64 will translate your synthesized IPv6 back to IPv4 and connect on an IPv4 network. So it shouldn't matter that your server can't handle IPv6 because the app shouldn't be using it.

    I'm beginning to suspect that Apple's testers are doing something wrong, as this seems to be a major issue for native Obj-C apps as well.

  • JoshBailarJoshBailar USUniversity

    We are having the same issue, our App was rejected twice, and they said:

    "We discovered one or more bugs in your app when reviewed on iPad and iPhone running iOS 9.3.4 on Wi-Fi connected to an IPv6 network. Specifically, your app still states that there is no internet connection on launch".

    We followed the test specified on Apple article about testing on IPv6 with DNS64/NAT64 compatibility, even using a IPv6 proxy, and our app works well. We can't reproduce the issue.

    Our Api is hosted in Azure, and we are using the Azure Mobile SDK to consume it. Additionally, we are using Xamarin.Forms to build the UI.

    Any Ideas how to solve and pass the Apple revision?

  • ChristianHoefleChristianHoefle USUniversity ✭✭

    @JoshBailar Our app was now rejected the third time. What kind of IPv6 Proxy did you use? Our next try would be using Cloudflare as IPv4 <-> IPv6 Gateway, because I have no idea what else could solve the issue.

    We are using Xamarin with native UIs (iOS, Android, UWP) and MvvmCross, but no low-level APIs, no Reachability-stuff and no hardcoded IPv4 IPs. Networking-wise we use HttpClient.

  • MohammadZekrallahMohammadZekrallah SAMember ✭✭

    Our app is rejected for the third time for the same reason .. please guys help .. what the hell should we do ??!

  • JoshBailarJoshBailar USUniversity

    @ChristianHoefle We tried with this service http://ipv6proxies.com/ in our iOS devices, and our app worked well. The weird thing is that we have another similar app practically shares the same core to access our API, and this was approved, but the other was rejected twice. We are using Azure Mobile SDK to consume our API. The worst thing is that we can't reproduce the issue.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    Question to all - are you using the default HTTP client stack? Have you tried switching to the CFNetwork stack? CFNetwork is supposed to handle this stuff for you, so that might be the way to go.

  • PhilSeemanPhilSeeman USMember ✭✭

    We're having the exact same problem as others - app works fine using Apple's documented local IPv6 test environment but got rejected.

    @DaveHunt We're using Xamarin Forms in Visual Studio - any idea how to set the HTTP stack to the CFNetwork one? There's no option to do so on the Build dialog like there is shown for Xamarin iOS.

  • PhilSeemanPhilSeeman USMember ✭✭
    edited August 2016

    Regarding the question I asked above about using CFNetwork from Xamarin.Forms: while I haven't tried it yet (will do that shortly), I found this answer.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    @PhilSeeman - Fingers crossed!

  • @DaveHunt said:
    Question to all - are you using the default HTTP client stack? Have you tried switching to the CFNetwork stack? CFNetwork is supposed to handle this stuff for you, so that might be the way to go.

    Yes, I'm using it, however I'm only using Xamarin.iOS/Mono iOS. I'm not utilizing Xamarin.Forms. App got rejected again after some tests... Just need to figure out how to implement CFNetwork on Xamarin.iOS

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    Although the linked document is in the Cross-Platform Development section, it's not specific to Xamarin.Forms.

    If you're using Visual Studio and Xamarin.iOS, you can specify the handler with extra mtouch arguments in the iOS Build settings. See HttpClient. You can also set it programmatically. See Programmatically Setting the HttpMessageHandler.

    As far as I know, that only affects instances of HttpClient.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    @PhilSeeman - Excellent! Glad you got it sorted out. And kudos for posting your solution!

  • Marked @PhilSeeman Azure Mobile Service as an answer as well for those having issues with that service.

    In the meantime, I tried @DaveHunt suggestion w/ this: https://developer.xamarin.com/guides/cross-platform/transport-layer-security/#Programmatically_Setting_the_HttpMessageHandler So I'm setting up CFNetworkHandler as default and using WebRequests to perform my url JSON Azure Web API consumption instead of HttpWebRequest (since it's not mentioned here).

    So now to see if Apple Approves the app...

  • JoshBailarJoshBailar USUniversity

    Hello everyone, finally our app was approved. We are not sure what fixed the issue running our app over an IPv6 network because we could not reproduce it, but we updated our Azure Mobile Client SDK to the latest version, and we started using the ModernHttpClient (https://www.nuget.org/packages/modernhttpclient/) to use it as HttpClient handler.

  • PhilSeemanPhilSeeman USMember ✭✭

    I'm no longer sure that my solution, marked as the answer here for Azure Mobile Services apps, is correct: after having our app accepted by the App Store, I then submitted a basically identical build to TestFlight and it's been rejected twice.

    So I'm now going to try the two changes @JoshBailar posted just above, and see what happens. Will provide an update when I have one.

  • PhilSeemanPhilSeeman USMember ✭✭
    edited September 2016

    @JoshBailar What version of the Azure Mobile Client SDK did you update to? I'm trying to update to 2.1.1 but when I do, that leads to an error of missing member Array.Empty, which seems to be caused because my app is targeting .NET Framework 4.5 and it seems Array.Empty was added in .NET 4.6.

    But when I try to switch my app to 4.6, VS changes it back to 4.5.1 with the message The following will be automatically targeted because they support the same set of portable APIs: .NET Framework 4.5.1. I'm unsure how to resolve that issue and move to .NET 4.6 - unless perhaps you only updated to a lesser version of the Azure Mobile Client? Or were you able to update to .NET 4.6 and if so, how?

  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    @PhilSeeman

    Just a note - Array.Empty is new for .NET 4.6, but it's not available in a PCL, so can't be used there anyway.

    VS is telling you that the same set of portable (e.g. in a PCL) APIs are supported in 4.5.1 and 4.6. In other words, none of the new stuff in 4.6 works in a PCL.

  • PhilSeemanPhilSeeman USMember ✭✭

    Very interesting, @DaveHunt, thanks for that info. Do you know if it's not yet supported in a PCL because it's new, or if it's one of those things that just won't be available in a PCL?

    Seems like kind of a significant issue for Azure Mobile apps since it means the latest Azure Mobile Client 2.1.1 can't be used in a PCL solution.

  • DaveHuntDaveHunt USMember ✭✭✭✭✭
    edited September 2016

    @PhilSeeman - All I know is the Version Information listed on the page for Array.Empty. It only shows UWP and .NET 4.6, no Portable Class Library. Unlike, say Array.Exists, which does list Portable Class Library.

Sign In or Register to comment.