Easy HTTP–not Just a Catchy Name

I was recently referred to EasyHTTP by it’s creator, Hadi Hariri. Hadi was looking at some code I had sent him regarding my work with the TeamCity REST API and thought that things could be a little easier and less verbose.

我最近被它的创造者Hadi Hariri称为EasyHTTP

Hadi正在查看我发给他的关于我使用TeamCity REST API的一些代码,并认为事情可能会更简单,更简洁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Caller
{
public Uri CreateUri(string relativeUrl)
{
//url build here
}
public HttpWebRequest CreateWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.Credentials = new NetworkCredential(_configuration.UserName,
_configuration.Password);
webRequest.Proxy = null;
return (webRequest);
}
public string Request(Uri uri)
{
HttpWebRequest webRequest = CreateWebRequest(uri);
webRequest.Accept = "application/json";
string output = string.Empty;
try
{
using (var response = webRequest.GetResponse())
{
using (var stream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1252)))
{
output = stream.ReadToEnd();
}
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
using (var stream = new StreamReader(ex.Response.GetResponseStream()))
{
output = stream.ReadToEnd();
}
}
else if (ex.Status == WebExceptionStatus.Timeout)
{
output = "Request timeout is expired.";
}
}
return output;
}
}

In summary my application creates a new HttpWebRequest passing in the request type as a magic string. It opens a stream to read the JSON response and that JSON is then de-serialised to an entity. It was very messy. In order to call this class from my application I would have had to do the follow:

总之,我的应用程序创建了一个新的HttpWebRequest,将请求类型作为魔术字符串(magic string)传递。 它打开一个流来读取JSON响应,然后将JSON反序列化为实体。 这非常凌乱。 为了从我的应用程序中调用此类,我将不得不执行以下操作:

1
2
3
4
5
6
7
8
public IEnumerable<Project> GetAllProjects()
{
var uri = _caller.CreateUri("/URL");
var request = _caller.Request(uri);

var projects = JsonConvert.DeserializeObject<ProjectWrapper>(request).Projects;
return projects;
}

There is absolutely no mention of whether the request was a GET never mind a PUT or a DELETE. This is where EasyHTTP came in for me.

绝对没有提到请求是否是GET,PUT还是DELETE。 这就是EasyHTTP为我提供的地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Caller
{
public T Get<T>(string urlPart)
{
var request = CreateHttpRequest(_configuration.UserName, _configuration.Password);
string url = CreateUrl(urlPart);
try
{
var staticBody = request.Get(url).StaticBody<T>();
return staticBody;
}
catch (HttpException ex)
{
//do something here for an outut
throw;
}
}
private string CreateUrl(string urlPart)
{
var protocol = _configuration.UseSSL ? "https://" : "http://";
return string.Format("{0}{1}{2}", protocol, _configuration.HostName, urlPart);
}

HttpClient CreateHttpRequest(string userName, string password)
{
var httpClient = new HttpClient();
httpClient.Request.Accept = HttpContentTypes.ApplicationJson;
httpClient.Request.SetBasicAuthentication(userName, password);

return httpClient;
}
}

I was able to make a generic method for a GET request. This method takes a url and a type and with the help of JsonFx, de-serialises the response back to the requested type. THis was a great way to take the hassle out of my old code where I was creating a Url, calling a request and then de-serialising it. The code in the calling class now looks as follows:

我能够为GET请求创建一个通用方法。
此方法采用url和类型,并在JsonFx的帮助下,将响应内容(response)反序列化回请求的类型。 这是解决我的旧代码的麻烦的一个很好的方式,我在创建一个Url,调用请求然后反序列化它。 调用类中的代码现在看起来如下:

1
2
3
4
5
public List<Project> GetAllProjects()
{
var projectWrapper = _caller.Get<ProjectWrapper>("/Url");
return projectWrapper.Project;
}

I was originally using the Newtonsoft JSON library for my de-serialising my JSON back to types and to do that I had to decorate the properties with code similar to the following:

我最初使用Newtonsoft JSON library将我的JSON反序列化为类型,为此我必须使用它来装饰属性 代码类似于以下内容:

1
2
[JsonProperty(PropertyName = “id”)]
public string Id {get; set;}

This would effectively map a piece of JSON to a property that was not named exactly the same. EasyHTTP took care of this for me as well. To quote Hadi, EasyHTTP handles mapping as follows:

这样可以有效地将一段JSON映射到一个未命名为 exactly的属性。 EasyHTTP也为我解决了这个问题。 引用Hadi,EasyHTTP处理映射如下:

“For mapping properties, it handles camelcase, lowercase and a bunch of other conventions. You can also specify explicitly”

“对于映射属性,它处理camelcase,小写和一些其他约定。 你也可以明确指定”

Using EasyHTTP, I was able to cut at least 2 lines of code per method in the client code. I was also able to delete an attribute that was present on all properties in the entities in a little bit of work.

使用EasyHTTP,我能够在客户端代码中为每个方法删除至少2行代码。 我还能够在一些工作中删除实体中的所有属性

The added distinction of creating the notion of GETs, PUTs and DELETE calls from each other mean that my class can be extended much easier. Hadi has written a post on EasyHTTP on his blog. I would strongly suggest reading this and discovering if you can use this application in place of old HttpWebRequest calls. Its cleaner and helps to make code a little bit more DRY. My thanks to Hadi (and any contributors there may be) for making my work in this area a little easier!

创建GET,PUT和DELETE调用概念的额外区别意味着我的类可以更容易地扩展。 Hadi在他的博客上写了一篇关于EasyHTTP的文章。 我强烈建议阅读本文并发现是否可以使用此应用程序代替旧的HttpWebRequest调用。 它更干净,有助于使代码更简练。 我要感谢Hadi(以及可能的任何贡献者)让我在这方面的工作变得更轻松!