You are on page 1of 9

Articles Web Development Web Services General

Using Casablanca to consume a REST


API
N
Niisshh N
Niisshhaanntt, 6 Jun 2013

CPOL

4.86 (12 votes)


The article walks through using the Casablanca REST API library to consume a REST web service
from C++ code

Introduction
Casablanca is the quasi-official C++ REST library from Microsoft published as an open source
project on CodePlex. And I say "quasi" as it does not come with Visual C++ by default, but for all
you know that may change in future. The VC++ team has backed it strongly and has recommended
using it for all your REST access requirements.
Casablanca - C++ REST SDK (CodePlex)
Casablanca allows you to write native code to access REST services and uses an asynchronous
approach to consuming HTTP and JSON based services. There are extensions that allow you to
write Windows 8 store applications in Casablanca, but you can use it in desktop apps as well. The
code is written in a portable manner, so you can use it from Linux too, should you want to.
This article quickly demonstrates a skeletal ASP.NET MVC 4 REST web service that is consumed
by C++ code that uses Casablanca to do the four common HTTP operations - GET, POST, PUT,
and DELETE. It also shows how to parse and create JSON, and also how to use the PPL
extensions to write asynchronous code.

The skeletal web service


I wanted to keep the example simple, so this service uses a very simple business object called
Member.
public class Member
{
public int Id { get; set; }
public string Name { get; set; }
public string Sport { get; set; }
}
Instead of reading and witting from an actual database or backend, I have a mock storage class
that can add, edit, fetch, and delete Member objects.

public class Members


{
private Collection<Member> members = new Collection<Member>();
private int nextId = 1;
public Member Add(string name, string sport)
{
var member = new Member()
{
Id = nextId++,
Name = name,
Sport = sport
};
members.Add(member);
return member;
}
public IEnumerable<Member> GetAll()
{
return members;
}
public Member Get(int id)
{
return members.FirstOrDefault(m => m.Id == id);
}
public Member Update(int id, string name, string sport)
{
var item = Get(id);
if (item != null)
{
item.Name = name;
item.Sport = sport;
return item;
}
return null;
}
public bool Delete(int id)
{
var item = Get(id);
if (item != null)
{
members.Remove(item);
return true;
}
return false;
}
}
And here's the controller.
public class ValuesController : ApiController
{
static ValuesController()
{
members.Add("Nish", "Tennis");
members.Add("Andrew", "Baseball");

// . . .
}
private static Members members = new Members();

// GET api/values
public IEnumerable<Member> Get()
{
return members.GetAll();
}
// GET api/values/id
public Member Get(int id)
{
return members.Get(id);
}
// POST api/values
public int Post(dynamic data)
{
return members.Add((string)data.name, (string)data.sport).Id;
}
// PUT api/values/id
public Member Put(int id, dynamic data)
{
return members.Update(id, (string)data.name,
(string)data.sport);
}
// DELETE api/values/id
public bool Delete(int id)
{
return members.Delete(id);
}
}

Making GET calls and parsing JSON


Typically, these are the include files you'd need to use Casablanca.
#include <http_client.h>
#include <ppltasks.h>
#include <json.h>
Here's the C++ version of the business object.
class Member
{
public:
int Id;
std::wstring Name;
std::wstring Sport;
void Display()
{
std::wcout << Id << L", " << Name << L", " << Sport << std::endl;
}
};
I added a Display method for logging/display purposes. I also added a helper class to create a
Member object given JSON data.

enum FieldValue {Id, Name, Sport };


class MemberGenerator
{
std::map<std::wstring, FieldValue> fieldMap;
Member member;
public:
MemberGenerator()
{
fieldMap[L"Id"] = FieldValue::Id;
fieldMap[L"Name"] = FieldValue::Name;
fieldMap[L"Sport"] = FieldValue::Sport;
}
void SetField(std::wstring name, json::value value)
{
switch(fieldMap[name])
{
case FieldValue::Id:
member.Id = value.as_integer();
break;
case FieldValue::Name:
member.Name = value.as_string();
break;
case FieldValue::Sport:
member.Sport = value.as_string();
break;
}
}
Member GetMemberFromJson(json::value jsonValue)
{
for(auto iterInner = jsonValue.cbegin(); iterInner !=
jsonValue.cend(); ++iterInner)
{
const json::value &propertyName = iterInner->first;
const json::value &propertyValue = iterInner->second;
SetField(propertyName.as_string(), propertyValue);
}
return member;
}
};
I wish C++ had reflection the way C# has (or rather .NET has). That'd have made writing this much
easier and cleaner. But this is close enough and is probably better from a performance perspective.
The GetMemberFromJson gets a json::value object as its argument. The
json::value class is basically a C++ abstraction over a JSON value. In my example, this will
be a composite JSON value that contains the properties of the Member object. Using cbegin
and cend, we iterate through the composite object. The iterator is an std::vector of an
std::pair of json::value objects. The pair represents the property name and its
associated value. The SetField method then looks up the property name and for each
property, we know the type and thus call one of the as_xxx() methods which converts the
JSON value into the requested type. Obviously, a more real world scenario would have multi-level
nested business objects, so you'd need a more involved conversion framework, but I would
imagine that the core approach would remain very similar to what I did there.
Here's the code that does a G
GE
ETT call to get all objects. This is basically the implementation for
G
GE
ETT aappii//vvaalluueess.
pplx::task<void> GetAll()

{
return pplx::create_task([]
{
http_client client(L"http://localhost:5540/api/values");
return client.request(methods::GET);
}).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
return response.extract_json();
}
return pplx::create_task([] { return json::value(); });
}).then([](json::value jsonValue)
{
if(jsonValue.is_null())
return;
MemberGenerator generator;
for(auto iterArray = jsonValue.cbegin(); iterArray !=
jsonValue.cend(); ++iterArray)
{
const json::value &arrayValue = iterArray->second;
auto member = generator.GetMemberFromJson(arrayValue);
member.Display();
}
});
}
The http_client class, rather unsurprisingly named, is the core class that handles the HTTP
connection to the web service. The request method sends the HTTP request asynchronously,
and I've specified this to be a G
GE
ETT request. The continuation gets an http_response object
that represents the response from the server. (These methods and types are so lucidly named that
I feel like an idiot repeating things. I mean saying things like - the http_response class represents
an HTTP response. Oh well!) It's got methods to get the body, headers, status code, etc. Once I
verify that the response code was 200, I call the extract_json method, also asynchronous.
When that's completed, the continuation receives a json::value object. In this case, I know
it's an array of JSON values representing Member objects, and so I iterate through the list and
extract the Member objects using my object conversion class. Here's the code that does a G
GE
ETT
aappii//vvaalluueess//iidd call.
pplx::task<void> Get(int id)
{
return pplx::create_task([id]
{
std::wstringstream ws;
ws << L"http://localhost:5540/api/values/" << id;
http_client client(ws.str());
return client.request(methods::GET);
}).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
return response.extract_json();
}
return pplx::create_task([] { return json::value(); });
}).then([](json::value jsonValue)
{

if(jsonValue.is_null())
return;
MemberGenerator generator;
auto member = generator.GetMemberFromJson(jsonValue);
member.Display();
});
}
It's quite similar except the URL now includes the id to fetch and the JSON response is for a single
Member object.

Submitting a POST
Here's code showing how to P
PO
OS
STT data to the service.
pplx::task<int> Post()
{
return pplx::create_task([]
{
json::value postData;
postData[L"name"] = json::value::string(L"Joe Smith");
postData[L"sport"] = json::value::string(L"Baseball");
http_client client(L"http://localhost:5540/api/values");
return client.request(methods::POST, L"",
postData.to_string().c_str(), L"application/json");
}).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
auto body = response.extract_string();
std::wcout << L"Added new Id: " << body.get().c_str() <<
std::endl;
return std::stoi(body.get().c_str());
}
return 0;
});
}
The json::value class has overloaded [] operators, so you can use an array-like
syntax to set data. When making the request call, you need to specify P
PO
OS
STT, provide the data
to sent, and set the ccoonntteenntt--ttyyppee to aapppplliiccaattiioonn//jjssoonn. The web service returns back the ID of the
newly added object, so there's code there to parse that and return the int value.

Making PUT and DELETE calls


The P
PU
UTT implementation is very similar to P
PO
OS
STT, except you pass an ID.
pplx::task<void> Put(int id)
{
return pplx::create_task([id]
{
json::value postData;
postData[L"name"] = json::value::string(L"Joe Y Smith");
postData[L"sport"] = json::value::string(L"Baseball 2");
std::wstringstream ws;

ws << L"http://localhost:5540/api/values/" << id;


http_client client(ws.str());
return client.request(methods::PUT, L"",
postData.to_string().c_str(), L"application/json");
}).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
auto body = response.extract_string();
std::wcout << L"Updated: " << body.get().c_str() << std::endl;
}
});
}
The D
DE
ELLE
ETTE
E is fairly simple too.
pplx::task<void> Delete(int id)
{
return pplx::create_task([id]
{
std::wstringstream ws;
ws << L"http://localhost:5540/api/values/" << id;
http_client client(ws.str());
return client.request(methods::DEL);
}).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
auto body = response.extract_string();
std::wcout << L"Deleted: " << body.get().c_str() << std::endl;
}
});
}
This actually returns a bool, but I am not parsing it and merely displaying it to the console. But
you can really do whatever you want with it. At this point, it's fairly easy to chain all these calls
together and do something like this.
GetAll().then([]
{
Post().then([](int newId)
{
Get(newId).then([newId]
{
Put(newId).then([newId]
{
GetAll().then([newId]
{
Delete(newId).then([]
{
GetAll();
});
});
});
});
});
});
That's all. As usual, do post any feedback or criticism via the forum at the bottom of this article.

References
Setting VC++ up to use Casablanca
Casablanca on CodePlex

History
JJuunnee 66tthh,, 22001133 - Article published

License
This article, along with any associated source code and files, is licensed under The Code Project
Open License (CPOL)

Share
About the Author
N ish N ishant

United States
N
Niisshh N
Niisshhaanntt is a Software Architect/Consultant based out of C
Coolluum
mbbuuss,, O
Ohhiioo. He has over 16
years of software industry experience in various roles including LLeeaadd S
Sooffttw
waarree A
Arrcchhiitteecctt,
P
Prriinncciippaall S
Sooffttw
waarree E
Ennggiinneeeerr, and P
Prroodduucctt M
Maannaaggeerr. Nish is a recipient of the annual
M
Miiccrroossoofftt V
Viissuuaall C
C++++ M
MV
VP
P Award since 2002 (14 consecutive awards as of 2015).
Nish is an industry acknowledged expert in the Microsoft technology stack. He authored
C++/CLI in Action for Manning Publications in 2005, and had previously co-authored
Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition,
he has over 140 published technology articles on CodeProject.com and another 250+ blog
articles on his
WordPress blog. Nish is vastly experienced in team management, mentoring teams, and
directing all stages of software development.
C
Coonnttaacctt N
Niisshh : You can reach Nish on his google email id vvooiiddnniisshh.
W
Weebbssiittee aanndd B
Blloogg
www.voidnish.com
voidnish.wordpress.com

You may also be interested in...


Consuming
Google Maps API
Rest Services in
.NET

The Microsoft
Cloud Platform for
Developers

Consuming CrossDomain WCF


REST Services
with jQuery using
JSONP

Game On: Intel


Edison with the
Xadow Wearable
Kit

Create RESTful
WCF Service API:
Step By Step
Guide

Building Modern
Web Apps with
ASP.NET MVC 6

Comments and Discussions


55 m
meessssaaggeess have been posted for this article Visit hhttttpp::////w
ww
ww
w..ccooddeepprroojjeecctt..ccoom
m//A
Arrttiicclleess
//660033881100//U
Ussiinngg--C
Caassaabbllaannccaa--ttoo--ccoonnssuum
mee--aa--R
RE
ES
STT--A
AP
PII to post and view comments on this
article, or click hheerree to get a print view with messages.

Permalink | Advertise | Privacy | Terms of Use | Mobile


Web03 | 2.8.160304.1 | Last Updated 6 Jun 2013

Select Language

Article Copyright 2013 by Nish Nishant


Everything else Copyright CodeProject, 1999-2016

You might also like