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.