Skip to content

Instantly share code, notes, and snippets.

@kellabyte
Created April 10, 2012 23:29
Show Gist options
  • Save kellabyte/2355599 to your computer and use it in GitHub Desktop.
Save kellabyte/2355599 to your computer and use it in GitHub Desktop.
Web API ideas
/*
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:as="http://atomserver.org/namespaces/1.0/"
xmlns:os="http://a9.com/-/spec/opensearchrss/1.1/">
<os:totalResults>65801</os:totalResults>
<os:startIndex>0</os:startIndex>
<os:itemsPerPage>2</os:itemsPerPage>
<as:endIndex>153</as:endIndex>
<link href="/myserver/v1/widgets/acme?start-index=153&amp;max-results=2" rel="next" />
<link href="/myserver/v1/widgets/acme?start-index=0&amp;max-results=2" rel="self" />
<author>
<name>AtomServer APP Service</name>
</author>
<title type="text">acme entries</title>
<updated>2007-10-05T19:17:42.750Z</updated>
<id>tag:atomserver.org,2007:v1:acme</id>
<entry>
<id>/myserver/v1/widgets/acme/205390.en.xml</id>
<as:entryId>205390</as:entryId>
<title type="text"> Entry: acme 205390.en</title>
<author>
<name>AtomServer Atom Service</name>
</author>
<link href="/myserver/v1/widgets/acme/205390.en.xml" rel="self" />
<link href="/myserver/v1/widgets/acme/205390.en.xml/2" rel="edit" />
</entry>
</feed>
*/
// Option 1 - AtomFormatter understands how to deal with it's own model. Feed, Entry, etc.
public class StoryController : ApiController
{
public HttpResponseMessage Get(int id)
{
Story story = GetMeAStory(id);
var response = new HttpResponseMessage(HttpStatusCode.OK);
Entry entry = ConvertToEntry(story); // Why do we need this?
response.Content = new ObjectContent<SyndicationItem>(entry, atomFormatter);
return response;
}
}
// I'm not convinced we need media type specific models and translate twice. Atom example:
// Story (our model) -> Entry (atom model) -> Atom Representation
//
// I think we can do better.
// Option 2
var formatter = new AtomFormatter();
formatter.MapModel<Story>()
.ToTitle(x => x.Topic)
.ToAuthor(x => x.Owner);
// Option 2b - Since Atom is specifically XML, why not use it.
var formatter = new AtomFormatter();
formatter.MapModel<Story>()
.To("/feed/title", x => x.Topic)
.To("/feed/author/name", x => x.Owner);
// AtomFormatter.MapModel<T>() would return an AtomModelMap, so we still have SRP as the mapping and
// formatting are still independent.
public class StoryController : ApiController
{
public HttpResponseMessage Get(int id)
{
Story story = GetMeAStory(id);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = this.Request.Represent(story); // The proper formatter is used based on conneg
return response;
}
}
// Option 2 and 2b don't require copying data for the purpose of mapping a translation like option 1 does.
// We've also eliminated a double translation that occurred in option 1.
@pedroreys
Copy link

Given that the available transitions/links are dependent of the resource state, I'm assuming the Story object would be responsible to know it's available transitions/links.

The formatter then would have to know how to retrieve the links from the story object in the response message. Is that correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment