6

I am trying to make the file:

.well-known/apple-developer-merchantid-domain-association

accessible via my Azure website. I have added this to the route config:

routes.MapRoute(
    name: "ApplePay-MacOS",
    url: ".well-known/apple-developer-merchantid-domain-association",
    defaults: new { controller = "Home", action = "WellKnownApplePay" });

Which points to a controller action that gives the file out.

Now everything works when I test it on my local IIS and IIS Express but when I upload it to azure it just isn't accepting the dot "." character in the URL. If I remove it then it works and the file downloads after it has been published to azure. I need it to work with the dot as that is what apple pay requires of my site.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Daniel Haddon
  • 215
  • 3
  • 9

6 Answers6

8

I was able to solve this using a different approach. I stopped trying to write routing for the certificate and added a web.config into the directory per Peter Hahndorf's answer here: IIS: How to serve a file without extension?

<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <system.webServer>
         <staticContent>
             <mimeMap fileExtension="." mimeType="text/xml" />
         </staticContent>
     </system.webServer>
 </configuration>
Community
  • 1
  • 1
Tom Gerken
  • 2,930
  • 3
  • 24
  • 28
  • 1
    Hey Tom, the issue isnt that the file will not be served. If I remove the period and make the URL "well-known/" instead of ".well-known/" then the file is server. So the issue is that adding a period to the .well-known path is causing azure not to serve the file. Not that its missing an extension. – Daniel Haddon Oct 06 '16 at 08:13
  • Glad my answer was able to help! I'm bypassing routing altogether and just leaving it as a file in the file system. So I think I ran into a different set of problems than you. I stumbled across your question while looking for the answer to my own and posted what I admit was not an answer to the question you asked ;) – Tom Gerken Oct 06 '16 at 17:52
5

I found the answer! Thanks to Tom's answer.

You can indeed add the mimemap to the web config to fix the issue. But instead of putting the mimeType="text/xml" you need to use mimeType="application/octet-stream" to serve the raw apple-developer-merchantid-domain-association file and not serve it as text (which the server doesnt want to do).

So the answer is to add this to the system.webserver node in webconfig:

<staticContent>
    <mimeMap fileExtension="." mimeType="application/octet-stream" />
</staticContent>
Daniel Haddon
  • 215
  • 3
  • 9
  • Daniel, since you got this working, could you take a look at my question above and see if you have any suggestions. In your solution are you still using routing or just serving the file from the file system? Thanks, Mike Moore – Mike Moore Apr 09 '20 at 17:45
4

For those who came here trying to create .well-known folder in Azure Web Apps here is my work around that worked:

  1. Use WinSCP to connect to the Azure Web App’s FTP and not FileZilla
  2. Create the directly “.well-known” a. note that the folder will not show up in the FTP client
  3. Select Go To option in WinSCP ( right click on empty space or use toolbar on FTP side) to navigate inside the folder by typing out the path: /site/wwwroot/.well-known
2

As mentioned in the other answers, the issue is the way IIS handles paths with . in them.

I resolved this issue in ASP.NET MVC by writing an IHttpHandler that was registered like so:

<system.webServer>
  <handlers>
    <add name="ApplePayMerchantIdDomainAssociation" path=".well-known/apple-developer-merchantid-domain-association" verb="GET" type="MyNamespace.ApplePayMerchantIdDomainAssociationHandler, MyAssembly" resourceType="Unspecified" preCondition="integratedMode" />
  </handlers>
</system.webServer>

Which was then handled similarly to this:

 using System.Globalization; using System.Web; using System.Web.Mvc;

namespace MyNamespace
{
    public class ApplePayMerchantIdDomainAssociation : IHttpHandler
    {
        public bool IsReusable => true;

        public void ProcessRequest(HttpContext context)
        {
            var wrapper = new HttpContextWrapper(context);
            ProcessRequest(wrapper);
        }

        public void ProcessRequest(HttpContextBase context)
        {
            var type = GetType();
            var assembly = type.Assembly;

            string resourceName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}.apple-developer-merchantid-domain-association",
                type.Namespace);

            using (var stream = assembly.GetManifestResourceStream(resourceName))
            {
                if (stream == null)
                {
                    context.Response.StatusCode = 404;
                }
                else
                {
                    stream.CopyTo(context.Response.OutputStream);

                    context.Response.ContentType = "text/plain";
                    context.Response.StatusCode = 200;
                }
            }
        }
    }
}

In ASP.NET Core things are a lot earier as you can just serve it as static content straight from wwwroot.

Martin Costello
  • 9,672
  • 5
  • 60
  • 72
2
My Problem

I wanted to add a .well-known/something.json file to my Azure App Service (Web App on Linux) for domain validation. However, while I could access the file locally (localhost), I got a 404 File Not Found when I tried to access the file in production.

I found out that the file located in my project under wwwroot/.well-known/something.json was not uploaded during the deployment process to Azure (C# ASP.NET Core, Visual Studio 2019).

My Solution

In my Azure App Service resource I used the Advanced Tools item to access the Kudu container. There, I used the bash console to navigate to my site's wwwroot directory: cd site/wwwroot/wwwroot/. I created the well-known folder mkdir .well-known, navigated inside it cd .well-known and then created my file using vi something.json. After that the file was accessible.

Kolazomai
  • 806
  • 7
  • 6
0

This is .NET 6 solutions inside the middleware, works well for me.

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.Use(async (context, next) =>
        {
            if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith("/.well-known/apple-developer-merchantid-domain-association"))
            {
                var file = $@"{Configuration.GetValue<string>(WebHostDefaults.ContentRootKey)}\wwwroot\well-known\apple-developer-merchantid-domain-association";
                var txt = await File.ReadAllTextAsync(file);
                await context.Response.WriteAsync(txt);

                return;
            }
            
            await next();

        });

You can put the file in any folder, just read it and return the text in the response.

Filix Mogilevsky
  • 727
  • 8
  • 13