2

In interface of IApplicationService I have decorated one of my method as [HttpOptions]

When I do ajax from another domain, the method will be fired from the server side but I have got the below exception in Client-Side:

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

As This link described how to enable CORS in MVC core or WebApi in ASPNetBoilerplate but I have neither app.UseCors("AllowAll") nor services.AddMvc(); in ASP.Net MVC with ABP.

I am using https://aspnetboilerplate.com/.

Is there a way to enable it in ABP ?

Sample:

abp.services.fep.user.ping().done(function (data) {
                console.log(data);
            });

but the result:

General
 Request URL:http://xxxx/wado1/api/services/fep/user/Ping
 Request Method:OPTIONS
 Status Code:200 OK
 Remote Address:192.168.16.201:80
 Referrer Policy:no-referrer-when-downgrade
Response Headers:
 Access-Control-Allow-Origin:*
 Cache-Control:private
 Content-Length:129
 Content-Type:application/json; charset=utf-8
 Date:Mon, 12 Feb 2018 10:06:41 GMT
 Server:Microsoft-IIS/10.0
 Set-Cookie:Abp.Localization.CultureName=en-US; expires=Tue, 12-Feb-2019 
 10:06:33 GMT; path=/WADO1
 Set-Cookie:.ASPXANONYMOUS=jE6RBHsyANH3AuPkKFlnusuKGyqfdikCJ5cJSo38xg-
 pCqe8JnUOX3t0o2V6s0_aT3N0PLnw2XG9PRzCPIse3uLC60vS8l-
 3H8Z_UP1lqCIyDunM9oxhxqKJOca1B4Nv5eQwaQ2; expires=Sun, 22-Apr-2018 20:46:33 
 GMT; path=/; HttpOnly
 X-AspNet-Version:4.0.30319
 X-Powered-By:ASP.NET
 X-StackifyID:V1|80000cf1-0001-f700-b63f-84710c7967bb|
Request Headers
 Accept:*/*
 Accept-Encoding:gzip, deflate
 Accept-Language:en-US,en;q=0.9
 Access-Control-Request-Headers:content-type
 Access-Control-Request-Method:POST
 Cache-Control:no-cache
 Connection:keep-alive
 Host:xxxx
 Origin:http://localhost
 Pragma:no-cache
 User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, 
 like Gecko) Chrome/64.0.3282.140 Safari/537.36

When I create a new template from https://aspnetboilerplate.com with ASP.Net Core frame work I can see something like below in Startup file:

// Configure CORS for angular2 UI
services.AddCors(
    options => options.AddPolicy(
        _defaultCorsPolicyName,
        builder => builder
            .WithOrigins(
                // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                _appConfiguration["App:CorsOrigins"]
                    .Split(",", StringSplitOptions.RemoveEmptyEntries)
                    .Select(o => o.RemovePostFix("/"))
                    .ToArray()
            )
            .AllowAnyHeader()
            .AllowAnyMethod()
    )
);

UPDATE1: I add the below webapi config to enable CORS:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    { 
        config.EnableCors();  
    }
}

and register it :

public override void Initialize()
{ 
    WebApiConfig.Register(GlobalConfiguration.Configuration);
}

but in client-side I got Error 500, after enabling Failed Request Tracing, I see the log trace and buffer error like:

{"message":"An error has occurred.","exceptionMessage":"There is an action Ping defined for api controller fep/user but with a different HTTP Verb. Request verb is POST. It should be Options","exceptionType":"Abp.AbpException","stackTrace":" at Abp.WebApi.Controllers.Dynamic.Selectors.AbpApiControllerActionSelector.GetActionDescriptorByActionName(HttpControllerContext controllerContext, DynamicApiControllerInfo controllerInfo, String actionName)\r\n at Abp.WebApi.Controllers.Dynamic.Selectors.AbpApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.Cors.AttributeBasedPolicyProviderFactory.SelectAction(HttpRequestMessage request, IHttpRouteData routeData, HttpConfiguration config)\r\n at System.Web.Http.Cors.AttributeBasedPolicyProviderFactory.GetCorsPolicyProvider(HttpRequestMessage request)\r\n at System.Web.Http.Cors.CorsMessageHandler.d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Cors.CorsMessageHandler.d__b.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Cors.CorsMessageHandler.d__0.MoveNext()"}

UPDATE2:

I enabled CORS by :

var cors = new EnableCorsAttribute(
                origins: "*",
                headers: "*",
                methods: "*");
config.EnableCors(cors);

and register it in application_start but by this ajax with contentType:application/x-www-form-urlencoded" as @AlperEbicoglu posted in his answer method get fired in Back-End but entered DTO be null because it is JSON...

Abp set contentType to application/json automatically in abp.jquery.js file, for this reason(application/json) when I want run below code:

 abp.services.fep.user.authenticate(box_in).done(function (data) {
                console.log(data);
            }); 

I got that mentioned exception in UPDATE1 section.

Why it can be called with application/x-www-form-urlencoded but with application/json exception raised (I see this in XML Tacer file in IIS).

I think 1 step remained two resolve this, any help would be truly appreciated.

Thanks in advance.

Community
  • 1
  • 1
Aria
  • 3,724
  • 1
  • 20
  • 51
  • ASP.NET Core or MVC5? Pretty sure you should decorate the concrete class instead of interface. – aaron Feb 12 '18 at 12:22
  • @aaron, ASP.Net MVC5, as Boilerplate site mentioned here to put, `[HttpOptions]` over method in interface or main class, I think this is not work, something like configure it to enable CORS... – Aria Feb 12 '18 at 12:39
  • Any server-side error? – aaron Feb 12 '18 at 13:08
  • @aaron, No, I have one method named `Ping()` just return a string , I set breakpoint in server-side , the method get fired nicely, but in the client-side I got that mentioned error, Do you think so I have to change my framework to ASP.Net Core.x? – Aria Feb 12 '18 at 13:24
  • No. Try this: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors – aaron Feb 12 '18 at 13:33
  • Thanks I read them before, but I am in doubt about how it can be used, 1- That is WebApi but mine is MVC 5 , 2- That is decorated ASP.Net Controller not ABP application services methods how it can be used with ABP? – Aria Feb 12 '18 at 13:38
  • Well, try it :) – aaron Feb 12 '18 at 14:08
  • Have you upgraded your project or downloaded this version only – Vivek Nuna Feb 12 '18 at 16:24
  • @viveknuna, I didn't upgrade I just Download that template to know more details and see that code, – Aria Feb 12 '18 at 16:28
  • Try to Run UI in incognito mode – Vivek Nuna Feb 12 '18 at 16:29

2 Answers2

0

updated my answer.... You already succeeded in enabling CORS. Now you have a problem with preflight requests. I think you need to decorate your method as POST verb. Browser automatically sends preflight request if it needs.

and if you insist on making it OPTIONS. so you need to execute it with custom ajax like you can use JQuery ajax.

something like this:

$.ajax({
  url: .....,
  type: 'OPTIONS',
  contentType: "application/x-www-form-urlencoded",
  data: .......,
  success: function (data, status) {
    console.log("Success!!");
    console.log(data);
    console.log(status);
  },
  error: function (xhr, desc, err) {
    console.log(xhr);
    console.log("Desc: " + desc + "\nErr:" + err);
  }
});

pls read this: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Alper Ebicoglu
  • 8,884
  • 1
  • 49
  • 55
  • Thanks, But doesn't work, I also get that exception. – Aria Feb 12 '18 at 16:17
  • @ismcagdas, I have decided to change my `ApplicationServices` to `AbpApiController` but how it be configured to generate proxy for all controllers? – Aria Feb 14 '18 at 07:08
  • @AlperEbicoglu, I am close for resolving, you know by doing `ajax` manually and set `type` to post, method get fired and succeeded callback, but when calling `abp.services.fep.user.ping()` that preflight error occurred again. – Aria Feb 14 '18 at 12:26
  • When I set `contentType` to `application/x-www-form-urlencoded` , ajax done but but entered DTO will be null, because it is JSON, in the other side with `application/json` method internal error 500 occurred. – Aria Feb 14 '18 at 14:16
  • It sets as application/json because ApplicationService methods send JSON. If you are using AbpApiController, it inherits from ApiController. Basically you can change the content-type of ApiController. See https://stackoverflow.com/a/23381647/1767482 – Alper Ebicoglu Feb 15 '18 at 07:14
0

Last time i had a similar requirement with abp i have addressed it with custom attribute instead of enablecors method like below:

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext filterContext)
    {
        if (filterContext.Response != null)
            if (filterContext.Response.Headers != null)
                filterContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        base.OnActionExecuted(filterContext);
    }
}

and then in WebApiModule:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
            .ForAll<IApplicationService>(typeof(WebsiteApplicationModule).Assembly, "api")
            .WithConventionalVerbs()
            .WithFilters(new AllowCrossSiteJsonAttribute())
            .Build();

if you still getting error regarding Access-Control-Allow-Headers try to add it also in response headers

based on this thread: Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method