Ad Hoc iOS Hosting with .NET Core

Working with iOS applications is always somewhat of a chore.  Dealing with mobile provisioning profiles, certificates, the Apple App Store; these all seem like barriers to be over come.

I am currently working on a new mobile application that has .NET Core 2 API that is hosting a download page for new iOS mobile app.  Previous to this I have never worked with .NET Core 2 in a production application so there is always a bit of a learning curve and I wanted to impart my trials and tribulations in this post. 

What do I need?

First of all you will need the following things to be able distribute an application in an Ad Hoc way.

  • Your organization needs to have an Apple Enterprise Developer License
  • Your personal developer account needs to be an administrator.
  • A computer with OS X and XCode
  • A TLS secured website to host the mobile application download page
  • Firewall ports opened to allow port 80 and 443 traffic
  • Allow ITMS traffic through the firewall

Creating the App Package

In XCode after building your mobile application, you need to archive your project with your production distribution provision.  This must be an Enterprise or Ad Hoc certificate and mobile provisions.

You must also check the Over The Air checkbox.  Next, you need to type in the hosing address for the .ipa file and two images.  These don’t have to be perfect as these can be changed later but it’s good to get it as close as possible.

Setting up .NET Core 2 API

To be able to host the .ipa and .plist file extensions, you have to tell .NET Core 2 about their mime-types.  Core 2 apps bypass the mime-types setup in IIS so without setting this up in Core 2.  Any calls to access your .ipa or .plist will return a HTTP 404.  I ran into this issue and it took me over 4 hours to debug.

To setup this up in .NET core, the following code should work for you.

In Startup.cs

// Set up custom content types - associating file extension to MIME type
            var provider = new FileExtensionContentTypeProvider();
            // Add new mappings
            provider.Mappings[".plist"] = "application/xml";
            provider.Mappings[".ipa"] = "application/octet-stream";
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(
		Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")),
                ContentTypeProvider = provider
            });

 

My Core 2 template is an Angular Core 2 template.  To allow users to download your application, you need to put the manifest.plist, the .ipa, and the 2 image files in your wwwroot folder.

Troubleshooting

Okay, so you followed my guide and searched all over StackOverflow and you are still having issues.  Try debugging using these steps

  1. Verify your download page’s anchor tag correctly links to your manifest.plist file. (
    itms-services://?action=download-manifest&url=https://www.example.com/manifest.plist)
  2. Verify that the all of your links are being served/hosted under HTTPS.
  3. Verify that your manifest.plist file correctly links to your app .ipa (https://www.example.com/myapp.ipa)
  4. Verify that your display-image correctly links to your image (https://www.example.com/57×57.png)
  5. Verify that your full-size-image correctly links to your image (https://www.example.com/512×512.png)
  6. Verify that you can hit your .plist and you get the XML file back.
  7. Verify that you can hit your .ipa and download it even if it doesn’t install
  8. Verify that you can hit your images and see them load.

If all of these work individually and your download still doesn’t work then a firewall rule or port is not allowing ITMS to hit your Ad Hoc download

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s