54
       

A Guide to Designing and Building RESTful Web Services With WCF 3

Embed Size (px)

DESCRIPTION

RESTFul Services

Citation preview

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 1/54

   

 

 

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 2/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 3/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 4/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 5/54

 

 

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 6/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 7/54

?tag={tag}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 8/54

{username}?tag={tag}

/users/{username}

/users/{username}/profile

/users/{username}/bookmarks

/users/{username}/bookmarks?tag={tag}

/users/{username}/bookmarks/{id}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 9/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 10/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 11/54

Authorization: skonnard:uCMfSzkjue+HSDygYB5aEg==

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 12/54

<User>

  <Email>[email protected]</Email>

  <Name>Aaron Skonnard</Name>

</User>

<User>

  <Bookmarks>http://contoso.com/bookmarkservice/skonnard</Bookmarks>

  <Email>[email protected]</Email>

  <Id>http://contoso.com/bookmarkservice/skonnard</Id>

  <Name>Aaron Skonnard</Name>

</User>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 13/54

<UserProfile>

  <Bookmarks>http://contoso.com/bookmarkservice/skonnard</Bookmarks>

  <Id>http://contoso.com/bookmarkservice/skonnard</Id>

  <Name>Aaron Skonnard</Name>

</UserProfile>

<Bookmark>

  <Public>true</Public>

  <Tags>REST,WCF</Tags>

  <Title>Aaron’s Blog</Title>

  <Url>http://pluralsight.com/aaron</Url>

</Bookmark>

<Bookmark>

  <Id>http://contoso.com/bookmarkservice/users/skonnard/bookmarks/13</Id>

  <LastModified>2008‐03‐12T00:00:00</LastModified>

  <Public>true</Public>

  <Tags>REST,WCF</Tags>

  <Title>Aaron's Blog</Title>

  <Url>http://pluralsight.com/aaron</Url>

  <User>skonnard</User>

  <UserProfile>http://contoso.com/bookmarkservice/users/skonnard/profile

  </UserProfile>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 14/54

</Bookmark>

<Bookmarks>

  <Bookmark>

  <Id>http://contoso.com/bookmarkservice/users/skonnard/bookmarks/13</Id>

  <LastModified>2008‐03‐12T00:00:00</LastModified>

  <Public>true</Public>

  <Tags>REST,WCF</Tags>

  <Title>Aaron's Blog</Title>

  <Url>http://pluralsight.com/aaron</Url>

  <User>skonnard</User>

  <UserProfile>http://contoso.com/bookmarkservice/users/skonnard/profile

  </UserProfile>

  </Bookmark>

  <Bookmark>...</Bookmark>

  <Bookmark>...</Bookmark>

</Bookmarks>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 15/54

?tag={tag}&format=json

{username}?tag={tag}&format=json

users/{username}?format=json

users/{username}/profile?format=json

...

{User:{Email:'[email protected]', Name:'Aaron Skonnard'}}

 

feed?tag={tag}&format={format}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 16/54

<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Public Bookmarks</title>

  <updated>2008‐09‐13T18:30:02Z</updated>

  <id>http://contoso.com/bookmarkservice/feed</id>

  <entry>

  <author>

  <name>Aaron Skonnard</name>

  </author>

  <title>Aaron’s Blog</title>

  <link href="http://pluralsight.com/aaron"/>

  <id>http://contoso.com/bookmarkservice/users/skonnard/bookmarks/13</id>

  <updated>2008‐09‐13T18:30:02Z</updated>

  <category term="REST,WCF"/>

</entry>

  <entry>...</entry>

  <entry>...</entry>

</feed>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 17/54

<service xmlns="http://www.w3.org/2007/app"

  xmlns:atom="http://www.w3.org/2005/Atom">

  <workspace>

  <atom:title>Contoso Bookmark Service</atom:title>

  <collection href="http://contoso.com/bookmarkservice/" >

  <atom:title>Public Bookmarks</atom:title>

  </collection>

<collection href="http://contoso.com/bookmarkservice/skonnard" >

  <atom:title>Aaron Skonnard's Public Bookmarks</atom:title>

  </collection>

<collection>...</collection>

  </workspace>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 18/54

</service>

 

OPTIONS http://contoso.com/bookmarkservice/skonnard/bookmarks HTTP/1.1

HTTP/1.1 200 OK

Allow: GET, POST

HTTP/1.1 200 OK

Allow: GET

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 19/54

POST /bookmarkservice/skonnard/bookmarks/123 HTTP/1.1

X‐HTTP‐Method‐Override: DELETE

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 20/54

public class  BookmarkService : IHttpHandler

{

  public bool  IsReusable { get  { return true; } }

  public void  ProcessRequest(HttpContext context)

  {

  Uri uri = context.Request.Url;

  // compare URI to resource templates and find match

  if  (Matches(uri, "{username}?tag={tag}"))

  {

  // extract variables from URI

  Dictionary<string, string> vars =

  ExtractVariables(uri, "{username}?tag={tag} ");

  string  username = vars["username"];

  string  tag = vars["tag"];

  // figure out which HTTP method is being used

  switch  (context.Request.HttpMethod)

  {

  // dispatch to internal methods based on URI and HTTP method

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 21/54

 

  // and write the correct response status & entity body

  case "GET":

  List<Bookmark> bookmarks = GetBookmarks(username, tag);

  WriteBookmarksToResponse(context.Response, bookmarks);

  SetResponseStatus(context.Response, "200", "OK");

  break;

  case "POST":

  Bookmark newBookmark = ReadBookmarkFromRequest(context.Request);

  string  id = CreateNewBookmark(username, newBookmark);

  WriteLocationHeader(id);

  SetResponseStatus(context.Response, "201", "Created");

  break;

  default:

  SetResponseStatus(context.Response, "405", "Method Not Allowed");

  }

  }

  if  (Matches(uri, "users/{username}/bookmarks/{id}"))

  {

  // dispatch to internal methods based on URI and HTTP method

  // and write the correct response status & entity body

  ...  }

  ... // match addition URI templates here

  }

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 22/54

 

public class  User

{

  public  Uri Id { get; set; }

  public string  Username { get; set; }

  public string  Name { get; set; }

  public string  Email { get; set; }

  public  Uri Bookmarks { get; set; }

}

public class  UserProfile{

  public  Uri Id { get; set; }

  public string  Name { get; set; }

  public  Uri Bookmarks { get; set; }

}

public class  Bookmark

{

  public  Uri Id { get; set; }

  public string  Title { get; set; }

  public  Uri Url { get; set; }

  public string  User { get; set; }  public  Uri UserLink { get; set; }

  public string  Tags { get; set; }

  public bool  Public { get; set; }

  public  DateTime LastModified { get; set; }

}

[CollectionDataContract]

public class  Bookmarks : List<Bookmark>

{

  public  Bookmarks() { }

  public  Bookmarks(List<Bookmark> bookmarks) : base(bookmarks) {}

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 23/54

public class  BookmarkService

{

  Bookmarks GetPublicBookmarks(string  tag) {...}

  Bookmarks GetUserPublicBookmarks(string  username, string  tag) {...}

  Bookmarks GetUserBookmarks(string  username) {...}

  UserProfile GetUserProfile(string  username) {...}  User GetUser(string  username) {...}

  void  PutUser(string  username, User user) {...}

  void  DeleteUser(string  username) {...}

  Bookmark GetBookmark(string  username, string  id) {...}

  void  PostBookmark(string  username, Bookmark newValue) {...}

  void  PutBookmark(string  username, string  id, Bookmark bm) {...}

  void  DeleteBookmark(string  username, string  id) {...}

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 24/54

Uri baseUri = new  Uri("http://contoso.com/bookmarkservice");

UriTemplate uriTemplate = new  UriTemplate(

  "users/{username}/bookmarks/{id}");

// generate a new bookmark URI

Uri newBookmarkUri = uriTemplate.BindByPosition(baseUri, "skonnard", "123");// match an existing bookmark URI

UriTemplateMatch match = uriTemplate.Match(baseUri, newBookmarkUri);

System.Diagnostics.Debug.Assert(match != null);

Console.WriteLine(match.BoundVariables["username"]);

Console.WriteLine(match.BoundVariables["id"]);

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 25/54

[ServiceContract]

public partial class  BookmarkService

{  [WebGet(UriTemplate = "?tag={tag}")]

  [OperationContract]

  Bookmarks GetPublicBookmarks(string  tag) {...}

  [WebGet(UriTemplate = "{username}?tag={tag}")]

  [OperationContract]

  Bookmarks GetUserPublicBookmarks(string  username, string  tag) {...}

  [WebGet(UriTemplate = "users/{username}/bookmarks?tag={tag}")]

  [OperationContract]

  Bookmarks GetUserBookmarks(string  username, string  tag) {...}

  [WebGet(UriTemplate = "users/{username}/profile")]

  [OperationContract]

  UserProfile GetUserProfile(string  username) {...}

  [WebGet(UriTemplate = "users/{username}")]

  [OperationContract]

  User GetUser(string  username) {...}

  [WebGet(UriTemplate = "users/{username}/bookmarks/{bookmark_id}" )]

  [OperationContract]

  Bookmark GetBookmark(string  username, string  bookmark_id) {...}

  ...

}

[ServiceContract]

public partial class  BookmarkService

{

  [WebInvoke(Method = "PUT", UriTemplate = "users/{username}")]

  [OperationContract]

  void  PutUserAccount(string  username, User user) {...}

  [WebInvoke(Method = "DELETE", UriTemplate = "users/{username}")]

  [OperationContract]

  void  DeleteUserAccount(string  username) {...}

  [WebInvoke(Method = "POST", UriTemplate = "users/{username}/bookmarks")]

  [OperationContract]

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 26/54

  void  PostBookmark(string  username, Bookmark newValue) {...}

  [WebInvoke(Method = "PUT", UriTemplate = "users/{username}/bookmarks/{id")]

  [OperationContract]

  void  PutBookmark(string  username, string  id, Bookmark bm) {...}

  [WebInvoke(Method = "DELETE", UriTemplate = "users/{username}/bookmarks/{id}")]

  [OperationContract]

  void  DeleteBookmark(string  username, string  id) {...}

  ...

}

[ServiceContract]

public partial class  BookmarkService

{

  // in‐memory resource collections

  Dictionary<string, User> users = new  Dictionary<string, User>();

  Dictionary<string, Bookmark> bookmarks = new  Dictionary<string, Bookmark>();

  [WebGet(UriTemplate = "users/{username}")]

  [OperationContract]

  User GetUserAccount(string  username)

  {

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 27/54

  if  (!IsUserAuthorized(username))

  {

  WebOperationContext.Current.OutgoingResponse.StatusCode =

  HttpStatusCode.Unauthorized;

  return;

  }

  User user = FindUser(username);

  if  (user == null)

  {

  WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();

  return null;

  }

  return  user;

  }

  [WebInvoke(Method = "PUT", UriTemplate = "users/{username}")]

  [OperationContract]

  void  PutUserAccount(string  username, User newValue)

  {

  User user = FindUser(username);

  if  (user == null)

  {  // set status to created and include new URI in Location header

  WebOperationContext.Current.OutgoingResponse.SetStatusAsCreated(

  GetUserLink(username));

  ... // process new user backend logic

  }

  else if  (!IsUserAuthorized(username))

  {

  WebOperationContext.Current.OutgoingResponse.StatusCode =

  HttpStatusCode.Unauthorized;

  return;

  }  // create or update new user, but don't let user set Id/Bookmarks

  newValue.Id = GetUserLink(username);

  newValue.Bookmarks = GetUserBookmarksLink(username);

  users[username] = newValue;

  }

  ... // remaining methods ommitted

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 28/54

ServiceHost host = new ServiceHost(typeof(BookmarkService),

  new Uri("http://localhost:8080/bookmarkservice"));

host.Open();

... // keep the host open until you want to shut it down

 

WebServiceHost host = new WebServiceHost(typeof(BookmarkService),

  new Uri("http://localhost:8080/bookmarkservice"));

host.Open();

... // keep the host open until you want to shut it down

<configuration>

  <system.serviceModel>

  <services>  <service name="BookmarkService">

  <endpoint binding="webHttpBinding"  contract="BookmarkService"

  behaviorConfiguration="webHttp"/>

  </service>

  </services>

  <behaviors>

  <endpointBehaviors>

  <behavior name="webHttp">

  <webHttp/>

  </behavior>

  </endpointBehaviors>  </behaviors>

  </system.serviceModel>

<configuration>

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 29/54

<%@ ServiceHost Service="BookmarkService"

  Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

<configuration>

  <system.serviceModel>

  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

  </system.serviceModel>

</configuration>

[AspNetCompatibilityRequirements(RequirementsMode =

  AspNetCompatibilityRequirementsMode.Allowed)]

[ServiceContract]

public partial class BookmarkService

{

  ...

http://localhost/bookmarkservice.svc/skonnard?tag=wcf

http://localhost/bookmarkservice.svc/users/skonnard/bookmarks/13

...

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 30/54

http://localhost/bookmarkservice/skonnard?tag=wcf

http://localhost/bookmarkservice/users/skonnard/bookmarks/13

...

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 31/54

[ServiceContract]public partial class  BookmarkService

{

  ...

  [WebInvoke(Method = "POST", RequestFormat=WebMessageFormat.Json,

  UriTemplate = "users/{username}/bookmarks?format=json")]

  [OperationContract]

  void  PostBookmarkAsJson(string  username, Bookmark newValue)

  {

  HandlePostBookmark(username, newValue);

  }

  [WebGet(ResponseFormat= WebMessageFormat.Json,  UriTemplate = "users/{username}/bookmarks/{id}?format=json" )]

  [OperationContract]

  Bookmark GetBookmarkAsJson(string  username, string  id)

  {

  HandleGetBookmark(username, id);

  }

  ...

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 32/54

[WebGet(UriTemplate ="feed?tag={tag}&format=atom")]

[ServiceKnownType(typeof(Rss20FeedFormatter))]

[ServiceKnownType(typeof(Atom10FeedFormatter))]

[OperationContract]

SyndicationFeedFormatter GetPublicBookmarksFeed(string  tag, string  format)

{

  Bookmarks publicBookmarks = HandleGetPublicBookmarks(tag);  WebOperationContext ctx = WebOperationContext.Current;

  List<SyndicationItem> items = new  List<SyndicationItem>();

  foreach  (Bookmark bm in  publicBookmarks)

  {

  SyndicationItem item = new  SyndicationItem(bm.Title, "", bm.Url,

  bm.Id.ToString(), new  DateTimeOffset(bm.LastModified));

  foreach  (string  c in  bm.Tags.Split(','))

  item.Categories.Add(new  SyndicationCategory(c));

  item.Authors.Add(new  SyndicationPerson("", bm.User, ""));

  items.Add(item);

  }  SyndicationFeed feed = new  SyndicationFeed()

  {

  Title = new  TextSyndicationContent("Public Bookmarks"),

  Id = ctx.IncomingRequest.UriTemplateMatch.RequestUri.ToString(),

  LastUpdatedTime = DateTime.Now,

  Items = items

  };

  if  (format.Equals("atom"))

  return new  Atom10FeedFormatter(feed);

  else

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 33/54

 

 

  return new  Rss20FeedFormatter(feed);

}

ServiceDocument HandleGetServiceDocument()

{

  List<ResourceCollectionInfo> collections = new  List<ResourceCollectionInfo>();

  collections.Add(new  ResourceCollectionInfo(

  new  TextSyndicationContent("Public Bookmarks"),

  GetPublicBookmarksFeedLink()));

  foreach  (string  user in  users.Keys)

  collections.Add(

  new  ResourceCollectionInfo(

  new  TextSyndicationContent(

  string.Format("Public Bookmarks by {0}", user)),

  GetUserBookmarksFeedLink(user)));

  List<Workspace> workspaces = new  List<Workspace>();

  workspaces.Add(new  Workspace(

  new  TextSyndicationContent("Contoso Bookmark Service"), collections));

  return new  ServiceDocument(workspaces);}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 34/54

if (!AuthenticateUser(username))

{

private bool  AuthenticateUser(string  user)

{

  WebOperationContext ctx = WebOperationContext.Current;

  string  requestUri = ctx.IncomingRequest.UriTemplateMatch.RequestUri.ToString();

  string  authHeader = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization];

  // if supplied hash is valid, user is authenticated

  if  (IsValidUserKey(authHeader, requestUri))

  return true;

  return false;}

public bool  IsValidUserKey(string  key, string  uri)

{

  string[] authParts = key.Split(':');

  if  (authParts.Length == 2)

  {

  string  userid = authParts[0];

  string  hash = authParts[1];

  if  (ValidateHash(userid, uri, hash))

  return true;

  }  return false;

}

bool  ValidateHash(string  userid, string  uri, string  hash)

{

  if  (!UserKeys.ContainsKey(userid))

  return false;

  string  userkey = UserKeys[userid];

  byte[] secretBytes = ASCIIEncoding.ASCII.GetBytes(userkey);

  HMACMD5 hmac = new  HMACMD5(secretBytes);

  byte[] dataBytes = ASCIIEncoding.ASCII.GetBytes(uri);

  byte[] computedHash = hmac.ComputeHash(dataBytes);  string  computedHashString = Convert.ToBase64String(computedHash);

  return  computedHashString.Equals(hash);

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 35/54

  WebOperationContext.Current.OutgoingResponse.StatusCode =

  HttpStatusCode.Unauthorized;

  return;

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 36/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 37/54

 

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 38/54

 

 

 

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 39/54

public class Bookmark

{

  public Uri Url { get; set; }

  public string User { get; set; }

  public string Title { get; set; }

  public string Tags { get; set; }

  public bool Public { get; set; }

  public DateTime LastModified { get; set; }

}

public class BookmarkItemInfo

{

  public Bookmark Bookmark { get; set; }

  public Uri Link { get; set; }

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 40/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 41/54

[ServiceBehavior(IncludeExceptionDetailInFaults = true,

  InstanceContextMode = InstanceContextMode.Single,  ConcurrencyMode = ConcurrencyMode.Single)]

[AspNetCompatibilityRequirements(

  RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

[ServiceContract]

public partial class  FeedService

{

  [WebGet(UriTemplate = "?numItems={i}")]

  [OperationContract]

  public  Atom10FeedFormatter GetFeed(int  i)

  {

  SyndicationFeed feed;  // TODO: Change the sample content feed creation logic here

  if  (i == 0) i = 1;

  // Create the list of syndication items. These correspond to Atom entries

  List<SyndicationItem> items = new  List<SyndicationItem>();

  for  (int  j = 1; j <= i; ++j)

  {

  items.Add(new  SyndicationItem()

  {

  // Every entry must have a stable unique URI id

  Id = String.Format(

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 42/54

  CultureInfo.InvariantCulture, "http://tmpuri.org/Id{0}", j),

  Title = new  TextSyndicationContent(

  String.Format("Sample item '{0}'", j)),

  // Every entry should include the last time it was updated

  LastUpdatedTime = new  DateTime(

  2008, 7, 1, 0, 0, 0, DateTimeKind.Utc),

  // The Atom spec requires an author for every entry.

  Authors =

  {

  new  SyndicationPerson()

  {

  Name = "Sample Author"

  }

  },

  // The content of an Atom entry can be text, xml, a link or

  // arbitrary content. In this sample text content is used.

  Content = new  TextSyndicationContent("Sample content"),

  });

  }

  // create the feed containing the syndication items.

  feed = new  SyndicationFeed()

  {

  // The feed must have a unique stable URI id

  Id = "http://tmpuri.org/FeedId",

  Title = new  TextSyndicationContent("Sample feed"),

  Items = items,

  Links =

  {

  // A feed should have a link to the service that produced the feed.

  GetSelfLink(),

  }

  };  WebOperationContext.Current.OutgoingResponse.ContentType = AtomContentType;

  return  feed.GetAtom10Formatter();

  }

  ...

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 43/54

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 44/54

public class BookmarksEDM : DataService< /* TODO: your data source class name */ >

{

  // This method is called only once to initialize service‐wide policies.

  public static void InitializeService(IDataServiceConfiguration config)

  {

  // TODO: set rules to indicate which entity sets are visible, updatable, etc.

  // Examples:

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 45/54

  // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);

  // config.SetServiceOperationAccessRule("MyServiceOperation",

  // ServiceOperationRights.All);

  }

}

public class BookmarksEDM : DataService<BookmarksModel.BookmarksEntities>

{

  public static void InitializeService(IDataServiceConfiguration config)

  {

  config.SetEntitySetAccessRule("Bookmarks", EntitySetRights.All);

  }

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 46/54

 

http://localhost:55555/BookmarksEDM.svc/Bookmarks?$filter=User%20eq%20'skonnard'

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 47/54

[DataServiceKey("Id")]

public class  Bookmark

{

  public string  Id { get; set; }

  public string  Url { get; set; }

  public string  User { get; set; }

  public string  Title { get; set; }

  public string  Tags { get; set; }

  public bool  Public { get; set; }

  public  DateTime LastModified { get; set; }

}

// this class replaces the EDM definition ‐ it provides an in‐memory data source

public class  BookmarkService

{

  static  List<Bookmark> bookmarks = new  List<Bookmark>();

  static  BookmarkService()

  {

  ... // initialize 'bookmarks' collection with a bunch of objects

  }

  public  IQueryable<Bookmark> Bookmarks  {

  get  { return  bookmarks.AsQueryable<Bookmark>(); }

  }

}

public class  BookmarkDataService : DataService<BookmarkService>

{

  public static void  InitializeService(IDataServiceConfiguration config)

  {

  config.SetEntitySetAccessRule("Bookmarks", EntitySetRights.All);

  }

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 48/54

if  (WScript.Arguments.length < 2)

{

  WScript.echo("Client HTTP Request Utility\n");

  WScript.echo("usage: httprequest method uri [options]");

  WScript.echo();

  WScript.echo(" ‐f filename");

  WScript.echo(" ‐h headerName headerValue");

  WScript.Quit(1);}

var  method = WScript.Arguments.Item(0);

var  uri = WScript.Arguments.Item(1);

var  req = new  ActiveXObject("MSXML2.XMLHTTP");

var  filename = null;

req.Open(method, uri, false);

WScript.echo();

WScript.echo("********* Request ********* ");

WScript.echo(method + " "  + uri + " HTTP/1.1");

for  (i=2; i < WScript.Arguments.length; i++)

{  var  option = WScript.Arguments.Item(i);

  if  (option == "‐f")

  filename = WScript.Arguments.Item(i+1);

  if  (option == "‐h")

  {

  WScript.echo(WScript.Arguments.Item(i+1) + ": "  +

  WScript.Arguments.Item(i+2));

  req.setRequestHeader(WScript.Arguments.Item(i+1),

  WScript.Arguments.Item(i+2));

  }

}try

{

  if  (filename != null)

  {

  WScript.echo();

  var  fso = new  ActiveXObject("Scripting.FileSystemObject");

  var  file = fso.OpenTextFile(filename, 1, false);

  var  fileContents = file.ReadAll();

  file.Close();

  WScript.echo(fileContents);

  req.Send(fileContents);

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 49/54

static void GetPublicBookmarks()

{

  string uri = "http://localhost:55555/bookmarkservice.svc/";

  HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest;

  HttpWebResponse resp = req.GetResponse() as HttpWebResponse;

  Bookmarks bookmarks = DeserializeBookmarks(resp.GetResponseStream());

  foreach (Bookmark bm in bookmarks)

  Console.WriteLine("{0}\r\n{1}\r\n", bm.Title, bm.Url);

}

  printResponse(req);

  }

  else

  {

  req.send();

  printResponse(req);

  }

}

catch(e)

{

  WScript.echo();

  WScript.echo("******* Response ********* ");

  WScript.echo(e.message);

}

function  printResponse(req)

{

  WScript.echo();

  WScript.echo("******* Response ********* ");

  WScript.echo("HTTP/1.1"  + " "  + req.status + " "  + req.statusText);

  var  headers = req.getAllResponseHeaders();

  WScript.echo(headers);

  WScript.echo(req.responseText);

}

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 50/54

[ServiceContract]

public interface IBookmarkService

{

  [WebGet(UriTemplate = "?tag={tag}")]

  [OperationContract]

  Bookmarks GetPublicBookmarks(string tag);

  ...

}

WebChannelFactory<IBookmarkService> cf = new  WebChannelFactory<IBookmarkService>(  new  Uri("http://localhost:55555/BookmarkService.svc" ));

IBookmarkService channel = cf.CreateChannel();

Bookmarks bms = channel.GetPublicBookmarks("WCF");

foreach  (Bookmark bm in  bms)

  Console.WriteLine("{0}\r\n{1}", bm.Title, bm.Url);

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 51/54

BookmarkService bookmarkService = new  BookmarkService(

  new  Uri("http://localhost:55555/Bookmarks.svc/"));

// this generates the following URL:

// http://localhost:55555/Bookmarks.svc/Bookmarks()?$filter=substringof('WCF',Tags)&// $orderby=LastModified

var  bookmarks = from  b in  bookmarkService.Bookmarks

  where  b.Tags.Contains("WCF")

  orderby  b.LastModified

  select  b;

foreach  (Bookmark bm in  bookmarks)

  Console.WriteLine("{0}\r\n{1}", bm.Title, bm.Url);

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 52/54

 

7/17/2019 A Guide to Designing and Building RESTful Web Services With WCF 3

http://slidepdf.com/reader/full/a-guide-to-designing-and-building-restful-web-services-with-wcf-3 53/54