4
votes

I’m having an issue when calling Elastic from a .NET Core web API application. Below is my setup, description of the issue, and debug information.

My Setup

  • Web API built with .NET Core 2.1
  • Class library encapsulating all my NEST logic
  • Testing Console application Both the web app and the testing console are using the class library’s repository to make the call to elastic.
  • I can run the web API service either locally or locally in a docker container (Ubuntu)
  • Elasticsearch is running locally, Shield is installed with an AD and native realm.
  • All my stuff is using the run-as header and both the console app and web API are using the same bind and run-as user.

Issue: When I execute a query from my console application, I get success and results.
When I do the same via the web API I get the following error:

Unsuccessful low level call on POST: /storeinventory/doc/_search

The odd part is I’m constructing my query with a builder method (used both for the console and web API), when I take the failing query I built from the web API call and paste it into Kibana, it succeeds.

I’ve tested with curl locally using http://localhost:9200 as well as a host name http://mysearch.example.com:9200 (which is configured in my host file) it works on both.

So in short, It appears that making a query from my web API fails, even though the query it builds works in Kibana. However, it works perfectly from my console application.

I’m not sure what I’m missing and will happily entertain all ideas.

Debug info below

Unsuccessful low level call on POST: /storeinventory/doc/_search\r\n# Audit trail of this API call:\r\n - [1] BadRequest: Node: http://elasticsearch.example.com:9200/ Took: 00:00:01.3970177\r\n# OriginalException: System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it\r\n at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)\r\n
--- End of inner exception stack trace ---\r\n at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask)\r\n at System.Threading.Tasks.ValueTask1.get_Result()\r\n
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\r\n at Elasticsearch.Net.HttpConnection.Request[TResponse](RequestData requestData)\r\n# Request:\r\n{\"from\":0,\"size\":10,\"query\":{\"query_string\":{\"query\":\"whiskey\"}},\"highlight\":{\"fields\":{\"itemname\":{}, \"itemlocation\":{}}},\"aggs\":{\"source\": {\"terms\": { \"field\": \"_index\"}},\"Avg_Quantity\": {\"avg\": { \"field\": \"quantity\"}}}}\r\n# Response:\r\n\r\n"

And, here is how I’m making the call using the ElasticLowLevelClient:

var searchResponse = lowlevelClient.Search<StringResponse>(_index, "doc", PostData.String(qJson));

And here is the body of my post for the query, built by my web API application, which works in Kibana:

{
    "from": 0,
    "size": 10,
    "query": {
        "query_string": {
            "query": "whiskey"
        }
    },
    "highlight": {
        "fields": {
            "itemname": {},
            "itemlocation": {}
        }
    },
    "aggs": {
        "source": {
            "terms": {
                "field": "_index"
            }
        },
        "Avg_Quantity": {
            "avg": {
                "field": "quantity"
            }
        }
    }
}
2
The exception System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused indicates a problem connecting to Elasticsearch from the Web API. If you were to issue the same request with HttpClient, do you see the same behaviour?Russ Cam
I plan on testing this later this evening. I've also captured the requests in fiddler from both my console app and the webapi. i'll compare those as well - in case something got added. will update after that.neurongaragesale

2 Answers

0
votes

Ok, so I found the fix.

My node url was http://localhost:9200. This works in the console application, but does not work in the webapi project. I changed it to http://127.0.0.1:9200 and it worked.

For the record (in case someone is looking at this in the future and is like, “but this doesn’t fix my problem!” – spin up fiddler (or a similar app) and watch the traffic.

The error message there was more descriptive. It told me that the error was a timeout. This is a lot more helpful than the error the lowlevelclient returned.

Granted that alone didn’t solve my problem, but it made me reevaluate the situation, do a bit more googling and find someone complaining about curl translating localhost to IPv6 and using 127.0.0.1 instead.

0
votes

In case you are getting this error:

Invalid NEST response built from a unsuccessful (429) low level call on PUT

ServerError: Type: cluster_block_exception Reason: \"index [] blocked by: [TOO_MANY_REQUESTS/12/index read-only / allow delete (api)];

It could be that your C drive is almost full:

enter image description here