1

I have a Core 2.2 Web API project as my back-end for an Angular front-end. On one screen I allow the user to select x amount of records for processing from a data grid. Before the records can be processed I need to check the database to see if records exist in another table by passing a list of 3 fields (intelligent key) to my API. I put this list into an object array, do a Json.stringify on that object and send it to my API as a Get request. This works fine as long as I select 1-3 records. As soon as I select 4 or more records I get "Access to XMLHttpRequest at 'request url' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

My Cors policy indicates it should let anything through and I'm also confused by why 1-3 records works fine.

In my startup.cs -> ConfigureServices method I have the Cors policy defined like so:

services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.WithOrigins("http://localhost:4200")
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials());
            });

In my Angular service I make this call which serializes by array (apiUrl is my url to call my API: https://localhost/api/controller)

getRecordsByIntelligentKey(intelligentKey: IntelligentKey[]): Observable<Record[]>{
    const jsonObject = JSON.stringify(intelligentKey);
    const url = `${apiUrl}/${jsonObject}`;

    return this.http.get<Record[]>(url).pipe(
        tap(_ => console.log('fetching records based on intelligent key')),
        catchError(this.handleError('getRecordsByIntelligentKey', []))
    );
}

In my controller GET action I deserialize my string. I mean I'd like to pass an object but I think I need to do a POST for that.

[HttpGet("{jsonObject}")]
public ActionResult<List<Commission>> GetByCustomerAndTerritoryManager(string jsonObject)
{
    try
    {
        var intelligentKey = JsonConvert
            .DeserializeObject<List<ThreeFields>>(jsonObject);
        return _repo.GetRecordsByIntelligentKey(intelligentKey);
    }
    catch (Exception ex)
    {
        _logger.Error(ex, "Error retrieving records.");
        throw;
    }
}

Now my problem is the user could select 1000s of records. When I select over 1000 records I just get ERR_CONNECTION_RESET probably due to the querystring being way too long.

I'm thinking I need an object but everything I've researched seems to advise against doing that with a GET and using the POST request instead. Problem is, it's a restful API and I'm already using the POST request for the processing portion. I guess I could use PUT or DELETE but it just feels wrong. I'm going to wire up the PUT right after I post this question to see if it will work but ultimately I'd like to find the correct solution for this.

UPDATE: The PUT method works fine even with over 1000 records selected so I guess this will be my interim solution for now. I still feel like there's code smell and would love to use a GET but at least this allows me to proceed.

Zoey
  • 226
  • 2
  • 13
  • Have a look here https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers – Zorglube Sep 18 '19 at 15:51
  • Does your browser's network console show a difference in the request when it's <3 items vs >3 items? The request must be different in some way to trigger the CORS policy. (I agree, that is strange) – Nate Barbettini Sep 18 '19 at 17:03
  • For request url, its length is limit. Try to construct your url with query string like ``${apiUrl}/?jsonObject=${jsonObject}``. In general, for large request, you may consider move it to request body with post or put. – Edward Sep 19 '19 at 02:11
  • Nate: the query string looks the same with both although I can't see the end of it due to my long property names. Once it gets long enough, I didn't have time to see what the cut-off was but if I passed over 1000s keys I get yet a different error which I'm guessing is due to the query string limit. – Zoey Sep 19 '19 at 15:03
  • Tao: that is what I did, just doesn't feel very Restful so was hoping there was a method using the get that could work. Just feels weird that you can't pass an object to a get, surely there are cases for it. – Zoey Sep 19 '19 at 15:05

0 Answers0