9

I'm trying to make a POST request with CORS.

I've a class that adds the correct response header on my methods inside my controller

using System;
using System.Web.Mvc;

public class AllowCrossSiteAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "*");
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        base.OnActionExecuting(filterContext);
    }
}

and I use it like this

[AllowCrossSite]
public ActionResult GetReportParameters(string IdRapport)

and I get the expected result enter image description here

But the problem is when I'm trying to make a POST request with a custom header to pass this specific content type

'Content-Type': 'application/json; charset=utf-8'

I'm actually getting these Response headers

enter image description here

So it's like nothing is done about the header even if I'm correctly going in my attribute class.

Here is my front side in Angular 2 service

const headers = new Headers({ 'Content-Type': 'application/json; charset=utf-8' });
const options = new RequestOptions({ headers: headers , withCredentials: true });

const mock = {
  name: 'TitreRegroupement1',
  visible: false,
  type: 'System.String',
  value: 'Test'
};

// tslint:disable-next-line:max-line-length
const body = JSON.stringify({ idRapport: '00392024-d171-4f39-9c5c-97a51f53fd54', filtre: '', exportFormat: '', parameters: data });

return this.http.post('http://localhost:8080/ReportingViewer/ExportReport', body, options)
  .map((response: Response) => {
      return this.extractSingleData(response, Parameters);
  })
  .catch(this.handleError);
}

By using postman there is no problem to declare, the whole thing travel correctly I can access my parameters from the method inside the controller with no problem.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Fitch
  • 1,084
  • 1
  • 11
  • 17
  • Do not forget ID is a keyword : {controller}/{action}/{id} client side javascript: $http.get("../controller/action/" + ID).then(function (r) { $scope.item = r.data; }); server side C#.net: public JsonResult action(int ID){...} – zokaee hamid Nov 19 '18 at 17:52

3 Answers3

7

I found how to make it work. First I apply what proposed me sideshowbarker

if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OridinalIgnoreCase) &&
    Request.HttpMethod == "OPTIONS") {
    Response.Flush();
}

and I was missing something in my Headers, I was doing "*" all the way but finally with these parameters it worked

filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

for those who are interested in the final form of my class here it is

using System;
using System.Web;
using System.Web.Mvc;

namespace Via.Client.WebMvc
{
    public class AllowCrossSiteAttribute : System.Web.Mvc.ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {    
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Credentials", "true");

            if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
            {
                filterContext.HttpContext.Response.Flush();
            }

            base.OnActionExecuting(filterContext);
        }
    }
}
Dale K
  • 25,246
  • 15
  • 42
  • 71
Fitch
  • 1,084
  • 1
  • 11
  • 17
  • I'm curious why do you prefer `OnActionExecuting` over `OnActionExecuted` as you won't have to `Flush()` if the latter was chosen .. – Ken Kin Jun 14 '21 at 22:40
4

Your frontend JavaScript code is triggering your browser to do a CORS preflight OPTIONS request.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

You need to change the server-side code to handle that OPTIONS request, by adding, for example:

if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OridinalIgnoreCase) &&
    Request.HttpMethod == "OPTIONS") {
    Response.Flush();
}

Or see https://stackoverflow.com/search?q=%5Basp.net-mvc%5D+%5Bcors%5D+options for many other related answers.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
1

The code that you have tried is all good. This should be work but in your case this is not working.

I have a reference for you about it you have to check it out

Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method

Community
  • 1
  • 1
Manoj
  • 4,951
  • 2
  • 30
  • 56