Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support simple class with BodySerializationMethod.UrlEncoded #79

Open
Pokerkoffer opened this issue Jan 23, 2018 · 6 comments
Open

Support simple class with BodySerializationMethod.UrlEncoded #79

Pokerkoffer opened this issue Jan 23, 2018 · 6 comments

Comments

@Pokerkoffer
Copy link

The param is required to implement IDictionary, https://github.com/canton7/RestEase#url-encoded-bodies e.g.

Task Collect([Body(BodySerializationMethod.UrlEncoded)] Dictionary<string, object> data);

Refit can do this, see: https://github.com/paulcbetts/refit#form-posts e.g.

Task Collect([Body(BodySerializationMethod.UrlEncoded)] Measurement measurement);
// Serialized as: v=1&tid=UA-1234-5&cid=d1e9ea6b-2e8b-4699-93e0-0bcbd26c206c&t=event

Are there any reasons why RestEase doesn't support this or is this just not implemented yet?

Nevertheless, this is an awesome lib! Keep up the good work!

@Pokerkoffer Pokerkoffer changed the title Support simple class in BodySerializationMethod.UrlEncoded Support simple class with BodySerializationMethod.UrlEncoded Jan 23, 2018
@canton7
Copy link
Owner

canton7 commented Jan 27, 2018

It's not supported because I didn't want to start going down the rabbit hole of writing a custom serializer! Those things get complex fast: I've done it before.

That said, it probably isn't too hard to let json.net turn the object into a JObject, then munge that into a query string. I'll have an investigate.

@canton7
Copy link
Owner

canton7 commented Jan 27, 2018

I guess whatever happens to request bodies should also happen to query maps.

@Pokerkoffer
Copy link
Author

This is the class in Refit which is responsible to convert an object to a Dictionary:
https://github.com/paulcbetts/refit/blob/master/Refit/FormValueDictionary.cs

It is used here:
https://github.com/paulcbetts/refit/blob/master/Refit/RequestBuilderImplementation.cs#L444

The field names are retrieved via Reflection and then inserted into the FormUrlEncodedContent class.

@canton7
Copy link
Owner

canton7 commented Feb 4, 2018

Todo list:

  1. Write code to serialise an object to a set of query params.
  2. Add a new attribute allowing a name to be given to a property in such a class
  3. Add a new type of serialiser allowing this behaviour to be customised. Move the existing dictionary serializarion code into this serialiser. Make sure we allow custom cultures, etc.
  4. Refractor RequestInfo so that QueryMap can accept any object, and pass that object to the Requester.
  5. Update Requester so that it calls the serialiser for QueryMap and serialised request bodies.
  6. Consider whether to allow a format string to be used when serializinf property values.
  7. Consider what to do with nested objects. Do we just call ToString on them, or do we try and serialise them? Changing this later will be breaking behaviour.
  8. Tests. Cover non-public properties, abstract, no getter, getter throws an exception, getter returns a collection, getter returns null, getter returns an object whose ToString method throws. Nested objects if appropriate.
  9. Document it all.

@StefH
Copy link

StefH commented Feb 16, 2018

A simple workaround could be:

public class MeasurementWrapper : Dictionary<string, object>
{
    public MeasurementWrapper(Measurement m)
    {
        Add("v", m.V);
        Add("id", m.Id);
    }
}

@canton7
Copy link
Owner

canton7 commented Feb 28, 2018

I had a look at this. Some notes on some of the complexity that needs to be worked through:

  1. I want to make this work similarly for QueryMap and request bodies
  2. With QueryMap, each of the values can be serialized as ToString or Serialized
    a. ToString just calls ToString
    b. Serialized goes through RequestQueryParamSerializer (the same as normal query parameters)
  3. With request bodies, the object as a whole can be serialized as UrlEncoded or Serialized.
    a. UrlEncoded invokes the current IDictionary behaviour, where each value is serialized using ToString, unless it is an IEnumerable, where each value therein is serialized using ToString.
    b. Serialized puts it through RequestBodySerializer, which by default turns it into JSON

So, that issues are:

  1. Members which are IEnumerable are currently handled differently
  2. Query maps have an enum controlling how each individual value is serialized. Bodies have an enum controlling how the object as a whole is serialized.
  3. Bodies may need to use the RequestBodySerializer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants