Search code examples
c#apix-www-form-urlencoded

API response is always "null"


I created an API and a Login Form and I need to authorize access to my API using Username and Password properties, which I get from two textboxes in my Login Form. However, the response from the API is always null. Here's my original code:

    public async Task<AuthenticatedUser> Authenticate(string username, string password)
    {
        var data = new List<KeyValuePair<string, string>>()
        {
            new KeyValuePair<string, string>("grant_type", "password"),
            new KeyValuePair<string, string>("username", username), //I made sure that both username and password
            new KeyValuePair<string, string>("password", password)  //are passed correctly to the Authenticate() void
        };
        var content = new FormUrlEncodedContent(data); //var data is not null but "content" is
        using (HttpResponseMessage response = await apiClient.PostAsync("/token", content))
        {
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadAsAsync<AuthenticatedUser>(); //response is always "null"
                return result;
            }
            else
            {
                throw new Exception(response.ReasonPhrase);
            }
        }
    }

I tried replacing the List<> with an array of KeyValuePair<>s, I also tried using a Dictionary<string, string>. Neither of these options worked. After some research on the net, I saw an alternative using StringContent or MediaFolder but I didn't know how to make it work with them. I am also using https in my domain, so there seems to be no mistake there. For now, it looks as if FormUrlEncodedContent doesn't encode correctly.

Also, requests from Swagger and Postman return values.


Solution

  • First of all password grant type only accepts form encoding application/x-www-form-urlencoded and not JSON encoding application/JSON.

    You can read more about it here and also try to change the content as follows:

    Replace this:

    var data = new List<KeyValuePair<string, string>>()
    {
         new KeyValuePair<string, string>("grant_type", "password"),
         new KeyValuePair<string, string>("username", username), //I made sure that both username and password
         new KeyValuePair<string, string>("password", password)  //are passed correctly to the Authenticate() void
    };
    var content = new FormUrlEncodedContent(data);
    

    with this:

    var content = new FormUrlEncodedContent(
        new KeyValuePair<string, string>[] {
            new KeyValuePair<string, string>("grant_type", "password"),
            new KeyValuePair<string, string>("username", username),
            new KeyValuePair<string, string>("password", password)
       }
    );