Serge P
Serge P

Reputation: 1611

RestSharp unable to cast object when awaiting for response

Using RestSharp I'm building an API to perform CRUD operations given a datatype/object.

My CrudAbstract class is generic and has the following:

public virtual async Task<keyType> Post(dto item)
{
    try
    {
        var request = await _client.GetRequestAsync(_path);
        request.Method = RestSharp.Method.POST;
        request.AddJsonBody(item);
        var result = await _client.ExecuteRequestAsync<keyType>(request);
        return result;
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
    throw new Exception("Was not able to process crud post operation.");
}

My WebClient class has the following:

Entities = new CrudAbstract<DtoEntity, int>("/entities", this); // in constructor
// So the keyType from definition above is int (Int32)

The post method in this class is

public async Task<T> ExecuteRequestAsync<T>(IRestRequest request)
{
    try
    {
        var response = await GetClient().ExecuteTaskAsync<T>(request);

        // Exception occurs here. The above statement is unable to finish.

        var data = response.Data;
        return data;
    }
    catch (Exception e)
    {
        // Log exception
    }
    throw new Exception("Was not able to process restclient execute async method.");
}

My Api EntitiesController has the following:

    public int Post(DtoEntity value)
    {
        using (var db = // some database...)
        {
            try
            {
                // Upsert object into database here
                //... value.Id no longer null at this point

                /*
                   The problem occurs here. I only want to return the ID of the object 
                   (value.Id). I do not want to return the whole object (value)
                */
                return value.Id;
            }
            catch (Exception e)
            {
                // Log exception
            }
        }
        throw new Exception("Was not able to process entities post method.");
    }

The exception I get is:

Unable to cast object of type 'System.Int64' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.

This is basically saying it is unable to cast the object int (which I have returned in the post with value.Id) to a DtoEntity object (which is the actual object on which CRUD operations were performed).

What am I doing wrong?

I have placed typeof and .getType() onto each keyType, T, and value.Id, and all of them are Int32. Is it in the RestSharp library that the problem occurs? At what stage is there a casting of int to a DtoEntity in the line:

var response = await GetClient().ExecuteTaskAsync<T>(request);

Note: when I change the return type of the post method in my controller to DtoEntity and change the value.Id to just value it works. The response is received, and the response.Data is the DtoEntity object.

I've seen similar questions here but not found a solution yet.

Upvotes: 1

Views: 1529

Answers (1)

Todd Menier
Todd Menier

Reputation: 39319

I believe you've spotted a bug in RestSharp. RestSharp internally uses a JSON parser called SimpleJson (borrowed from the Facebook .NET SDK). It appears that this parser is correctly deserializing the response body to a number (since JSON is untyped it uses Int64 to be safe), but the RestSharp's JsonDeserializer class attempts to cast this result to an IDictionary in the first line of this method:

    private object FindRoot(string content)
    {
        var data = (IDictionary<string, object>)SimpleJson.DeserializeObject(content);

        if (RootElement.HasValue() && data.ContainsKey(RootElement))
        {
            return data[RootElement];
        }

        return data;
    }

I think your options are:

  • File an issue with the RestSharp team.
  • Get the raw string body and cast it to an int yourself (may be the path of least resistance).
  • Try a different library.

Upvotes: 3

Related Questions