8000 Support for URL encoded form posts. by bennor · Pull Request #46 · reactiveui/refit · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Support for URL encoded form posts. #46

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

Merged
merged 1 commit into from
Jul 6, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not going to be constantly reading and writing to this collection from multiple threads, it's actually more efficient to just use lock in these cases

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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lock this block

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