Home > Net >  Why is CORS Error Returned When Passing Encoded Data
Why is CORS Error Returned When Passing Encoded Data

Time:02-01

I'm forced to work with poor data quality. One instance is that primary key value of a given table can contain spaces and special characters, e.g. 35581/H0034-100003

What I'm trying to do is get a record by it's primary key value, so the web API I setup is a GET:

[HttpGet]
[Route("Api/SaleHeaders/{saleNumberEncoded}")]
public SaleHdrViewModel GetSaleHeader(string saleNumberEncoded)
{
    var saleNumber = HttpUtility.UrlDecode(saleNumberEncoded);
    return _saleHeaderService.Get(saleNumber);
}

Then when I go to send the value from the front-end, I use:

getSaleHeader(saleNumber: string): Observable<ISaleHeader> {
    saleNumber = encodeURIComponent(saleNumber);
    const url = `${environment.ApiUrl}/Api/SaleHeaders/${saleNumber}`;
    return this.http.get<ISaleHeader>(url);
}

The issue is that the request is failing, specifically due to a CORS error:

Access to XMLHttpRequest at 'localhost:52864/Api/SaleHeaders/ 35581/H0033-100000' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I don't think that this is actually a CORS error. I think this actually has to do with CORS because if I edit and resend with the Access-Control-Allow-Origin: * header, it returns a 404. I think this has to do with trying to send encoded primary key value.

I know that I can change my request type from a GET to a POST and then just pass the primary key value in the body, but I'd prefer to keep getting records in a consistent manner (GET request with Api/{table}/{pk} route).

Edit - I've verified that if I pass an unencoded value (e.g. 00007931) then the endpoint works fine.

CodePudding user response:

You cannot use character / as a route parameter because it will be readed as a different resource access. I recommend you to use another pattern to encode your data and avoid missunderstanding the information. Otherwise you could pass the data as a query parameter using:

http://testweb.z/route?userdata=123/321

Also you can change your method signature to: (that's the way I recommend to you)

[HttpGet]
[Route("Api/SaleHeaders/{table}/{pk}")]
public SaleHdrViewModel GetSaleHeader(string table, string pk)

CodePudding user response:

I followed Jorge Machado's advice that was posted in the comment section of encoding the value to Base64 and then decoding it on the server.

Angular:

getSaleHeader(saleNumber: string): Observable<ISaleHeader> {
    saleNumber = btoa(saleNumber);
    const url = `${environment.ApiUrl}/Api/SaleHeaders/${saleNumber}`;
    return this.http.get<ISaleHeader>(url);
}

C#:

[HttpGet]
[Route("Api/SaleHeaders/{saleNumberEncoded}")]
public SaleHdrViewModel GetSaleHeader(string saleNumberEncoded)
{
    var bytes = System.Convert.FromBase64String(saleNumberEncoded);
    var saleNumber = System.Text.Encoding.UTF8.GetString(bytes);

    return _saleHeaderService.Get(saleNumber);
}

This allows me to keep with my existing pattern of having a GET endpoint where the route follows the following pattern: Api/{table name}/{primary key value}

  •  Tags:  
  • Related