Skip to content

Commit

Permalink
Support for urlencoded form posts.
Browse files Browse the repository at this point in the history
  • Loading branch information
bennor committed Jun 28, 2014
1 parent c69c63c commit ce83803
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
30 changes: 30 additions & 0 deletions Refit-Tests/RequestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public interface IRestMethodInfoTests
[Get("/foo/bar/{id}")]
IObservable<string> FetchSomeStuffWithBody([AliasAs("id")] int anId, [Body] Dictionary<int, string> theData);

[Post("/foo/bar/{id}")]
IObservable<string> PostSomeUrlEncodedStuff([AliasAs("id")] int anId, [Body(BodySerializationMethod.UrlEncoded)] Dictionary<string, string> theData);

[Get("/foo/bar/{id}")]
[Headers("Api-Version: 2 ")]
Task<string> FetchSomeStuffWithHardcodedHeaders(int id);
Expand Down Expand Up @@ -132,6 +135,18 @@ public void FindTheBodyParameter()
Assert.AreEqual(1, fixture.BodyParameterInfo.Item2);
}

[Test]
public void AllowUrlEncodedContent()
{
var input = typeof(IRestMethodInfoTests);
var fixture = new RestMethodInfo(input, input.GetMethods().First(x => x.Name == "PostSomeUrlEncodedStuff"));
Assert.AreEqual("id", fixture.ParameterMap[0]);

Assert.IsNotNull(fixture.BodyParameterInfo);
Assert.AreEqual(0, fixture.QueryParameterMap.Count);
Assert.AreEqual(BodySerializationMethod.UrlEncoded, fixture.BodyParameterInfo.Item1);
}

[Test]
public void HardcodedHeadersShouldWork()
{
Expand Down Expand Up @@ -227,6 +242,9 @@ public interface IDummyHttpApi
[Get("/void")]
Task FetchSomeStuffWithVoid();

[Post("/foo/bar/{id}")]
Task<string> PostSomeUrlEncodedStuff(int id, [Body(BodySerializationMethod.UrlEncoded)] object content);

string SomeOtherMethod();
}

Expand Down Expand Up @@ -423,5 +441,17 @@ public void HttpClientShouldNotPrefixEmptyAbsolutePathToTheRequestUri()

Assert.AreEqual("http://api/foo/bar/42", testHttpMessageHandler.RequestMessage.RequestUri.ToString());
}

[Test]
public void BodyContentGetsUrlEncoded()
{
var fixture = new RequestBuilderImplementation(typeof(IDummyHttpApi));
var factory = fixture.BuildRequestFactoryForMethod("PostSomeUrlEncodedStuff");
var output = factory(new object[] {6, new {Foo = "Something", Bar = 100, Baz = (string) null}});

string content = output.Content.ReadAsStringAsync().Result;

Assert.AreEqual("Foo=Something&Bar=100&Baz=", content);
}
}
}
2 changes: 1 addition & 1 deletion Refit/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public override HttpMethod Method {
}

public enum BodySerializationMethod {
Json, Xml,
Json, UrlEncoded
}

[AttributeUsage(AttributeTargets.Parameter)]
Expand Down
44 changes: 43 additions & 1 deletion Refit/RequestBuilderImplementation.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -82,7 +83,15 @@ public Func<object[], HttpRequestMessage> BuildRequestFactoryForMethod(string me
} else if (stringParam != null) {
ret.Content = new StringContent(stringParam);
} else {
ret.Content = new StringContent(JsonConvert.SerializeObject(paramList[i]), Encoding.UTF8, "application/json");
switch (restMethod.BodyParameterInfo.Item1) {
case BodySerializationMethod.UrlEncoded:
ret.Content = new FormUrlEncodedContent(new FormValueDictionary(paramList[i]));
break;
case BodySerializationMethod.Json:
ret.Content = new StringContent(JsonConvert.SerializeObject(paramList[i]), Encoding.UTF8, "application/json");
break;
}

}

continue;
Expand Down Expand Up @@ -511,4 +520,37 @@ void determineReturnTypeInfo(MethodInfo methodInfo)
throw new ArgumentException("All REST Methods must return either Task<T> or IObservable<T>");
}
}

class FormValueDictionary : Dictionary<string, string>
{
// Can't use ConcurrentDictionary because Silverlight doesn't have it
private static readonly Dictionary<Type, PropertyInfo[]> propertyCache
= new Dictionary<Type, PropertyInfo[]>();

public FormValueDictionary(object source) {
if (source == null) return;

var dictionary = source as IDictionary;
if (dictionary != null) {
foreach (var key in dictionary.Keys) {
Add(key.ToString(), string.Format("{0}", dictionary[key]));
}
}
else {
var type = source.GetType();
if (!propertyCache.ContainsKey(type)) {
propertyCache[type] = getProperties(type);
}
foreach (var property in propertyCache[type]) {
Add(property.Name, string.Format("{0}", property.GetValue(source, null)));
}
}
}

PropertyInfo[] getProperties(Type type) {
return type.GetProperties()
.Where(p => p.CanRead)
.ToArray();
}
}
}

0 comments on commit ce83803

Please sign in to comment.