I'm building a .Net Web Api that will be consumed by Angular 6 client but for any reason I'm not being able to make it to work in my development environment.
I started with an extremely simple Web Api that just does nothing but returns a string (with communication between frontend and backend testing purposes):
// GET: api/Login
public IEnumerable<string> Get()
{
return new string[] { "Now it works!" };
}
// POST: api/Login
public void Post([FromBody]string value)
{
string strTest = "I'm doing just nothing";
}
and then in my Angular 6 app I have a method with the following post request:
return this.http.post<any>(`http://localhost:9810/api/Login`, { username, password })
.pipe(map(user => {
// login successful if there's a jwt token in the response
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user;
}));
In my first attempts all my responses were failing with response:
zone.js:2969 OPTIONS http://localhost:9810/api/Login 405 (Method Not Allowed)
login:1 Failed to load http://localhost:9810/api/Login : Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost:4200 ' is therefore not allowed access.
So I after investigating I've added CORS support to my WebApi .Net project the next way:
1) Installed Nuget packages:
Microsoft.AspNet.WebApi.Cors
Microsoft.AspNet.Cors
2) In WebApiConfig Register method:
var cors = new EnableCorsAttribute("http://localhost:4200", "*", "*");
// or var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
3) Alternatively to 2) in Api controller class header:
[EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]
But none seems to work, the request always fails with the same error as described above in browser console.
I tried creating a self hosting WebApi listening http calls on http://localhost:9000 as well as my last attempt that was publishing the WebApi in my local Windows 10 IIS server with 9810 port.
If I access the url in browser like so " http://localhost/api/Login " then the string is returned like so:
<ArrayOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<string>Now it works!</string>
</ArrayOfstring>
and no error is displayed in console but as long as I try to make the request by Angular (default port 4200) the request fails with CORS error.
I'm stuck. If I cannot make it to work from Angular I won't be able to do debugging and testing.
Thanks.
Edit 1: Chrome network tab info added.
General:
Request URL: http://localhost:9000/api/Login
Request Method: OPTIONS
Status Code: 405 Method Not Allowed
Remote Address: [::1]:9000
Referrer Policy: no-referrer-when-downgrade
Response Headers:
Allow: GET,POST
Content-Length: 76
Content-Type: application/json; charset=utf-8
Date: Wed, 29 Aug 2018 10:32:36 GMT
Server: Microsoft-HTTPAPI/2.0
Request Headers:
Accept: /
Accept-Encoding: gzip, deflate, br
Accept-Language: es-ES,es;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:9000
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
After struggling my head the whole morning and trying everything each one of you suggested here I cannot believe in the end my problem could have been resolved so easily.
Regarding @Madpop suggestion Application_BeginRequest (for any reason) was never being fired (dind't want to spend much time investigating why).
@Steveland solution involved adding dependency injection and it resulted a little bit complicated to me (I don't have much experience with that) aparte from the fact I'm not using Asp.Net Core but Asp.Net framework 4.6.
I was looking for a simple solution to a problem I thought it should have been easy to solve and the key was appending
[HttpPost]
[HttpOptions] //this was the key
[Authorize]
to Post method header. This was the only way for me to allow "Options" verb in request.
I don't know if this is the best way to accomplish this but for now it works (let me know what d'you think guys).
I appreciate ev'ry help I've received here from everybody and say thanks and as I'm not an expert on this subject (Angular + Web Api) I would like to finally ask the next:
Will I have to put this [HttpOptions] also for production when the api will be deployed to server or this is just needed for now for debugging and testing locally purposes?
Edit 1:
After testing I've noticed it works with self hosting Web Api but as I publish Web Api to my local IIS I get "415 Unsupported Media Type" in browser :(
Regarding the cors issue i also faced the similar issue i have created a global.asax file that i have place the below code
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://staging.example.com:8044");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Accepts, Content-Type, Origin, X-My-Header");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "60");
HttpContext.Current.Response.End();
}
}
it worked for me in angular 6 as well in ionic 3 also and before all these try to install https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
the above chrome plugin and activate it and then try to run the application
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.