JSON REST client proxy generator Trying to create something really lightweight. Sources are on GitHub.

To create a proxy we need to define an interface first, e.g.:

// Fake Online REST API for Testing and Prototyping
[Site("https://jsonplaceholder.typicode.com")]    
public interface ITypicode
{
    [Get("posts")]
    Task&lt;BlogPost[]&gt; GetAsync();

    [Get("posts/{0}")]
    Task&lt;BlogPost&gt; GetAsync(int id);

    [Post("posts")]
    Task&lt;BlogPost&gt; PostAsync([Body] BlogPost data);

    [Put("posts/{0}")]
    Task&lt;BlogPost&gt; PutAsync(int id, [Body] BlogPost data);

    [Delete("posts/{0}")]
    Task&lt;BlogPost&gt; DeleteAsync(int id);
}

public class BlogPost
{
    public int UserId { get; set; }
    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}


At this moment we actually know enough to generate a proxy:

ITypicode typicode = RestClient.Create&lt;ITypicode&gt;();
BlogPost blogPost = await typicode.PutAsync(1, new BlogPost { Body = "Wow!" });
Console.WriteLine(blogPost.Body);


We can inject HttpMessageHandler:

ITypicode typicode = RestClient.Create&lt;ITypicode&gt;(handler);


We can also emit the proxy class for dependency injection:

Type typicodeType = RestClient.Emit&lt;ITypicode&gt;();


About error handling – this exception is thrown for unsuccessful HTTP status codes:

public class RestException : Exception
{
    public RestException(HttpResponseMessage response)
    {
        Response = response;
    }

    public HttpResponseMessage Response { get; }
    public override string ToString() =&gt; 
        Response.Content.ReadAsStringAsync().Result;
}


We could specify extra type parameter for the SiteAttribute:

[Site("https://jsonplaceholder.typicode.com", Error = typeof(TypicodeError))]
public interface ITypicode
{
    // …
}


to have generic exception be thrown instead:

public class RestException&lt;TError&gt; : RestException
{
    public RestException(HttpResponseMessage response)
        : base(response)
    {
    }

    public T Error =&gt; JsonConvert.DeserializeObject&lt;TError&gt;(ToString());
}


So error response body will be kindly deserialized for us.

It is possible to implement API interface on a server side ASP.NET Web API Controller also to insure compatibility.

What do you think about this design?

To be continued with implementation details.



UPDATE: Adding support for HTTP headers – something like this:

[Site("https://jsonplaceholder.typicode.com")]
public interface ITypicode
{
    [Get("posts/{0}")]
    [Header("X-API-KEY: {1}")]   // req - in
    [Header("Content-Type: {2}; charset={3}")]  // res - out
    Task&lt;BlogPost&gt; GetAsync(
        int id, string apiKey, out string contentType, out string charset);    
}


Does it look good? Anything else that might be useful?
Usually when I see your questions there isn't much for me to say, because you usually flesh everything out really well. :) (Probably why this has been unanswered so long.)

That said, I think I do have one comment here:

If you have support to edit the HeaderAttribute or the GetAttribute, I would consider replacing the {0}, {1} (etc.) format symbols with a named format symbol.

[Get("posts/{id}")]
Task&lt;BlogPost&gt; GetAsync(int id);

[Site("https://jsonplaceholder.typicode.com")]
public interface ITypicode
{
    [Get("posts/{id}")]
    [Header("X-API-KEY: {apiKey}")]   // req - in
    [Header("Content-Type: {contentType}; charset={charset}")]  // res - out
    Task&lt;BlogPost&gt; GetAsync(
        int id, string apiKey, out string contentType, out string charset);    
}


It makes everything more meaningful.

If it's WebAPI you probably don't have access to the source for these attributes, but you can probably wrap them with a new one to add support for this feature. (Adds a little complexity, but should be really awesome to see happen.)