CORS Preview Handling in Asp.net Frontend
I have three applications in my architecture.
They are on the same server but have different port numbers.
A - Token Application (port 4444) - Asp.net WebApi
B - API Application (port 3333) - Asp.net WebApi
C - UI Application (port 2222) - AngularJS App.
Application flow looks like below
1. The UI project gets a token from the Token application (this requires Windows Auth.) Example: awxrsdsaWeffs12da
2- The UI app puts this token in a custom header called "accessToken"
Example: accessToken: awxrsdsaWeffs12da
3-user app sends request to API app Example: http:myaddress:3333/api/TheRestServiceHere
UI app gets 401 error which dispatches OPTIONS method. (I think preliminarily)
In my web api project, I have included Cors as shown below.
public static void Register(HttpConfiguration config)
{
....
//CORS
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
....
}
Configuration
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//CORS
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
json.SerializerSettings.Formatting = Formatting.None;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.Remove(config.Formatters.XmlFormatter);
}
}
So I am looking for a solution to call Application API controllers (B) and get 200 :)
Hello
source to share
I have fixed this in an application I am working on by creating a module that responds to requests that use the OPTIONS verb. You should probably change it a bit to include the verbs and the type of content the app is requesting. In my case, I decided to post everything as JSON (which requires prior validation). The module looks like this:
public class OptionsModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, args) =>
{
var app = (HttpApplication) sender;
if (app.Request.HttpMethod == "OPTIONS")
{
app.Response.StatusCode = 200;
app.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
app.Response.AddHeader("Access-Control-Allow-Origin", APISettings.ApplicationOrigin);
app.Response.AddHeader("Access-Control-Allow-Credentials", "true");
app.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
app.Response.AddHeader("Content-Type", "application/json");
app.Response.End();
}
};
}
public void Dispose()
{
}
}
Then you need to register it in your web.config:
<system.webServer>
<modules>
<add name="HandleOptions" type="namespace.OptionsModule" />
</modules>
</system.webServer>
Another thing you might want to do is specify an explicitly permitted origin. Chrome doesn't like to have a wildcard.
source to share
One of my friends solved the problem using OPTIONSVerbHandler.
When the UI app wants to use the GET method , the browser sends the OPTION to the server first (pre-flight). Then, if the Preflight request is ok, it sends a GET request .
For CORS testing purposes, we used the following code to send the GET method .
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( document ).ready(function() {
var adress = "http://10.10.27.36:3434/backend/api/role";
$.ajaxSetup({
headers: {
'Content-Type': 'application/json',
'accessToken': 'some value',
'Origin' : ''
}
});
$.ajax({
type: "GET",
url: adress,
dataType: "json"
});
});
</script></head><body></body></html>
To handle the OPTION method sent by the browser before the GET, you must have the following settings.
1- Webconfig
<system.webServer>
<handlers>
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" resourceType="Unspecified" requireAccess="None" />
</handlers>
</system.webServer>
2- Adding OPTIONSVerbHandler with the following settings
Restrictions on request
3- Our header settings have an accessToken which is normal as you can see
source to share