Search code examples
c#dotnet-httpclientdsharp+

Why does running this task return Error: System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found)


Just as a side project I decided to make a discord bot that allows for users to enter a word and get its defintion. I've gotten most of the things done except for the command that actually gets the definition. I'm using FreeDictionaryAPI and when I run

public class DictionaryCommand : BaseCommandModule
{
    [Command("dict")]
    public async Task dictCommand(CommandContext ctx)
    {
        //await ctx.Channel.SendMessageAsync("Penis");

        var dictionary = new DictionaryOutput();
        await dictionary.getDefinition(ctx.Message.Content);
        await ctx.Channel.SendMessageAsync(dictionary.defo); 
    }
}

in theory it should run

public async Task getDefinition(string message)
{
    //Dictionary stuff
    string DictionaryURL = "https://api.dictionaryapi.dev/api/v2/entries/en/" + message;

    using (var client = new HttpClient())
    {
        try
        {
            var response = await client.GetStringAsync(DictionaryURL);
            List<Word>? word = JsonSerializer.Deserialize<List<Word>>(response.ToString());
            Console.WriteLine(word);

            defo = word[0].meanings[0].definitions[0].definition;
        }
        catch (HttpRequestException exception)
        {
            Console.WriteLine("Error: {0}", exception);
        }
    }
}

However, it returns

Error: System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at System.Net.Http.HttpClient.GetStringAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   at DictionaryAPITesting.DictionaryOutput.getDefinition(String message) C:\repos\DictionaryAPITesting\DictionaryAPITesting\DictionaryOutput.cs:line 18

Line 18 is the line that contains var response = await client.GetStringAsync(DictionaryURL);

It works fine when the method is .GetAsync but breaks the moment it is switched to .GetStringAsync

So far I have tried to have it simply using the .GetAsync method rather than the .GetStringAsync method, but this has proven futile after the entire program just decides to not run. This is really the only thing I've tried thus far as I don't really know what the issue is. Is there a way to fix this?


Solution

  • Based on this documentation, a command that takes an argument from the user, in your case a word, needs an actual string parameter in the method signature.

    My answer simply returns the string from the HTTP response, but you can do whatever you want like deserializing it to Word objects. It doesn't matter if you use GetStringAsync or GetAsync, what matters is that you handle a 404 Not Found correctly.

    Because, if the URL tries looking up a non-existing word, the API replies with a 404 Not Found status with the following body:

    {"title":"No Definitions Found","message":"Sorry pal, we couldn't find definitions for the word you were looking for.","resolution":"You can try the search again at later time or head to the web instead."}
    

    A possible implementation:

    [Command("dict")]
    public async Task DictCommand(CommandContext ctx, string word)
    {
        var dictionary = new DictionaryOutput();
        string definition = await dictionary.getDefinition(word);
        // await ctx.Channel.SendMessageAsync(dictionary.defo); 
        await ctx.RespondAsync($"Definition for {word}: {definition}");
    }
    
    
    public async Task<string> GetDefinition(string message)
    {
        //Dictionary stuff
        string DictionaryURL = "https://api.dictionaryapi.dev/api/v2/entries/en/" + message;
    
    
        using (var client = new HttpClient())
        {
            try
            {
                var response = await client.GetAsync(DictionaryURL);
                if (response.IsSuccessStatusCode)
                    return await response.Content.ReadAsStringAsync();
                else 
                    return $"Word '{message}' not found in dictionary!";
                // List<Word> word = JsonSerializer.Deserialize<List<Word>>(response.ToString());
            }
            catch (HttpRequestException exception)
            {
                Console.WriteLine("Error: {0}", exception);
            }
        }
        return null;
    }