Reputation: 555
I have read everything I can find on the subject of ASP.NET Core and CORS and I believe I understand most of it but, I'll be damned if I can get it to work. I'm using the Chrome browser, here is the data:
Prefilght:
General:
Request URL:http://localhost:34376/api/login
Request Method:OPTIONS
Status Code:204 No Content
Remote Address:[::1]:34376
Response Headers:
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:access-control-allow-origin,content-type
Access-Control-Allow-Origin:http://localhost:3000
Date:Wed, 23 Nov 2016 03:05:00 GMT
Server:Kestrel
Vary:Origin
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcbXZjXFNob3BVc1NlcnZpY2Vcc3JjXFNob3BVc1NlcnZpY2VcYXBpXGxvZ2lu?=
Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:access-control-allow-origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:34376
Origin:http://localhost:3000
Referer:http://localhost:3000/authentication
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Post:
Request URL:http://localhost:34376/api/login
Request Method:POST
Status Code:500 Internal Server Error
Remote Address:[::1]:34376
Response Headers:
view source
Content-Length:0
Date:Tue, 22 Nov 2016 03:11:40 GMT
Server:Kestrel
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcbXZjXFNob3BVc1NlcnZpY2Vcc3JjXFNob3BVc1NlcnZpY2VcYXBpXGxvZ2lu?=
Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Access-Control-Allow-Origin:true
Connection:keep-alive
Content-Length:87
Content-Type:application/json
Host:localhost:34376
Origin:http://localhost:3000
Referer:http://localhost:3000/authentication
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Request Payload:
view source
{userName: "", email: "irv@testing.com", password: "!P@ssw0rd", rememberMe: false}
email: "irv@testing.com"
password: "!P@ssw0rd"
rememberMe: false
userName:""
ASP.NET Core code:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => {
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials().Build() );
});
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors("CorsPolicy");
app.UseApplicationInsightsRequestTelemetry();
app.UseApplicationInsightsExceptionTelemetry();
app.UseMvc();
}
ASP.NET Core Controller:
[EnableCors("CorsPolicy")]
[Produces("application/json")]
[Route("api/Authentication")]
public class AuthenticationController : Controller
{
private IUnitOfWork _unitOfWork;
public AuthenticationController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpPost]
[Route("/api/login")]
public JsonResult Login([FromBody]LoginInfo loginInfo)
{
return Json(new { id_token = _unitOfWork.Users.CreateJwt(loginInfo) });
}
Here is the Angular code:
@Injectable()
export class AuthenticationService {
private _currentAdminMode: boolean = false;
constructor(private _http: Http, private _config: ConfigurationService) {
}
public login(logInfo: LoginInfo): Observable<TokenContainer> {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
//return an observable
return this._http.post(this._config.hostPrefix + '/api/login', JSON.stringify(logInfo), { headers: headers })
.map((response) => {
return <TokenContainer>(response.json());
});
}
The exact error that I'm getting in the console of the browser is:
XMLHttpRequest cannot load http://localhost:34376/api/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500.
Notice that I'm getting a 500 error from the POST request. That doesn't seem like the error the server would send if there was a CORS issue. I think it's something else but, all of this code worked in single domain, now that it's CORS something is going haywire. anyway I have read everything I can find and nothing is working. I'm thinking that it might have something to do with the WebAPI route.
Thanks for any help you can give!
Upvotes: 2
Views: 5000
Reputation: 1146
Well, I've spent a day trying to figure out how to handle almost the same problem. I'll try to describe more info:
I use netcoreapp1.0, RESTful services over WebAPI hosted on IIS. Frontend: angular2.
In my Startup.cs:
// this is not much important, you can organize builder in Configure method, calling app.UseCors()
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder.WithOrigins("http://localhost:37885")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("AllowSpecificOrigin");
app.UseMvc();
}
This code worked perfectly when I run it in Visual Studio. But as soon as I published my WebAPI project on IIS I got trouble: preflight request returned Status "Code:204 No Content", while POST and PUT requests returned "405 Method Not Allowed":
It seemed like AllowAnyMethod() did not have any effect when app was hosted on IIS, because only GET, HEAD, OPTIONS, TRACE were allowed as we can see from the picture above.
To test this thing and to remove suspicions from angular and Web API, I created test script and ran it in Chrome developer console:
var xmlHttp = new XMLHttpRequest(); //returns a XMLHttpRequest object
xmlHttp.open('PUT', "http://localhost:27895/api/usergroups/58c624eb54d98519e85c5771", true);
xmlHttp.setRequestHeader('Content-Type', "application/json");
xmlHttp.send(JSON.stringify({"id":"58c624eb54d98519e85c5771","Name":"Группа первооткрывателей"}));
I've got the same issue running this script from my angular client page. Than I ran this script from the same origin WebApi was hosted on (to check webAPI without COR). I've got an error, which told me that PUT method is not Allowed on site!
Finally, I found the solution: the problem was in WebDAV module on IIS, conflicted with my RESTful services. I removed WEBDAV module from my webAPI site On IIS and now it works perfect:
To do this:
Remove WebDAV option from Handler Mappings on IIS for your webApi site as well.
These topics can be useful if you want some more explaination about WEBDAV and Web API conflicts:
As it turned out, WebDav handler and module appears again in IIS after the next publish. So, to prevent site from doing this, modify your web.config of WebAPI application, like this:
<handlers>
<remove name="WebDAV" />
</handlers>
<modules>
<remove name="WebDAVModule" />
</modules>
this topic helped me to figure it out.
Upvotes: 7