veljkoz veljkoz - 1 year ago 53
C# Question

CORS headers missing when deployed on Azure Web App / Azure API

I have created an OWIN hosted

WebAPI 2
. There's also a web app (
AngularJS
) that's using the API and acting as a client.

I've added the necessary code for the
CORS
to the
Startup.cs
, and hosted it in local IIS on a port different than the client and confirmed that it fixes the
Cors
issue.

Then, I deployed both apps to Azure (I've put both on the Azure as Web App, and I also tried putting the OWIN to the Azure API that is currently in preview) but - the preflight request now fails (no
Access-Control-Allow-Origin
present in the response).

Q: Is there some specific of Azure I'm not aware of? How come that OWIN isn't serving this header when deployed but it's working on localhost? I don't see any constraints in the properties window on Azure blades settings for the apps.

Notes:

About some specifics of the setup I'm using:


  • Using
    Owin
    ,
    WebAPI2
    ,
    Ninject
    ,
    SignalR

  • Custom token is issued and provided in headers on each subsequent request, and is verified with a custom filter.

  • Cors I'm attempting for now is
    *



The relevant part of Startup.cs:

public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll);

HttpConfiguration config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

//bind IClientsNotifier with method returning singleton instance of hub
var ninjectKernel = NinjectWebCommon.GetKernel();
ninjectKernel.Bind<MySignalRHub>().ToSelf().InSingletonScope();
ninjectKernel.Bind<QueryStringBearerAuthorizeAttribute>().ToSelf();

GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(ninjectKernel);
appBuilder.Map(
"/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration();
map.RunSignalR(hubConfiguration);
});

config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

config.Formatters.Remove(config.Formatters.XmlFormatter);

config.Filters.Add(new NoCacheHeaderFilter()); //the IE9 fix for cache
var resolver = new NinjectDependencyResolver(NinjectWebCommon.GetKernel());

config.Filters.Add((System.Web.Http.Filters.IFilter)resolver.GetService(typeof(WebApiAuthenticationFilter)));

appBuilder.UseNinjectMiddleware(NinjectWebCommon.GetKernel);
appBuilder.UseNinjectWebApi(config);
}


Additionally, I've commented out the following line from the
web.config
in order to support the
OPTIONS
HTTP request (otherwise, it was throwing HTTP error 405)

<system.webServer>
<handlers>
<!--<remove name="OPTIONSVerbHandler" />-->
...

Answer Source

In the end I went with easier way - removed all code-handling of CORS and simply put the headers in the web.config:

<configuration>
 <system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://my-client-website.azurewebsites.net" />
      <add name="Access-Control-Allow-Methods" value="*" />
      <add name="Access-Control-Allow-Headers" value="accept, content-type, x-my-custom-header" />
      <add name="Access-Control-Allow-Credentials" value="true" />
    </customHeaders>
  </httpProtocol>
 ...

(note that allow-origin doesn't have a slash at the end of the url!)

The allow-credentials part was to satisfy the SignalR, probably it could do without it.

If someone finds a reason as to why the coded way isn't working I'd like to know!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download