MVC 웹 API : 요청 된 자원에 'Access-Control-Allow-Origin'헤더가 없습니다.
이 기사에 쓰여진 모든 것을 시도했습니다 : http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api . angularJS를 사용하여 다른 도메인에서 사용하기 위해 webAPI2 (MVC5)에서 데이터를 가져 오려고합니다.
내 컨트롤러는 다음과 같습니다
namespace tapuzWebAPI.Controllers
{
[EnableCors(origins: "http://local.tapuz.co.il", headers: "*", methods: "*", SupportsCredentials = true)]
[RoutePrefix("api/homepage")]
public class HomePageController : ApiController
{
[HttpGet]
[Route("GetMainItems")]
//[ResponseType(typeof(Product))]
public List<usp_MobileSelectTopSecondaryItemsByCategoryResult> GetMainItems()
{
HomePageDALcs dal = new HomePageDALcs();
//Three product added to display the data
//HomePagePromotedItems.Value.Add(new HomePagePromotedItem.Value.FirstOrDefault((p) => p.ID == id));
List<usp_MobileSelectTopSecondaryItemsByCategoryResult> items = dal.MobileSelectTopSecondaryItemsByCategory(3, 5);
return items;
}
}
}
웹 API 에서 CORS 를 활성화해야합니다 . CORS를 전역 적으로 활성화하는 가장 쉽고 선호되는 방법은 다음을 web.config에 추가하는 것입니다.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
것을 바랍니다 노트 방법은 모두 개별적으로 사용하는 대신, 지정됩니다 *
. 사용시 버그가 발생하기 때문입니다 *
.
코드로 CORS 를 활성화 할 수도 있습니다 .
업데이트
다음 NuGet 패키지가 필요합니다 Microsoft.AspNet.WebApi.Cors
..
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors();
// ...
}
}
그런 다음 [EnableCors]
액션 또는 컨트롤러에서이 속성을 사용할 수 있습니다
[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
또는 전 세계적으로 등록 할 수 있습니다
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("http://www.example.com", "*", "*");
config.EnableCors(cors);
// ...
}
}
또한 Options
요청 으로 프리 플라이트 요청 을 처리해야 HTTP OPTIONS
합니다.
Web API
Options
요청이 실제로 지원되도록 구성되었는지 확인 하려면 요청에 응답해야합니다 CORS
.
이를 처리하려면 빈 응답을 다시 보내면 됩니다. 작업 내에서이 작업을 수행하거나 다음과 같이 전역 적으로 수행 할 수 있습니다.
# Global.asax.cs
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.Flush();
}
}
This extra check was added to ensure that old APIs
that were designed to accept only GET
and POST
requests will not be exploited. Imagine sending a DELETE
request to an API
designed when this verb didn't exist. The outcome is unpredictable and the results might be dangerous.
@Mihai-Andrei Dinculescu's answer is correct, but for the benefit of searchers, there is also a subtle point that can cause this error.
Adding a '/' on the end of your URL will stop EnableCors from working in all instances (e.g. from the homepage).
I.e. This will not work
var cors = new EnableCorsAttribute("http://testing.azurewebsites.net/", "*", "*");
config.EnableCors(cors);
but this will work:
var cors = new EnableCorsAttribute("http://testing.azurewebsites.net", "*", "*");
config.EnableCors(cors);
The effect is the same if using the EnableCors Attribute.
I followed all the steps above indicated by Mihai-Andrei Dinculescu.
But in my case, I needed 1 more step because http OPTIONS was disabled in the Web.Config by the line below.
<remove name="OPTIONSVerbHandler" />
I just removed it from Web.Config (just comment it like below) and Cors works like a charm
<handlers>
<!-- remove name="OPTIONSVerbHandler" / -->
</handlers>
It may be because of the installation of Cors nuget packages.
If you facing the problem after installing and enabaling cors from nuget , then you may try reinstalling web Api.
From the package manager, run Update-Package Microsoft.AspNet.WebApi -reinstall
Try this, to make sure you configured CORS correctly:
[EnableCors(origins: "*", headers: "*", methods: "*")]
Still not working? Check HTTP headers presence.
To make any CORS protocol to work, you need to have a OPTIONS method on every endpoint (or a global filter with this method) that will return those headers :
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: content-type
The reason is that the browser will send first an OPTIONS request to 'test' your server and see the authorizations
@Mihai-Andrei Dinculescu's answer worked for me, e.g.:
- Adding a
<httpProtocol>
in the web.config's<system.webServer>
section - Returning empty response for
OPTIONS
requests via the mentionedApplication_BeginRequest()
inglobal.asax
Except that his check for Request.Headers.AllKeys.Contains("Origin")
did NOT work for me, because the request contained an origing
, so with lowercase. I think my browser (Chrome) sends it like this for CORS requests.
I solved this a bit more generically by using a case insensitive variant of his Contains
check instead: if (culture.CompareInfo.IndexOf(string.Join(",", Request.Headers.AllKeys), "Origin", CompareOptions.IgnoreCase) >= 0) {
I know I'm coming to this very late. However, for anyone who's searching, I thought I'd publish what FINALLY worked for me. I'm not claiming it's the best solution - only that it worked.
Our WebApi service uses the config.EnableCors(corsAttribute) method. However, even with that, it would still fail on the pre-flight requests. @Mihai-Andrei Dinculescu's answer provided the clue for me. First of all, I added his Application_BeginRequest() code to flush the options requests. That STILL didn't work for me. The issue is that WebAPI still wasn't adding any of the expected headers to the OPTIONS request. Flushing it alone didn't work - but it gave me an idea. I added the custom headers that would otherwise be added via the web.config to the response for the OPTIONS request. Here's my code:
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.Headers.Add("Access-Control-Allow-Origin", "https://localhost:44343");
Response.Headers.Add("Access-Control-Allow-Headers",
"Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
Response.Headers.Add("Access-Control-Allow-Credentials", "true");
Response.Flush();
}
}
Obviously, this only applies to the OPTIONS requests. All other verbs are handled by the CORS configuration. If there's a better approach to this, I'm all ears. It feels like a cheat to me and I would prefer if the headers were added automatically, but this is what finally worked and allowed me to move on.
I catch the next case about cors. Maybe it will be useful to somebody. If you add feature 'WebDav Redirector' to your server, PUT and DELETE requests are failed.
So, you will need to remove 'WebDAVModule' from your IIS server:
- "In the IIS modules Configuration, loop up the WebDAVModule, if your web server has it, then remove it".
Or add to your config:
<system.webServer>
<modules>
<remove name="WebDAVModule"/>
</modules>
<handlers>
<remove name="WebDAV" />
...
</handlers>
If you have security\requestFiltering nodes in your web.config as follows:
<security>
<requestFiltering>
<verbs allowUnlisted="false">
<add verb="GET" allowed="true" />
<add verb="POST" allowed="true" />
<add verb="PUT" allowed="true" />
<add verb="DELETE" allowed="true" />
<add verb="DEBUG" allowed="true" />
</verbs>
</requestFiltering>
make sure you add this as well
<add verb="OPTIONS" allowed="true" />
I had tried everything I could find on the net including the methods that have been given on this answer. After almost trying to solve the problem for whole day I have found the solution that have worked for me like a charm.
in the file WebApiConfig in folder App_Start, comment all the lines of code and add the following code:
`public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
var enableCorsAttribute = new EnableCorsAttribute("*",
"Origin, Content-Type, Accept",
"GET, PUT, POST, DELETE, OPTIONS");
config.EnableCors(enableCorsAttribute);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
//routeTemplate: "api/{controller}/{id}",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Add(new BrowserJsonFormatter());
}
public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
public BrowserJsonFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
this.SerializerSettings.Formatting = Formatting.Indented;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}`
'IT story' 카테고리의 다른 글
문자열이 C ++의 숫자인지 확인하는 방법은 무엇입니까? (0) | 2020.07.28 |
---|---|
술어를 사용하여 시퀀스를 두 조각으로 나누는 방법은 무엇입니까? (0) | 2020.07.28 |
내 Git 저장소가 잘못된 루트 디렉토리에 있습니다. (0) | 2020.07.28 |
일부 Git 저장소에서 Git 저장소의 이름을 어떻게 얻습니까? (0) | 2020.07.28 |
파이썬은 여러 변수를 같은 값으로 할당합니까? (0) | 2020.07.28 |