Skip to content

Instantly share code, notes, and snippets.

@droyad
Last active August 29, 2015 14:11
Show Gist options
  • Select an option

  • Save droyad/605cbc124481e918f1d2 to your computer and use it in GitHub Desktop.

Select an option

Save droyad/605cbc124481e918f1d2 to your computer and use it in GitHub Desktop.
Dogfooding API Client
public class GenerateInvoice
{
private readonly IApiDogfoodingClient<Api.ElectricityInvoiceController> _apiElectricityController
public async Task<ActionResult> Invoice(int id)
{
var invoice = await _apiElectricityController.Get(c => c.Get(id));
return new PdfReportResult<ElectricityInvoiceReport>(invoice);
}
}
public class ElectricityInvoiceController : ApiController
{
[Route("api/Reporting/ElectricityInvoice/{id}")]
public ElectricityInvoiceModel[] Get(int id)
{
// Implementation
}
}
public interface IApiDogfoodingClient<T> where T : ApiController
{
Task<TResult> Get<TResult>(Expression<Func<T, TResult>> call);
}
public class ApiDogfoodingClient<T> : IApiDogfoodingClient<T> where T : ApiController
{
private readonly Uri _baseUri;
public ApiDogfoodingClient(HttpRequestBase request, UrlHelper urlHelper)
{
_baseUri = new Uri(request.Url, urlHelper.Content("~"));
}
public async Task<TResult> Get<TResult>(Expression<Func<T, TResult>> call)
{
var uri = GetUri(call);
var handler = new HttpClientHandler { UseDefaultCredentials = true };
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var result = await client.GetStringAsync(uri);
return JsonConvert.DeserializeObject<TResult>(result);
}
}
private Uri GetUri<TResult>(Expression<Func<T, TResult>> call)
{
var methodCall = (MethodCallExpression)call.Body;
var query = GetQuery(methodCall);
var route = methodCall.Method.GetCustomAttribute<System.Web.Http.RouteAttribute>().Template;
var template = new UriTemplate(route);
var uri = template.BindByName(_baseUri, query);
return uri;
}
private static Dictionary<string, string> GetQuery(MethodCallExpression methodCall)
{
var parameters = methodCall.Method.GetParameters().Select(p => p.Name).ToArray();
var arguments = methodCall.Arguments.Select(GetValue).ToArray();
var query = new Dictionary<string, string>();
for (int x = 0; x < parameters.Length; x++)
query[parameters[x]] = "" + arguments[0];
return query;
}
private static object GetValue(Expression expr)
{
var memberExpr = expr as MemberExpression;
if (memberExpr != null)
{
var obj = ((ConstantExpression)memberExpr.Expression).Value;
var memberInfo = memberExpr.Member;
if (memberInfo is PropertyInfo)
return ((PropertyInfo)memberInfo).GetValue(obj);
if (memberInfo is FieldInfo)
return ((FieldInfo)memberInfo).GetValue(obj);
throw new Exception("Could not get value from MemberExpression with expression of " + memberInfo.GetType());
}
if (expr is ConstantExpression)
return ((ConstantExpression)expr).Value;
throw new AggregateException("Could not get the value from a " + expr.GetType());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment