Loading ...
Sorry, an error occurred while loading the content.

The "purist" C# REST client?

Expand Messages
  • Jørn Wildt
    There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking
    Message 1 of 12 , Dec 9, 2009
    • 0 Attachment
      There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example, and would like to discuss a similar typed approach in C#.
       
      I am experimenting with an actual implementation and would like some feedback before getting too far :-)
       
      Thanks, Jørn
       
      Service example documentation
      In order to discuss a REST client we need a service example. My first use case is a movie shop where we can search for movies in a specific category. To do so the shop has published a single search service URL template: http://movies.org/movies?category={category}.
       
      The shop also publishes three ressource mime types:
       
      // Example "application/vnd.movies.movie+xml"
      <Movie>
        <Self href="http://movies.org/movies/91"/>
        <Title>Strange Dawn</Title>
        <Category>Thriller</Category>
        <Director href="http://movies.org/persons/47"/>
      </Movie>
       
      // Example "application/vnd.movies.movie-collection+xml"
      <Movies>
        <Self href="http://movies.org/movies?category=Thriller"/>
        <Movie>
          <Title>Strange Dawn</Title>
          <Self href="http://movies.org/movies/91"/>
        </Movie>
        <Movie>...</Movie>
        <Movie>...</Movie>
      </Movies>
       
      // Example "application/vnd.movies.person+xml"
      <Person>
        <Self href="http://movies.org/persons/47"/>
        <Name>Richard Strangelove</Name>
        <Photo href="http://facebook.com/photos/hh31y1"/>
      </Person>
       
      Comments
       
      - I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer. You could although create your own serializer, so this is not an important restriction.
       
      - Notice how the person type has external references :-)
       
       
      Code example - Searching
      The cleanest client usage I can come up with is:
       
        // A link (template). This should be fetched from a configuration file.
        Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
       
        // Anonymous class with search parameters. Reflection is used to extract values.
        // This is about the simplest way to write a "fixed hashmap" in C#
        var movieSearchParameter = new { category = "Thriller" };
       
        // Get ressource stored at the link endpoint
        MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);
       
        // Iterate over all movies and print title
        foreach (Movie movie in movies)
          Console.WriteLine("Title: " + movie.Title);
      Comments:
       
      - A Link is untyped. We do not know what lies at the end of it.
       
      - A link knows how to merge parameters into URL templates.
       
      - The result of GETing a link is typed. The actual type is defined by the returned mime type.
       
      - In order to do something usefull with the search we must assume that it returns a MovieCollection. Hence the generic type specifier in the Get<T>() method. This is apriori information which I cannot see how to code without.
       
       
      Parsing ressources
      One piece of magic is how Get<MovieCollection>(params) knows how to convert the bytes returned from the endpoint to a MovieCollection. For this we create a MimeTypeRegistry:
       
        MimeTypeRegistry.Register<MovieCollection, MovieCollectionBuilder>("application/vnd.movies.movie-collection");
       
      which is equal to:
       
        MimeTypeRegistry.Register(typeof(MovieCollection), typeof(MovieCollectionBuilder), "application/vnd.movies.movie-collection");
       
      This means: when ever we must parse a specific mime type, we look up a builder in the registry and uses this to parse the returned ressource representation.
       
      The typed Get<MovieCollection>(params) method GETs the ressource data, instantiates the corresponding builder, verifies that the built object type matches the requested and returns the built object.
       
      Comments:
       
      - This is static typing which RESTafarians seems to shy away from. But the type depends on the returned ressource, _not_ the URL. So to my knowledge this is fine.
       
      - It is not required to use the type safe Get<T>(), you could also call Get() which returns an object. The actual returned type then depends solely on the mime type of the ressource, and it is up to the programmer to decide what to do with it.
       
      - I am quite sure you can write some pretty generic XML builders without much overhead.
       
      - This is not limited to XML, you could add image/jpeg and other well known mime types. You just need to supply a proper builder.
       
       
      Code example - Getting sub-ressources
      Now we want to get information about the director of the movie:
       
        // One of the returned self links from the search query
        Link movieLink = movies[0].Self;
       
        // Get the actual movie
        Movie movie = movieLink.Get<Movie>();
       
        // Get the director
        MoviePerson director = movie.Director.Get<MoviePerson>();
       
      Comments:
       
      - There are no hard coded links here.
       
      - The only apriori information we use is the knowledge of the types of the referenced ressources. These types are documented in the mime type in which the links are used.
       
       
      Versioning
      Now our wonderfull movie shop decides to be able to sell and rate movies. They do their own selling, but uses the fameous ratings.org service to rate their movies. So the shop creates a new version of the movie mime type:
       
      // Example "application/vnd.movies.movie.v2+xml"
      <Movie>
        <Self href="http://movies.org/movies/91"/>
        <Title>Strange Dawn</Title>
        <Category>Thriller</Category>
        <Director href="http://movies.org/persons/47"/>
        <Orders href="http://movies.org/movies/91/orders"/>
      </Movie>
       
      In order to service both old and new clients the shop decides to return the initial movie mime type by default. Never clients should use the Accept header to indicate that they want the new version. The same goes for the movies collection type.
       
      Our existing client code works happily as it did before.
       
       
      Code example - A new client
      The new client code would look like this:
       
        // A link (template). This should be fetched from a configuration file.
        Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
       
        // Anonymous class with search parameters. Reflection is used to extract values.
        // This is about the simplest way to write a "fixed hashmap" in C#
        var movieSearchParameter = new { category = "thriller" };
       
        // Setting up the Accept header
        var movieSearchHeaders = new { Accept = "application/vnd.movies.movie-collection.v2" }
       
        // Get ressource stored at the link endpoint
        MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter, movieSearchHeaders);
       
        // Iterate over all movies and print title
        foreach (Movie movie in movies)
          Console.WriteLine("Title: " + movie.Title);
       
      Code example - Buying movies
      Now we have a movie which has an embedded link to it's sales orders. To buy a movie we post a new order to the sales order collection:
       
        // One of the returned self links from the search query
        Link movieLink = movies[0].Self;
       
        // Get the actual movie
        Movie movie = movieLink.Get<Movie>();
       
        // Create a new order request
        MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /* quantity */);
       
        // Post the order request to the order collection
        // Assume it returns the newly created order
        MovieOrder order = movie.Orders.Post(orderRequest);
       
      Comments:
       
      - The POST result in a redirect to the newly created order. The system GETs this new order and returns it. This means we loose the intermediate data returned from the POST.
       
       
      Other verbs
      The Link class is has built-in support for GET/PUT/POST/DELETE. Other verbs can be executed through a generic "Request" method:
       
        SomeType x = someLink.Request("SOMEVERB", somePayload);
       
       
      Caching
      The Link class and it's associted methods should of course respect ETag and if-not-modified-since etc. This would require the framework to be initialized with a cache implementation of some kind.
       
       
      Error handling
      I would suggest using execptions for error handling.
       
       
    • mike amundsen
      Jørn: This line stands out first: I have avoided Atom Links since, in my experience, these don t serialize well in the C# standard XML serializer. My advice
      Message 2 of 12 , Dec 9, 2009
      • 0 Attachment
        Jørn:

        This line stands out first: "I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer."
        My advice is to be wary of serializers when coding for HTTP. There are so many variances with incoming responses I think you'll find it a real task to build apps based on  successfully converting incoming response bodies into code-able objects. Using serializers also tends to lead programmers to tight-binding between the code and the HTTP response body. This means changes in the body may blow the serializer code. This is especially true when working with "generic" media-types such as XML and JSON, etc. since they have very little semantic value built into them.

        That leads me to another bit of advice I'll offer: think about link semantics from the very start when creating your library. The Web browser client works because the link semantics of the HTML media-type are well-defined (and pretty narrow). There are a limited number of link elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are navigational links (A, FORM). All, except FORM, are limited to using the GET method. It's the semantic model of HTML that allows browsers to properly handle HTTP responses from previously unknown locations and still provide full functionality - even a decade after the semantics where defined. I suspect you'll find that building a client to properly locate, identify, and understand the link semantics of a single media type (application/vnd.movies.movie+xml) is challenging by itself. Building one that handles multiple media-types just adds to the fun<g>.

        I also encourage you to treat HTTP control data (headers) as top-level programming objects in your library. Allowing programmers to decorate requests with control data (content-encoding, media-type, authorization, cache-control, etc.) and have direct access to the control data on responses will improve the flexibility of any client/server built w/ your library.

        In the big picture, I prefer looking at HTTP programming from the stand-point of "resource programming." I look for a code library that lets me define a resource, associate or or more URIs with that resource, handle multiple representations of the resource (for both requests and response bodies), and properly decorate requests and responses w/ control data. I also want to make sure it handles mime-types properly (conneg included), conditional requests (GET and PUT), and supports flexible authentication models. 

        FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's been dormant for quite some time as the current version works well for me, but there are lots of places it needs work. I've also built an HTTP utilities library [2] with most all the bits I need for building REST-ful HTTP apps. It's smaller and lighter than my 'framework' library. I mention these as some of the code there might be helpful and/or act as a cautionary tale as you work on your own projects.




        On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@...> wrote:


        There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example, and would like to discuss a similar typed approach in C#.
         
        I am experimenting with an actual implementation and would like some feedback before getting too far :-)
         
        Thanks, Jørn
         
        Service example documentation
        In order to discuss a REST client we need a service example. My first use case is a movie shop where we can search for movies in a specific category. To do so the shop has published a single search service URL template: http://movies.org/movies?category={category}.
         
        The shop also publishes three ressource mime types:
         
        // Example "application/vnd.movies.movie+xml"
        <Movie>
          <Self href="http://movies.org/movies/91"/>
          <Title>Strange Dawn</Title>
          <Category>Thriller</Category>
          <Director href="http://movies.org/persons/47"/>
        </Movie>
         
        // Example "application/vnd.movies.movie-collection+xml"
        <Movies>
          <Movie>
            <Title>Strange Dawn</Title>
            <Self href="http://movies.org/movies/91"/>
          </Movie>
          <Movie>...</Movie>
          <Movie>...</Movie>
        </Movies>
         
        // Example "application/vnd.movies.person+xml"
        <Person>
          <Name>Richard Strangelove</Name>
        </Person>
         
        Comments
         
        - I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer. You could although create your own serializer, so this is not an important restriction.
         
        - Notice how the person type has external references :-)
         
         
        Code example - Searching
        The cleanest client usage I can come up with is:
         
          // A link (template). This should be fetched from a configuration file.
          Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
         
          // Anonymous class with search parameters. Reflection is used to extract values.
          // This is about the simplest way to write a "fixed hashmap" in C#
          var movieSearchParameter = new { category = "Thriller" };
         
          // Get ressource stored at the link endpoint
          MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);
         
          // Iterate over all movies and print title
          foreach (Movie movie in movies)
            Console.WriteLine("Title: " + movie.Title);
        Comments:
         
        - A Link is untyped. We do not know what lies at the end of it.
         
        - A link knows how to merge parameters into URL templates.
         
        - The result of GETing a link is typed. The actual type is defined by the returned mime type.
         
        - In order to do something usefull with the search we must assume that it returns a MovieCollection. Hence the generic type specifier in the Get<T>() method. This is apriori information which I cannot see how to code without.
         
         
        Parsing ressources
        One piece of magic is how Get<MovieCollection>(params) knows how to convert the bytes returned from the endpoint to a MovieCollection. For this we create a MimeTypeRegistry:
         
          MimeTypeRegistry.Register<MovieCollection, MovieCollectionBuilder>("application/vnd.movies.movie-collection");
         
        which is equal to:
         
          MimeTypeRegistry.Register(typeof(MovieCollection), typeof(MovieCollectionBuilder), "application/vnd.movies.movie-collection");
         
        This means: when ever we must parse a specific mime type, we look up a builder in the registry and uses this to parse the returned ressource representation.
         
        The typed Get<MovieCollection>(params) method GETs the ressource data, instantiates the corresponding builder, verifies that the built object type matches the requested and returns the built object.
         
        Comments:
         
        - This is static typing which RESTafarians seems to shy away from. But the type depends on the returned ressource, _not_ the URL. So to my knowledge this is fine.
         
        - It is not required to use the type safe Get<T>(), you could also call Get() which returns an object. The actual returned type then depends solely on the mime type of the ressource, and it is up to the programmer to decide what to do with it.
         
        - I am quite sure you can write some pretty generic XML builders without much overhead.
         
        - This is not limited to XML, you could add image/jpeg and other well known mime types. You just need to supply a proper builder.
         
         
        Code example - Getting sub-ressources
        Now we want to get information about the director of the movie:
         
          // One of the returned self links from the search query
          Link movieLink = movies[0].Self;
         
          // Get the actual movie
          Movie movie = movieLink.Get<Movie>();
         
          // Get the director
          MoviePerson director = movie.Director.Get<MoviePerson>();
         
        Comments:
         
        - There are no hard coded links here.
         
        - The only apriori information we use is the knowledge of the types of the referenced ressources. These types are documented in the mime type in which the links are used.
         
         
        Versioning
        Now our wonderfull movie shop decides to be able to sell and rate movies. They do their own selling, but uses the fameous ratings.org service to rate their movies. So the shop creates a new version of the movie mime type:
         
        // Example "application/vnd.movies.movie.v2+xml"
        <Movie>
          <Self href="http://movies.org/movies/91"/>
          <Title>Strange Dawn</Title>
          <Category>Thriller</Category>
          <Director href="http://movies.org/persons/47"/>
        </Movie>
         
        In order to service both old and new clients the shop decides to return the initial movie mime type by default. Never clients should use the Accept header to indicate that they want the new version. The same goes for the movies collection type.
         
        Our existing client code works happily as it did before.
         
         
        Code example - A new client
        The new client code would look like this:
         
          // A link (template). This should be fetched from a configuration file.
          Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
         
          // Anonymous class with search parameters. Reflection is used to extract values.
          // This is about the simplest way to write a "fixed hashmap" in C#
          var movieSearchParameter = new { category = "thriller" };
         
          // Setting up the Accept header
          var movieSearchHeaders = new { Accept = "application/vnd.movies.movie-collection.v2" }
         
          // Get ressource stored at the link endpoint
          MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter, movieSearchHeaders);
         
          // Iterate over all movies and print title
          foreach (Movie movie in movies)
            Console.WriteLine("Title: " + movie.Title);
         
        Code example - Buying movies
        Now we have a movie which has an embedded link to it's sales orders. To buy a movie we post a new order to the sales order collection:
         
          // One of the returned self links from the search query
          Link movieLink = movies[0].Self;
         
          // Get the actual movie
          Movie movie = movieLink.Get<Movie>();
         
          // Create a new order request
          MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /* quantity */);
         
          // Post the order request to the order collection
          // Assume it returns the newly created order
          MovieOrder order = movie.Orders.Post(orderRequest);
         
        Comments:
         
        - The POST result in a redirect to the newly created order. The system GETs this new order and returns it. This means we loose the intermediate data returned from the POST.
         
         
        Other verbs
        The Link class is has built-in support for GET/PUT/POST/DELETE. Other verbs can be executed through a generic "Request" method:
         
          SomeType x = someLink.Request("SOMEVERB", somePayload);
         
         
        Caching
        The Link class and it's associted methods should of course respect ETag and if-not-modified-since etc. This would require the framework to be initialized with a cache implementation of some kind.
         
         
        Error handling
        I would suggest using execptions for error handling.
         
         



      • Will Hartung
        Just a couple of thoughts out loud. I like the mime-type mapping framework, that would be a nice, generic piece of code all on its own, and it should marshal
        Message 3 of 12 , Dec 9, 2009
        • 0 Attachment
          Just a couple of thoughts out loud.

          I like the mime-type mapping framework, that would be a nice, generic piece of code all on its own, and it should marshal both ways.

          I think you will need to use that in many places. Not simply for GETs, but for pushing data as well.

          But another place that would be valuable is the fact that most any HTTP result can have a typed body. So it's easy to envision when you get some warning, or other error message (perhaps a redirect), that you can leverage the ability to send more interesting data than what is simply in the headers, and have that data marshaled for you automagically.

          I think the LINK infrastructure should be aware of things like redirects, and expose those things. If you hit a URI that gets a permanent or temporary redirect, it would be nice for the client to honor that at least somewhat transparently. And by that I don't me silently following the redirect, but I mean if it sees you hitting it again, will simply jump straight to the final destination.

          For the trivial case, I don't see a reason why you should be having to set the Accept header -- framework should do that for you. It should set the content type on the way out properly, and set the accept header as well, since it "knows" you want the Movie info.

          The common headers should be First Class. I shouldn't have to set an "If-Modified" myself, I should be able to link.setIfModifiedSince(myDate), so I don't have to marshal the dates myself.

          Going back to the mime mapping, that should be controllable at a higher, "global"/framework level, but also at the request level. I can easily see having to map "text/xml" to something different at the request level depending on the link.

          So, anyway, just some quick thoughts.

          Regards,

          Will Hartung
          (willh@...)


        • Steve Bjorg
          Mike, It sounds like your library is quite similar to the one we developed for our application as well. MindTouch Dream [1] is a .NET framework for building
          Message 4 of 12 , Dec 9, 2009
          • 0 Attachment
            Mike,

            It sounds like your library is quite similar to the one we developed for our application as well.  MindTouch Dream [1] is a .NET framework for building portable web-services that can run as a standalone process, windows service, or natively under IIS.  It also runs under Linux using Mono.  Dream is used by quite a few sites including Mozilla [2], Novell [3], and Washington Post [4].  The license is Apache 2.0 for easy reuse.

            It's quite fun to build an entire application with a RESTful interface. :)


            On Dec 9, 2009, at 2:58 PM, mike amundsen wrote:

             

            Jørn:

            This line stands out first: "I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer."
            My advice is to be wary of serializers when coding for HTTP. There are so many variances with incoming responses I think you'll find it a real task to build apps based on  successfully converting incoming response bodies into code-able objects. Using serializers also tends to lead programmers to tight-binding between the code and the HTTP response body. This means changes in the body may blow the serializer code. This is especially true when working with "generic" media-types such as XML and JSON, etc. since they have very little semantic value built into them.

            That leads me to another bit of advice I'll offer: think about link semantics from the very start when creating your library. The Web browser client works because the link semantics of the HTML media-type are well-defined (and pretty narrow). There are a limited number of link elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are navigational links (A, FORM). All, except FORM, are limited to using the GET method. It's the semantic model of HTML that allows browsers to properly handle HTTP responses from previously unknown locations and still provide full functionality - even a decade after the semantics where defined. I suspect you'll find that building a client to properly locate, identify, and understand  the link semantics of a single media type (application/ vnd.movies. movie+xml) is challenging by itself. Building one that handles multiple media-types just adds to the fun<g>.

            I also encourage you to treat HTTP control data (headers) as top-level programming objects in your library. Allowing programmers to decorate requests with control data (content-encoding, media-type, authorization, cache-control, etc.) and have direct access to the control data on responses will improve the flexibility of any client/server built w/ your library.

            In the big picture, I prefer looking at HTTP programming from the stand-point of "resource programming." I look for a code library that lets me define a resource, associate or or more URIs with that resource, handle multiple representations of the resource (for both requests and response bodies), and properly decorate requests and responses w/ control data. I also want to make sure it handles mime-types properly (conneg included), conditional requests (GET and PUT), and supports flexible authentication models. 

            FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's been dormant for quite some time as the current version works well for me, but there are lots of places it needs work. I've also built an HTTP utilities library [2] with most all the bits I need for building REST-ful HTTP apps. It's smaller and lighter than my 'framework' library. I mention these as some of the code there might be helpful and/or act as a cautionary tale as you work on your own projects.




            On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@fjeldgruppen. dk> wrote:


            There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking at RESTFulie[1] , Subbu Alamarju[2], and the Starbucks[3] example, and would like to discuss a similar typed approach in C#.
             
            I am experimenting with an actual implementation and would like some feedback before getting too far :-)
             
            Thanks, Jørn
             
            Service example documentation
            In order to discuss a REST client we need a service example. My first use case is a movie shop where we can search for movies in a specific category. To do so the shop has published a single search service URL template: http://movies. org/movies? category= {category}.
             
            The shop also publishes three ressource mime types:
             
            // Example "application/ vnd.movies. movie+xml"
            <Movie>
              <Title>Strange Dawn</Title>
              <Category>Thriller</Category>
              <Director href="http://movies. org/persons/ 47"/>
            </Movie>
             
            // Example "application/ vnd.movies. movie-collection +xml"
            <Movies>
              <Movie>
                <Title>Strange Dawn</Title>
                <Self href="http://movies. org/movies/ 91"/>
              </Movie>
              <Movie>...</Movie>
              <Movie>...</Movie>
            </Movies>
             
            // Example "application/ vnd.movies. person+xml"
            <Person>
              <Name>Richard Strangelove</Name>
            </Person>
             
            Comments
             
            - I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer. You could although create your own serializer, so this is not an important restriction.
             
            - Notice how the person type has external references :-)
             
             
            Code example - Searching
            The cleanest client usage I can come up with is:
             
              // A link (template). This should be fetched from a configuration file.
              Link MoviesSearchLink = new Link("http://movies. org/movies? category= {category}");
             
              // Anonymous class with search parameters. Reflection is used to extract values.
              // This is about the simplest way to write a "fixed hashmap" in C#
              var movieSearchParamete r = new { category = "Thriller" };
             
              // Get ressource stored at the link endpoint
              MovieCollection movies = MoviesSearchLink. Get<MovieCollection>(movieSearchParamet er);
             
              // Iterate over all movies and print title
              foreach (Movie movie in movies)
                Console.WriteLine("Title: " + movie.Title) ;
            Comments:
             
            - A Link is untyped. We do not know what lies at the end of it.
             
            - A link knows how to merge parameters into URL templates.
             
            - The result of GETing a link is typed. The actual type is defined by the returned mime type.
             
            - In order to do something usefull with the search we must assume that it returns a MovieCollection. Hence the generic type specifier in the Get<T>() method. This is apriori information which I cannot see how to code without.
             
             
            Parsing ressources
            One piece of magic is how Get<MovieCollection>(params) knows how to convert the bytes returned from the endpoint to a MovieCollection. For this we create a MimeTypeRegistry:
             
              MimeTypeRegistry. Register<MovieCollection, MovieCollectionBuil der>("application/ vnd.movies. movie-collection");
             
            which is equal to:
             
              MimeTypeRegistry. Register( typeof(MovieColl ection), typeof(MovieCollect ionBuilder) , "application/ vnd.movies. movie-collection");
             
            This means: when ever we must parse a specific mime type, we look up a builder in the registry and uses this to parse the returned ressource representation.
             
            The typed Get<MovieCollection>(params) method GETs the ressource data, instantiates the corresponding builder, verifies that the built object type matches the requested and returns the built object.
             
            Comments:
             
            - This is static typing which RESTafarians seems to shy away from. But the type depends on the returned ressource, _not_ the URL. So to my knowledge this is fine.
             
            - It is not required to use the type safe Get<T>(), you could also call Get() which returns an object. The actual returned type then depends solely on the mime type of the ressource, and it is up to the programmer to decide what to do with it.
             
            - I am quite sure you can write some pretty generic XML builders without much overhead.
             
            - This is not limited to XML, you could add image/jpeg and other well known mime types. You just need to supply a proper builder.
             
             
            Code example - Getting sub-ressources
            Now we want to get information about the director of the movie:
             
              // One of the returned self links from the search query
              Link movieLink = movies[0].Self;
             
              // Get the actual movie
              Movie movie = movieLink.Get<Movie>();
             
              // Get the director
              MoviePerson director = movie.Director. Get<MoviePerson>();
             
            Comments:
             
            - There are no hard coded links here.
             
            - The only apriori information we use is the knowledge of the types of the referenced ressources. These types are documented in the mime type in which the links are used.
             
             
            Versioning
            Now our wonderfull movie shop decides to be able to sell and rate movies. They do their own selling, but uses the fameous ratings.org service to rate their movies. So the shop creates a new version of the movie mime type:
             
            // Example "application/ vnd.movies. movie.v2+xml"
            <Movie>
              <Title>Strange Dawn</Title>
              <Category>Thriller</Category>
              <Director href="http://movies. org/persons/ 47"/>
            </Movie>
             
            In order to service both old and new clients the shop decides to return the initial movie mime type by default. Never clients should use the Accept header to indicate that they want the new version. The same goes for the movies collection type.
             
            Our existing client code works happily as it did before.
             
             
            Code example - A new client
            The new client code would look like this:
             
              // A link (template). This should be fetched from a configuration file.
              Link MoviesSearchLink = new Link("http://movies. org/movies? category= {category}");
             
              // Anonymous class with search parameters. Reflection is used to extract values.
              // This is about the simplest way to write a "fixed hashmap" in C#
              var movieSearchParamete r = new { category = "thriller" };
             
              // Setting up the Accept header
              var movieSearchHeaders = new { Accept = "application/ vnd.movies. movie-collection .v2" }
             
              // Get ressource stored at the link endpoint
              MovieCollection movies = MoviesSearchLink. Get<MovieCollection>(movieSearchParamet er, movieSearchHeaders) ;
             
              // Iterate over all movies and print title
              foreach (Movie movie in movies)
                Console.WriteLine("Title: " + movie.Title) ;
             
            Code example - Buying movies
            Now we have a movie which has an embedded link to it's sales orders. To buy a movie we post a new order to the sales order collection:
             
              // One of the returned self links from the search query
              Link movieLink = movies[0].Self;
             
              // Get the actual movie
              Movie movie = movieLink.Get<Movie>();
             
              // Create a new order request
              MovieOrderRequest orderRequest = new MovieOrderRequest( movie.Self, 1 /* quantity */);
             
              // Post the order request to the order collection
              // Assume it returns the newly created order
              MovieOrder order = movie.Orders. Post(orderReques t);
             
            Comments:
             
            - The POST result in a redirect to the newly created order. The system GETs this new order and returns it. This means we loose the intermediate data returned from the POST.
             
             
            Other verbs
            The Link class is has built-in support for GET/PUT/POST/ DELETE. Other verbs can be executed through a generic "Request" method:
             
              SomeType x = someLink.Request("SOMEVERB", somePayload) ;
             
             
            Caching
            The Link class and it's associted methods should of course respect ETag and if-not-modified- since etc. This would require the framework to be initialized with a cache implementation of some kind.
             
             
            Error handling
            I would suggest using execptions for error handling.
             
             





          • mike amundsen
            Steve: i ve poked around in your code, then ! mca http://amundsen.com/blog/ ... Steve: i ve poked around in your code, then ! mca http://amundsen.com/blog/
            Message 5 of 12 , Dec 9, 2009
            • 0 Attachment
              Steve:

              i've poked around in your code, then<g>!

              mca
              http://amundsen.com/blog/



              On Wed, Dec 9, 2009 at 19:20, Steve Bjorg <steveb@...> wrote:
              Mike,

              It sounds like your library is quite similar to the one we developed for our application as well.  MindTouch Dream [1] is a .NET framework for building portable web-services that can run as a standalone process, windows service, or natively under IIS.  It also runs under Linux using Mono.  Dream is used by quite a few sites including Mozilla [2], Novell [3], and Washington Post [4].  The license is Apache 2.0 for easy reuse.

              It's quite fun to build an entire application with a RESTful interface. :)


              On Dec 9, 2009, at 2:58 PM, mike amundsen wrote:

               

              Jørn:

              This line stands out first: "I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer."
              My advice is to be wary of serializers when coding for HTTP. There are so many variances with incoming responses I think you'll find it a real task to build apps based on  successfully converting incoming response bodies into code-able objects. Using serializers also tends to lead programmers to tight-binding between the code and the HTTP response body. This means changes in the body may blow the serializer code. This is especially true when working with "generic" media-types such as XML and JSON, etc. since they have very little semantic value built into them.

              That leads me to another bit of advice I'll offer: think about link semantics from the very start when creating your library. The Web browser client works because the link semantics of the HTML media-type are well-defined (and pretty narrow). There are a limited number of link elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are navigational links (A, FORM). All, except FORM, are limited to using the GET method. It's the semantic model of HTML that allows browsers to properly handle HTTP responses from previously unknown locations and still provide full functionality - even a decade after the semantics where defined. I suspect you'll find that building a client to properly locate, identify, and understand the link semantics of a single media type (application/vnd.movies.movie+xml) is challenging by itself. Building one that handles multiple media-types just adds to the fun<g>.

              I also encourage you to treat HTTP control data (headers) as top-level programming objects in your library. Allowing programmers to decorate requests with control data (content-encoding, media-type, authorization, cache-control, etc.) and have direct access to the control data on responses will improve the flexibility of any client/server built w/ your library.

              In the big picture, I prefer looking at HTTP programming from the stand-point of "resource programming." I look for a code library that lets me define a resource, associate or or more URIs with that resource, handle multiple representations of the resource (for both requests and response bodies), and properly decorate requests and responses w/ control data. I also want to make sure it handles mime-types properly (conneg included), conditional requests (GET and PUT), and supports flexible authentication models. 

              FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's been dormant for quite some time as the current version works well for me, but there are lots of places it needs work. I've also built an HTTP utilities library [2] with most all the bits I need for building REST-ful HTTP apps. It's smaller and lighter than my 'framework' library. I mention these as some of the code there might be helpful and/or act as a cautionary tale as you work on your own projects.




              On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@...> wrote:


              There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example, and would like to discuss a similar typed approach in C#.
               
              I am experimenting with an actual implementation and would like some feedback before getting too far :-)
               
              Thanks, Jørn
               
              Service example documentation
              In order to discuss a REST client we need a service example. My first use case is a movie shop where we can search for movies in a specific category. To do so the shop has published a single search service URL template: http://movies.org/movies?category={category}.
               
              The shop also publishes three ressource mime types:
               
              // Example "application/vnd.movies.movie+xml"
              <Movie>
                <Self href="http://movies.org/movies/91"/>
                <Title>Strange Dawn</Title>
                <Category>Thriller</Category>
                <Director href="http://movies.org/persons/47"/>
              </Movie>
               
              // Example "application/vnd.movies.movie-collection+xml"
              <Movies>
                <Movie>
                  <Title>Strange Dawn</Title>
                  <Self href="http://movies.org/movies/91"/>
                </Movie>
                <Movie>...</Movie>
                <Movie>...</Movie>
              </Movies>
               
              // Example "application/vnd.movies.person+xml"
              <Person>
                <Name>Richard Strangelove</Name>
              </Person>
               
              Comments
               
              - I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer. You could although create your own serializer, so this is not an important restriction.
               
              - Notice how the person type has external references :-)
               
               
              Code example - Searching
              The cleanest client usage I can come up with is:
               
                // A link (template). This should be fetched from a configuration file.
                Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
               
                // Anonymous class with search parameters. Reflection is used to extract values.
                // This is about the simplest way to write a "fixed hashmap" in C#
                var movieSearchParameter = new { category = "Thriller" };
               
                // Get ressource stored at the link endpoint
                MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);
               
                // Iterate over all movies and print title
                foreach (Movie movie in movies)
                  Console.WriteLine("Title: " + movie.Title);
              Comments:
               
              - A Link is untyped. We do not know what lies at the end of it.
               
              - A link knows how to merge parameters into URL templates.
               
              - The result of GETing a link is typed. The actual type is defined by the returned mime type.
               
              - In order to do something usefull with the search we must assume that it returns a MovieCollection. Hence the generic type specifier in the Get<T>() method. This is apriori information which I cannot see how to code without.
               
               
              Parsing ressources
              One piece of magic is how Get<MovieCollection>(params) knows how to convert the bytes returned from the endpoint to a MovieCollection. For this we create a MimeTypeRegistry:
               
                MimeTypeRegistry.Register<MovieCollection, MovieCollectionBuilder>("application/vnd.movies.movie-collection");
               
              which is equal to:
               
                MimeTypeRegistry.Register(typeof(MovieCollection), typeof(MovieCollectionBuilder), "application/vnd.movies.movie-collection");
               
              This means: when ever we must parse a specific mime type, we look up a builder in the registry and uses this to parse the returned ressource representation.
               
              The typed Get<MovieCollection>(params) method GETs the ressource data, instantiates the corresponding builder, verifies that the built object type matches the requested and returns the built object.
               
              Comments:
               
              - This is static typing which RESTafarians seems to shy away from. But the type depends on the returned ressource, _not_ the URL. So to my knowledge this is fine.
               
              - It is not required to use the type safe Get<T>(), you could also call Get() which returns an object. The actual returned type then depends solely on the mime type of the ressource, and it is up to the programmer to decide what to do with it.
               
              - I am quite sure you can write some pretty generic XML builders without much overhead.
               
              - This is not limited to XML, you could add image/jpeg and other well known mime types. You just need to supply a proper builder.
               
               
              Code example - Getting sub-ressources
              Now we want to get information about the director of the movie:
               
                // One of the returned self links from the search query
                Link movieLink = movies[0].Self;
               
                // Get the actual movie
                Movie movie = movieLink.Get<Movie>();
               
                // Get the director
                MoviePerson director = movie.Director.Get<MoviePerson>();
               
              Comments:
               
              - There are no hard coded links here.
               
              - The only apriori information we use is the knowledge of the types of the referenced ressources. These types are documented in the mime type in which the links are used.
               
               
              Versioning
              Now our wonderfull movie shop decides to be able to sell and rate movies. They do their own selling, but uses the fameous ratings.org service to rate their movies. So the shop creates a new version of the movie mime type:
               
              // Example "application/vnd.movies.movie.v2+xml"
              <Movie>
                <Self href="http://movies.org/movies/91"/>
                <Title>Strange Dawn</Title>
                <Category>Thriller</Category>
                <Director href="http://movies.org/persons/47"/>
              </Movie>
               
              In order to service both old and new clients the shop decides to return the initial movie mime type by default. Never clients should use the Accept header to indicate that they want the new version. The same goes for the movies collection type.
               
              Our existing client code works happily as it did before.
               
               
              Code example - A new client
              The new client code would look like this:
               
                // A link (template). This should be fetched from a configuration file.
                Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");
               
                // Anonymous class with search parameters. Reflection is used to extract values.
                // This is about the simplest way to write a "fixed hashmap" in C#
                var movieSearchParameter = new { category = "thriller" };
               
                // Setting up the Accept header
                var movieSearchHeaders = new { Accept = "application/vnd.movies.movie-collection.v2" }
               
                // Get ressource stored at the link endpoint
                MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter, movieSearchHeaders);
               
                // Iterate over all movies and print title
                foreach (Movie movie in movies)
                  Console.WriteLine("Title: " + movie.Title);
               
              Code example - Buying movies
              Now we have a movie which has an embedded link to it's sales orders. To buy a movie we post a new order to the sales order collection:
               
                // One of the returned self links from the search query
                Link movieLink = movies[0].Self;
               
                // Get the actual movie
                Movie movie = movieLink.Get<Movie>();
               
                // Create a new order request
                MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /* quantity */);
               
                // Post the order request to the order collection
                // Assume it returns the newly created order
                MovieOrder order = movie.Orders.Post(orderRequest);
               
              Comments:
               
              - The POST result in a redirect to the newly created order. The system GETs this new order and returns it. This means we loose the intermediate data returned from the POST.
               
               
              Other verbs
              The Link class is has built-in support for GET/PUT/POST/DELETE. Other verbs can be executed through a generic "Request" method:
               
                SomeType x = someLink.Request("SOMEVERB", somePayload);
               
               
              Caching
              The Link class and it's associted methods should of course respect ETag and if-not-modified-since etc. This would require the framework to be initialized with a cache implementation of some kind.
               
               
              Error handling
              I would suggest using execptions for error handling.
               
               






            • Sebastien Lambla
              Well as we’re in the middle of citing the .net solutions helping for ReST architectures, may as well talk about www.openrasta.com. It’s used by many OSS
              Message 6 of 12 , Dec 10, 2009
              • 0 Attachment

                Well as we’re in the middle of citing the .net solutions helping for ReST architectures, may as well talk about www.openrasta.com. It’s used by many OSS developers, but as it’s not a commercial tool as such, I don’t have links to give you that I have the right to publish :) It’s MIT license, it runs on IIS, windows service, standalone process, in-memory, and there’s even a branch running in Silverlight.

                 

                Judging from only google, I’ll happily declare we’re the most talked about OSS ReST/HTTP focused server framework on .net. Ah the joys of marketing!

                 

                There’s a client library in the pipeline, that reuses the extensible pipeline and codecs existing in the server framework, but that won’t happen for a few iterations.

                 

                To go back to your point, I second what Mike is saying: Define your media type by studying your link relationships. A lot can happen in your user-agent when you react to certain link types or certain media types, making the application very interactive.

                 

                And I’ll also say what I said before: versioning through the media type shouldn’t be a habit, you only need versioning of your document types when you’re restricting yourself to xml serializers, or worse, add schema enforcing through xsd. If you remove those restrictions and simply try to parse just what is needed from an xml feed for an operation to succeed, everything will become much much easier.

                 

                Seb

                 

                 

                 

                From: rest-discuss@yahoogroups.com [mailto:rest-discuss@yahoogroups.com] On Behalf Of Steve Bjorg
                Sent: 10 December 2009 00:20
                To: mike amundsen
                Cc: Jørn Wildt; rest-discuss
                Subject: Re: [rest-discuss] The "purist" C# REST client?

                 




                Mike,

                 

                It sounds like your library is quite similar to the one we developed for our application as well.  MindTouch Dream [1] is a .NET framework for building portable web-services that can run as a standalone process, windows service, or natively under IIS.  It also runs under Linux using Mono.  Dream is used by quite a few sites including Mozilla [2], Novell [3], and Washington Post [4].  The license is Apache 2.0 for easy reuse.

                 

                It's quite fun to build an entire application with a RESTful interface. :)

                 

                 

                On Dec 9, 2009, at 2:58 PM, mike amundsen wrote:



                 

                 

                Jørn:

                 

                This line stands out first: "I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer."

                My advice is to be wary of serializers when coding for HTTP. There are so many variances with incoming responses I think you'll find it a real task to build apps based on  successfully converting incoming response bodies into code-able objects. Using serializers also tends to lead programmers to tight-binding between the code and the HTTP response body. This means changes in the body may blow the serializer code. This is especially true when working with "generic" media-types such as XML and JSON, etc. since they have very little semantic value built into them.

                 

                That leads me to another bit of advice I'll offer: think about link semantics from the very start when creating your library. The Web browser client works because the link semantics of the HTML media-type are well-defined (and pretty narrow). There are a limited number of link elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are navigational links (A, FORM). All, except FORM, are limited to using the GET method. It's the semantic model of HTML that allows browsers to properly handle HTTP responses from previously unknown locations and still provide full functionality - even a decade after the semantics where defined. I suspect you'll find that building a client to properly locate, identify, and understand the link semantics of a single media type (application/vnd.movies.movie+xml) is challenging by itself. Building one that handles multiple media-types just adds to the fun<g>.

                 

                I also encourage you to treat HTTP control data (headers) as top-level programming objects in your library. Allowing programmers to decorate requests with control data (content-encoding, media-type, authorization, cache-control, etc.) and have direct access to the control data on responses will improve the flexibility of any client/server built w/ your library.

                 

                In the big picture, I prefer looking at HTTP programming from the stand-point of "resource programming." I look for a code library that lets me define a resource, associate or or more URIs with that resource, handle multiple representations of the resource (for both requests and response bodies), and properly decorate requests and responses w/ control data. I also want to make sure it handles mime-types properly (conneg included), conditional requests (GET and PUT), and supports flexible authentication models. 

                 

                FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's been dormant for quite some time as the current version works well for me, but there are lots of places it needs work. I've also built an HTTP utilities library [2] with most all the bits I need for building REST-ful HTTP apps. It's smaller and lighter than my 'framework' library. I mention these as some of the code there might be helpful and/or act as a cautionary tale as you work on your own projects.

                 


                On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@...> wrote:

                 

                There has been a lot of discussion about the right way to implement a REST service, but less focus on how you would actually code a client. I have been looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example, and would like to discuss a similar typed approach in C#.

                 

                I am experimenting with an actual implementation and would like some feedback before getting too far :-)

                 

                Thanks, Jørn

                 

                 

                [1] http://github.com/caelum/restfulie

                [2] http://www.infoq.com/articles/subbu-allamaraju-rest

                 

                 

                Service example documentation

                In order to discuss a REST client we need a service example. My first use case is a movie shop where we can search for movies in a specific category. To do so the shop has published a single search service URL template: http://movies.org/movies?category={category}.

                 

                The shop also publishes three ressource mime types:

                 

                // Example "application/vnd.movies.movie+xml"

                <Movie>

                  <Self href="http://movies.org/movies/91"/>

                  <Title>Strange Dawn</Title>

                  <Category>Thriller</Category>

                  <Director href="http://movies.org/persons/47"/>

                </Movie>

                 

                // Example "application/vnd.movies.movie-collection+xml"

                <Movies>

                  <Movie>

                    <Title>Strange Dawn</Title>

                    <Self href="http://movies.org/movies/91"/>

                  </Movie>

                  <Movie>...</Movie>

                  <Movie>...</Movie>

                </Movies>

                 

                // Example "application/vnd.movies.person+xml"

                <Person>

                  <Name>Richard Strangelove</Name>

                </Person>

                 

                Comments

                 

                - I have avoided Atom Links since, in my experience, these don't serialize well in the C# standard XML serializer. You could although create your own serializer, so this is not an important restriction.

                 

                - Notice how the person type has external references :-)

                 

                 

                Code example - Searching

                The cleanest client usage I can come up with is:

                 

                  // A link (template). This should be fetched from a configuration file.

                  Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");

                 

                  // Anonymous class with search parameters. Reflection is used to extract values.

                  // This is about the simplest way to write a "fixed hashmap" in C#

                  var movieSearchParameter = new { category = "Thriller" };

                 

                  // Get ressource stored at the link endpoint

                  MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);

                 

                  // Iterate over all movies and print title

                  foreach (Movie movie in movies)

                    Console.WriteLine("Title: " + movie.Title);

                Comments:

                 

                - A Link is untyped. We do not know what lies at the end of it.

                 

                - A link knows how to merge parameters into URL templates.

                 

                - The result of GETing a link is typed. The actual type is defined by the returned mime type.

                 

                - In order to do something usefull with the search we must assume that it returns a MovieCollection. Hence the generic type specifier in the Get<T>() method. This is apriori information which I cannot see how to code without.

                 

                 

                Parsing ressources

                One piece of magic is how Get<MovieCollection>(params) knows how to convert the bytes returned from the endpoint to a MovieCollection. For this we create a MimeTypeRegistry:

                 

                  MimeTypeRegistry.Register<MovieCollection, MovieCollectionBuilder>("application/vnd.movies.movie-collection");

                 

                which is equal to:

                 

                  MimeTypeRegistry.Register(typeof(MovieCollection), typeof(MovieCollectionBuilder), "application/vnd.movies.movie-collection");

                 

                This means: when ever we must parse a specific mime type, we look up a builder in the registry and uses this to parse the returned ressource representation.

                 

                The typed Get<MovieCollection>(params) method GETs the ressource data, instantiates the corresponding builder, verifies that the built object type matches the requested and returns the built object.

                 

                Comments:

                 

                - This is static typing which RESTafarians seems to shy away from. But the type depends on the returned ressource, _not_ the URL. So to my knowledge this is fine.

                 

                - It is not required to use the type safe Get<T>(), you could also call Get() which returns an object. The actual returned type then depends solely on the mime type of the ressource, and it is up to the programmer to decide what to do with it.

                 

                - I am quite sure you can write some pretty generic XML builders without much overhead.

                 

                - This is not limited to XML, you could add image/jpeg and other well known mime types. You just need to supply a proper builder.

                 

                 

                Code example - Getting sub-ressources

                Now we want to get information about the director of the movie:

                 

                  // One of the returned self links from the search query

                  Link movieLink = movies[0].Self;

                 

                  // Get the actual movie

                  Movie movie = movieLink.Get<Movie>();

                 

                  // Get the director

                  MoviePerson director = movie.Director.Get<MoviePerson>();

                 

                Comments:

                 

                - There are no hard coded links here.

                 

                - The only apriori information we use is the knowledge of the types of the referenced ressources. These types are documented in the mime type in which the links are used.

                 

                 

                Versioning

                Now our wonderfull movie shop decides to be able to sell and rate movies. They do their own selling, but uses the fameous ratings.org service to rate their movies. So the shop creates a new version of the movie mime type:

                 

                // Example "application/vnd.movies.movie.v2+xml"

                <Movie>

                  <Self href="http://movies.org/movies/91"/>

                  <Title>Strange Dawn</Title>

                  <Category>Thriller</Category>

                  <Director href="http://movies.org/persons/47"/>

                </Movie>

                 

                In order to service both old and new clients the shop decides to return the initial movie mime type by default. Never clients should use the Accept header to indicate that they want the new version. The same goes for the movies collection type.

                 

                Our existing client code works happily as it did before.

                 

                 

                Code example - A new client

                The new client code would look like this:

                 

                  // A link (template). This should be fetched from a configuration file.

                  Link MoviesSearchLink = new Link("http://movies.org/movies?category={category}");

                 

                  // Anonymous class with search parameters. Reflection is used to extract values.

                  // This is about the simplest way to write a "fixed hashmap" in C#

                  var movieSearchParameter = new { category = "thriller" };

                 

                  // Setting up the Accept header

                  var movieSearchHeaders = new { Accept = "application/vnd.movies.movie-collection.v2" }

                 

                  // Get ressource stored at the link endpoint

                  MovieCollection movies = MoviesSearchLink.Get<MovieCollection>(movieSearchParameter, movieSearchHeaders);

                 

                  // Iterate over all movies and print title

                  foreach (Movie movie in movies)

                    Console.WriteLine("Title: " + movie.Title);

                 

                Code example - Buying movies

                Now we have a movie which has an embedded link to it's sales orders. To buy a movie we post a new order to the sales order collection:

                 

                  // One of the returned self links from the search query

                  Link movieLink = movies[0].Self;

                 

                  // Get the actual movie

                  Movie movie = movieLink.Get<Movie>();

                 

                  // Create a new order request

                  MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /* quantity */);

                 

                  // Post the order request to the order collection

                  // Assume it returns the newly created order

                  MovieOrder order = movie.Orders.Post(orderRequest);

                 

                Comments:

                 

                - The POST result in a redirect to the newly created order. The system GETs this new order and returns it. This means we loose the intermediate data returned from the POST.

                 

                 

                Other verbs

                The Link class is has built-in support for GET/PUT/POST/DELETE. Other verbs can be executed through a generic "Request" method:

                 

                  SomeType x = someLink.Request("SOMEVERB", somePayload);

                 

                 

                Caching

                The Link class and it's associted methods should of course respect ETag and if-not-modified-since etc. This would require the framework to be initialized with a cache implementation of some kind.

                 

                 

                Error handling

                I would suggest using execptions for error handling.

                 

                 

                 

                 

                 





              • Jørn Wildt
                ... Yes, I understand this. From a framework point of view it s left to the programmer to decide what kind of object-builder to register with a certain mime
                Message 7 of 12 , Dec 10, 2009
                • 0 Attachment
                  > Using serializers also tends to lead programmers to
                  > tight-binding between the code and the HTTP
                  > response body. This means
                  > changes in the body may blow the serializer code.

                  Yes, I understand this. From a framework point of view it's left to the
                  programmer to decide what kind of object-builder to register with a certain
                  mime type. It can be a very specific parser/builder (like the movie example,
                  or an image file) or a very loose builder (like a generic XML DOM object).

                  > I suspect you'll find that building a client to properly locate, identify,
                  > and understand the link semantics of a single media type
                  > (application/vnd.movies.movie+xml) is challenging by itself.

                  For a well documented and stable mime type it should not be a problem. But
                  maybe I have something to learn here :-)

                  > Building one
                  > that handles multiple media-types just adds to the fun

                  That's why the framework allows registration of one handler per mime type.
                  Makes coding them quite a bit easier. Instead of having one handler for all
                  mime types. But maybe I misunderstand you.

                  > I also encourage you to treat HTTP control data (headers) as top-level
                  > programming objects in your library

                  Will do.

                  Thanks for the feedback, Jørn

                  ----- Original Message -----
                  From: "mike amundsen" <mamund@...>
                  To: "Jørn Wildt" <jw@...>
                  Cc: "rest-discuss" <rest-discuss@yahoogroups.com>
                  Sent: Wednesday, December 09, 2009 11:58 PM
                  Subject: Re: [rest-discuss] The "purist" C# REST client?


                  Jørn:

                  This line stands out first: "I have avoided Atom Links since, in my
                  experience, these don't serialize well in the C# standard XML serializer."
                  My advice is to be wary of serializers when coding for HTTP. There are so
                  many variances with incoming responses I think you'll find it a real task to
                  build apps based on successfully converting incoming response bodies into
                  code-able objects. Using serializers also tends to lead programmers to
                  tight-binding between the code and the HTTP response body. This means
                  changes in the body may blow the serializer code. This is especially true
                  when working with "generic" media-types such as XML and JSON, etc. since
                  they have very little semantic value built into them.

                  That leads me to another bit of advice I'll offer: think about link
                  semantics from the very start when creating your library. The Web browser
                  client works because the link semantics of the HTML media-type are
                  well-defined (and pretty narrow). There are a limited number of link
                  elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are
                  navigational links (A, FORM). All, except FORM, are limited to using the GET
                  method. It's the semantic model of HTML that allows browsers to properly
                  handle HTTP responses from previously unknown locations and still provide
                  full functionality - even a decade after the semantics where defined. I
                  suspect you'll find that building a client to properly locate, identify,
                  and understand the link semantics of a single media type
                  (application/vnd.movies.movie+xml) is challenging by itself. Building one
                  that handles multiple media-types just adds to the fun<g>.

                  I also encourage you to treat HTTP control data (headers) as top-level
                  programming objects in your library. Allowing programmers to decorate
                  requests with control data (content-encoding, media-type, authorization,
                  cache-control, etc.) and have direct access to the control data on responses
                  will improve the flexibility of any client/server built w/ your library.

                  In the big picture, I prefer looking at HTTP programming from the
                  stand-point of "resource programming." I look for a code library that lets
                  me define a resource, associate or or more URIs with that resource, handle
                  multiple representations of the resource (for both requests and response
                  bodies), and properly decorate requests and responses w/ control data. I
                  also want to make sure it handles mime-types properly (conneg included),
                  conditional requests (GET and PUT), and supports flexible authentication
                  models.

                  FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's
                  been dormant for quite some time as the current version works well for me,
                  but there are lots of places it needs work. I've also built an HTTP
                  utilities library [2] with most all the bits I need for building REST-ful
                  HTTP apps. It's smaller and lighter than my 'framework' library. I mention
                  these as some of the code there might be helpful and/or act as a cautionary
                  tale as you work on your own projects.

                  mca
                  http://amundsen.com/blog/

                  [1] http://exyus.com
                  [2]
                  http://code.google.com/p/mikeamundsen/source/browse/#svn/trunk/Amundsen.Utilities



                  On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@...> wrote:

                  >
                  >
                  > There has been a lot of discussion about the right way to implement a REST
                  > service, but less focus on how you would actually code a client. I have
                  > been
                  > looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example,
                  > and would like to discuss a similar typed approach in C#.
                  >
                  > I am experimenting with an actual implementation and would like some
                  > feedback before getting too far :-)
                  >
                  > Thanks, Jørn
                  >
                  >
                  > [1] http://github.com/caelum/restfulie
                  > [2] http://www.infoq.com/articles/subbu-allamaraju-rest
                  > [3] http://www.infoq.com/articles/webber-rest-workflow
                  >
                  >
                  > *Service example documentation*
                  > In order to discuss a REST client we need a service example. My first use
                  > case is a movie shop where we can search for movies in a specific
                  > category.
                  > To do so the shop has published a single search service URL template:
                  > http://movies.org/movies?category={category<http://movies.org/movies?category=%7Bcategory>}.
                  >
                  >
                  > The shop also publishes three ressource mime types:
                  >
                  > // Example "application/vnd.movies.movie+xml"
                  > <Movie>
                  > <Self href="http://movies.org/movies/91"/>
                  > <Title>Strange Dawn</Title>
                  > <Category>Thriller</Category>
                  > <Director href="http://movies.org/persons/47"/>
                  > </Movie>
                  >
                  > // Example "application/vnd.movies.movie-collection+xml"
                  > <Movies>
                  > <Self href="http://movies.org/movies?category=Thriller"/>
                  > <Movie>
                  > <Title>Strange Dawn</Title>
                  > <Self href="http://movies.org/movies/91"/>
                  > </Movie>
                  > <Movie>...</Movie>
                  > <Movie>...</Movie>
                  > </Movies>
                  >
                  > // Example "application/vnd.movies.person+xml"
                  > <Person>
                  > <Self href="http://movies.org/persons/47"/>
                  > <Name>Richard Strangelove</Name>
                  > <Photo href="http://facebook.com/photos/hh31y1"/>
                  > </Person>
                  >
                  > Comments
                  >
                  > - I have avoided Atom Links since, in my experience, these don't serialize
                  > well in the C# standard XML serializer. You could although create your own
                  > serializer, so this is not an important restriction.
                  >
                  > - Notice how the person type has external references :-)
                  >
                  >
                  > *Code example - Searching*
                  > The cleanest client usage I can come up with is:
                  >
                  > // A link (template). This should be fetched from a configuration file.
                  > Link MoviesSearchLink = new Link("
                  > http://movies.org/movies?category={category}");
                  >
                  > // Anonymous class with search parameters. Reflection is used to extract
                  > values.
                  > // This is about the simplest way to write a "fixed hashmap" in C#
                  > var movieSearchParameter = new { category = "Thriller" };
                  >
                  > // Get ressource stored at the link endpoint
                  > MovieCollection movies =
                  > MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);
                  >
                  > // Iterate over all movies and print title
                  > foreach (Movie movie in movies)
                  > Console.WriteLine("Title: " + movie.Title);
                  > Comments:
                  >
                  > - A Link is untyped. We do not know what lies at the end of it.
                  >
                  > - A link knows how to merge parameters into URL templates.
                  >
                  > - The result of GETing a link is typed. The actual type is defined by the
                  > returned mime type.
                  >
                  > - In order to do something usefull with the search we must assume that it
                  > returns a MovieCollection. Hence the generic type specifier in the
                  > Get<T>()
                  > method. This is apriori information which I cannot see how to code
                  > without.
                  >
                  >
                  > *Parsing ressources*
                  > One piece of magic is how Get<MovieCollection>(params) knows how to
                  > convert
                  > the bytes returned from the endpoint to a MovieCollection. For this we
                  > create a MimeTypeRegistry:
                  >
                  > MimeTypeRegistry.Register<MovieCollection,
                  > MovieCollectionBuilder>("application/vnd.movies.movie-collection");
                  >
                  > which is equal to:
                  >
                  > MimeTypeRegistry.Register(typeof(MovieCollection),
                  > typeof(MovieCollectionBuilder),
                  > "application/vnd.movies.movie-collection");
                  >
                  > This means: when ever we must parse a specific mime type, we look up a
                  > builder in the registry and uses this to parse the returned ressource
                  > representation.
                  >
                  > The typed Get<MovieCollection>(params) method GETs the ressource data,
                  > instantiates the corresponding builder, verifies that the built object
                  > type
                  > matches the requested and returns the built object.
                  >
                  > Comments:
                  >
                  > - This is static typing which RESTafarians seems to shy away from. But the
                  > type depends on the returned ressource, _not_ the URL. So to my knowledge
                  > this is fine.
                  >
                  > - It is not required to use the type safe Get<T>(), you could also call
                  > Get() which returns an object. The actual returned type then depends
                  > solely
                  > on the mime type of the ressource, and it is up to the programmer to
                  > decide
                  > what to do with it.
                  >
                  > - I am quite sure you can write some pretty generic XML builders without
                  > much overhead.
                  >
                  > - This is not limited to XML, you could add image/jpeg and other well
                  > known
                  > mime types. You just need to supply a proper builder.
                  >
                  >
                  > *Code example - Getting sub-ressources*
                  > Now we want to get information about the director of the movie:
                  >
                  > // One of the returned self links from the search query
                  > Link movieLink = movies[0].Self;
                  >
                  > // Get the actual movie
                  > Movie movie = movieLink.Get<Movie>();
                  >
                  > // Get the director
                  > MoviePerson director = movie.Director.Get<MoviePerson>();
                  >
                  > Comments:
                  >
                  > - There are no hard coded links here.
                  >
                  > - The only apriori information we use is the knowledge of the types of the
                  > referenced ressources. These types are documented in the mime type in
                  > which
                  > the links are used.
                  >
                  >
                  > *Versioning*
                  > Now our wonderfull movie shop decides to be able to sell and rate movies.
                  > They do their own selling, but uses the fameous ratings.org service to
                  > rate their movies. So the shop creates a new version of the movie mime
                  > type:
                  >
                  > // Example "application/vnd.movies.movie.*v2*+xml"
                  > <Movie>
                  > <Self href="http://movies.org/movies/91"/>
                  > <Title>Strange Dawn</Title>
                  > <Category>Thriller</Category>
                  > <Director href="http://movies.org/persons/47"/>
                  > <Orders href="http://movies.org/movies/91/orders"/>
                  > <Ratings href=
                  > http://ratings.org/ratings?item=http%3a%2f%2fmovies.org%2fmovies%2f91/>
                  > </Movie>
                  >
                  > In order to service both old and new clients the shop decides to return
                  > the
                  > initial movie mime type by default. Never clients should use the Accept
                  > header to indicate that they want the new version. The same goes for the
                  > movies collection type.
                  >
                  > Our existing client code works happily as it did before.
                  >
                  >
                  > *Code example - A new client*
                  > The new client code would look like this:
                  >
                  > // A link (template). This should be fetched from a configuration file.
                  > Link MoviesSearchLink = new Link("
                  > http://movies.org/movies?category={category}");
                  >
                  > // Anonymous class with search parameters. Reflection is used to extract
                  > values.
                  > // This is about the simplest way to write a "fixed hashmap" in C#
                  > var movieSearchParameter = new { category = "thriller" };
                  >
                  > // Setting up the Accept header
                  > var movieSearchHeaders = new { Accept =
                  > "application/vnd.movies.movie-collection.v2" }
                  >
                  > // Get ressource stored at the link endpoint
                  > MovieCollection movies =
                  > MoviesSearchLink.Get<MovieCollection>(movieSearchParameter,
                  > movieSearchHeaders);
                  >
                  > // Iterate over all movies and print title
                  > foreach (Movie movie in movies)
                  > Console.WriteLine("Title: " + movie.Title);
                  >
                  > *Code example - Buying movies*
                  > Now we have a movie which has an embedded link to it's sales orders. To
                  > buy
                  > a movie we post a new order to the sales order collection:
                  >
                  > // One of the returned self links from the search query
                  > Link movieLink = movies[0].Self;
                  >
                  > // Get the actual movie
                  > Movie movie = movieLink.Get<Movie>();
                  >
                  > // Create a new order request
                  > MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /*
                  > quantity */);
                  >
                  > // Post the order request to the order collection
                  > // Assume it returns the newly created order
                  > MovieOrder order = movie.Orders.Post(orderRequest);
                  >
                  > Comments:
                  >
                  > - The POST result in a redirect to the newly created order. The system
                  > GETs
                  > this new order and returns it. This means we loose the intermediate data
                  > returned from the POST.
                  >
                  >
                  > *Other verbs*
                  > The Link class is has built-in support for GET/PUT/POST/DELETE. Other
                  > verbs
                  > can be executed through a generic "Request" method:
                  >
                  > SomeType x = someLink.Request("SOMEVERB", somePayload);
                  >
                  >
                  > *Caching*
                  > The Link class and it's associted methods should of course respect ETag
                  > and
                  > if-not-modified-since etc. This would require the framework to be
                  > initialized with a cache implementation of some kind.
                  >
                  >
                  > *Error handling*
                  > I would suggest using execptions for error handling.
                  >
                  >
                  >
                  >
                  >

                  ----- Original Message -----
                  From: "mike amundsen" <mamund@...>
                  To: "Jørn Wildt" <jw@...>
                  Cc: "rest-discuss" <rest-discuss@yahoogroups.com>
                  Sent: Wednesday, December 09, 2009 11:58 PM
                  Subject: Re: [rest-discuss] The "purist" C# REST client?


                  Jørn:

                  This line stands out first: "I have avoided Atom Links since, in my
                  experience, these don't serialize well in the C# standard XML serializer."
                  My advice is to be wary of serializers when coding for HTTP. There are so
                  many variances with incoming responses I think you'll find it a real task to
                  build apps based on successfully converting incoming response bodies into
                  code-able objects. Using serializers also tends to lead programmers to
                  tight-binding between the code and the HTTP response body. This means
                  changes in the body may blow the serializer code. This is especially true
                  when working with "generic" media-types such as XML and JSON, etc. since
                  they have very little semantic value built into them.

                  That leads me to another bit of advice I'll offer: think about link
                  semantics from the very start when creating your library. The Web browser
                  client works because the link semantics of the HTML media-type are
                  well-defined (and pretty narrow). There are a limited number of link
                  elements. Some are in-doc links (IMG, LINK, SCRIPT, etc.), some are
                  navigational links (A, FORM). All, except FORM, are limited to using the GET
                  method. It's the semantic model of HTML that allows browsers to properly
                  handle HTTP responses from previously unknown locations and still provide
                  full functionality - even a decade after the semantics where defined. I
                  suspect you'll find that building a client to properly locate, identify,
                  and understand the link semantics of a single media type
                  (application/vnd.movies.movie+xml) is challenging by itself. Building one
                  that handles multiple media-types just adds to the fun<g>.

                  I also encourage you to treat HTTP control data (headers) as top-level
                  programming objects in your library. Allowing programmers to decorate
                  requests with control data (content-encoding, media-type, authorization,
                  cache-control, etc.) and have direct access to the control data on responses
                  will improve the flexibility of any client/server built w/ your library.

                  In the big picture, I prefer looking at HTTP programming from the
                  stand-point of "resource programming." I look for a code library that lets
                  me define a resource, associate or or more URIs with that resource, handle
                  multiple representations of the resource (for both requests and response
                  bodies), and properly decorate requests and responses w/ control data. I
                  also want to make sure it handles mime-types properly (conneg included),
                  conditional requests (GET and PUT), and supports flexible authentication
                  models.

                  FWIW, I started work on a REST-ful HTTP C# framework a while back [1]. It's
                  been dormant for quite some time as the current version works well for me,
                  but there are lots of places it needs work. I've also built an HTTP
                  utilities library [2] with most all the bits I need for building REST-ful
                  HTTP apps. It's smaller and lighter than my 'framework' library. I mention
                  these as some of the code there might be helpful and/or act as a cautionary
                  tale as you work on your own projects.

                  mca
                  http://amundsen.com/blog/

                  [1] http://exyus.com
                  [2]
                  http://code.google.com/p/mikeamundsen/source/browse/#svn/trunk/Amundsen.Utilities



                  On Wed, Dec 9, 2009 at 17:00, Jørn Wildt <jw@...> wrote:

                  >
                  >
                  > There has been a lot of discussion about the right way to implement a REST
                  > service, but less focus on how you would actually code a client. I have
                  > been
                  > looking at RESTFulie[1], Subbu Alamarju[2], and the Starbucks[3] example,
                  > and would like to discuss a similar typed approach in C#.
                  >
                  > I am experimenting with an actual implementation and would like some
                  > feedback before getting too far :-)
                  >
                  > Thanks, Jørn
                  >
                  >
                  > [1] http://github.com/caelum/restfulie
                  > [2] http://www.infoq.com/articles/subbu-allamaraju-rest
                  > [3] http://www.infoq.com/articles/webber-rest-workflow
                  >
                  >
                  > *Service example documentation*
                  > In order to discuss a REST client we need a service example. My first use
                  > case is a movie shop where we can search for movies in a specific
                  > category.
                  > To do so the shop has published a single search service URL template:
                  > http://movies.org/movies?category={category<http://movies.org/movies?category=%7Bcategory>}.
                  >
                  >
                  > The shop also publishes three ressource mime types:
                  >
                  > // Example "application/vnd.movies.movie+xml"
                  > <Movie>
                  > <Self href="http://movies.org/movies/91"/>
                  > <Title>Strange Dawn</Title>
                  > <Category>Thriller</Category>
                  > <Director href="http://movies.org/persons/47"/>
                  > </Movie>
                  >
                  > // Example "application/vnd.movies.movie-collection+xml"
                  > <Movies>
                  > <Self href="http://movies.org/movies?category=Thriller"/>
                  > <Movie>
                  > <Title>Strange Dawn</Title>
                  > <Self href="http://movies.org/movies/91"/>
                  > </Movie>
                  > <Movie>...</Movie>
                  > <Movie>...</Movie>
                  > </Movies>
                  >
                  > // Example "application/vnd.movies.person+xml"
                  > <Person>
                  > <Self href="http://movies.org/persons/47"/>
                  > <Name>Richard Strangelove</Name>
                  > <Photo href="http://facebook.com/photos/hh31y1"/>
                  > </Person>
                  >
                  > Comments
                  >
                  > - I have avoided Atom Links since, in my experience, these don't serialize
                  > well in the C# standard XML serializer. You could although create your own
                  > serializer, so this is not an important restriction.
                  >
                  > - Notice how the person type has external references :-)
                  >
                  >
                  > *Code example - Searching*
                  > The cleanest client usage I can come up with is:
                  >
                  > // A link (template). This should be fetched from a configuration file.
                  > Link MoviesSearchLink = new Link("
                  > http://movies.org/movies?category={category}");
                  >
                  > // Anonymous class with search parameters. Reflection is used to extract
                  > values.
                  > // This is about the simplest way to write a "fixed hashmap" in C#
                  > var movieSearchParameter = new { category = "Thriller" };
                  >
                  > // Get ressource stored at the link endpoint
                  > MovieCollection movies =
                  > MoviesSearchLink.Get<MovieCollection>(movieSearchParameter);
                  >
                  > // Iterate over all movies and print title
                  > foreach (Movie movie in movies)
                  > Console.WriteLine("Title: " + movie.Title);
                  > Comments:
                  >
                  > - A Link is untyped. We do not know what lies at the end of it.
                  >
                  > - A link knows how to merge parameters into URL templates.
                  >
                  > - The result of GETing a link is typed. The actual type is defined by the
                  > returned mime type.
                  >
                  > - In order to do something usefull with the search we must assume that it
                  > returns a MovieCollection. Hence the generic type specifier in the
                  > Get<T>()
                  > method. This is apriori information which I cannot see how to code
                  > without.
                  >
                  >
                  > *Parsing ressources*
                  > One piece of magic is how Get<MovieCollection>(params) knows how to
                  > convert
                  > the bytes returned from the endpoint to a MovieCollection. For this we
                  > create a MimeTypeRegistry:
                  >
                  > MimeTypeRegistry.Register<MovieCollection,
                  > MovieCollectionBuilder>("application/vnd.movies.movie-collection");
                  >
                  > which is equal to:
                  >
                  > MimeTypeRegistry.Register(typeof(MovieCollection),
                  > typeof(MovieCollectionBuilder),
                  > "application/vnd.movies.movie-collection");
                  >
                  > This means: when ever we must parse a specific mime type, we look up a
                  > builder in the registry and uses this to parse the returned ressource
                  > representation.
                  >
                  > The typed Get<MovieCollection>(params) method GETs the ressource data,
                  > instantiates the corresponding builder, verifies that the built object
                  > type
                  > matches the requested and returns the built object.
                  >
                  > Comments:
                  >
                  > - This is static typing which RESTafarians seems to shy away from. But the
                  > type depends on the returned ressource, _not_ the URL. So to my knowledge
                  > this is fine.
                  >
                  > - It is not required to use the type safe Get<T>(), you could also call
                  > Get() which returns an object. The actual returned type then depends
                  > solely
                  > on the mime type of the ressource, and it is up to the programmer to
                  > decide
                  > what to do with it.
                  >
                  > - I am quite sure you can write some pretty generic XML builders without
                  > much overhead.
                  >
                  > - This is not limited to XML, you could add image/jpeg and other well
                  > known
                  > mime types. You just need to supply a proper builder.
                  >
                  >
                  > *Code example - Getting sub-ressources*
                  > Now we want to get information about the director of the movie:
                  >
                  > // One of the returned self links from the search query
                  > Link movieLink = movies[0].Self;
                  >
                  > // Get the actual movie
                  > Movie movie = movieLink.Get<Movie>();
                  >
                  > // Get the director
                  > MoviePerson director = movie.Director.Get<MoviePerson>();
                  >
                  > Comments:
                  >
                  > - There are no hard coded links here.
                  >
                  > - The only apriori information we use is the knowledge of the types of the
                  > referenced ressources. These types are documented in the mime type in
                  > which
                  > the links are used.
                  >
                  >
                  > *Versioning*
                  > Now our wonderfull movie shop decides to be able to sell and rate movies.
                  > They do their own selling, but uses the fameous ratings.org service to
                  > rate their movies. So the shop creates a new version of the movie mime
                  > type:
                  >
                  > // Example "application/vnd.movies.movie.*v2*+xml"
                  > <Movie>
                  > <Self href="http://movies.org/movies/91"/>
                  > <Title>Strange Dawn</Title>
                  > <Category>Thriller</Category>
                  > <Director href="http://movies.org/persons/47"/>
                  > <Orders href="http://movies.org/movies/91/orders"/>
                  > <Ratings href=
                  > http://ratings.org/ratings?item=http%3a%2f%2fmovies.org%2fmovies%2f91/>
                  > </Movie>
                  >
                  > In order to service both old and new clients the shop decides to return
                  > the
                  > initial movie mime type by default. Never clients should use the Accept
                  > header to indicate that they want the new version. The same goes for the
                  > movies collection type.
                  >
                  > Our existing client code works happily as it did before.
                  >
                  >
                  > *Code example - A new client*
                  > The new client code would look like this:
                  >
                  > // A link (template). This should be fetched from a configuration file.
                  > Link MoviesSearchLink = new Link("
                  > http://movies.org/movies?category={category}");
                  >
                  > // Anonymous class with search parameters. Reflection is used to extract
                  > values.
                  > // This is about the simplest way to write a "fixed hashmap" in C#
                  > var movieSearchParameter = new { category = "thriller" };
                  >
                  > // Setting up the Accept header
                  > var movieSearchHeaders = new { Accept =
                  > "application/vnd.movies.movie-collection.v2" }
                  >
                  > // Get ressource stored at the link endpoint
                  > MovieCollection movies =
                  > MoviesSearchLink.Get<MovieCollection>(movieSearchParameter,
                  > movieSearchHeaders);
                  >
                  > // Iterate over all movies and print title
                  > foreach (Movie movie in movies)
                  > Console.WriteLine("Title: " + movie.Title);
                  >
                  > *Code example - Buying movies*
                  > Now we have a movie which has an embedded link to it's sales orders. To
                  > buy
                  > a movie we post a new order to the sales order collection:
                  >
                  > // One of the returned self links from the search query
                  > Link movieLink = movies[0].Self;
                  >
                  > // Get the actual movie
                  > Movie movie = movieLink.Get<Movie>();
                  >
                  > // Create a new order request
                  > MovieOrderRequest orderRequest = new MovieOrderRequest(movie.Self, 1 /*
                  > quantity */);
                  >
                  > // Post the order request to the order collection
                  > // Assume it returns the newly created order
                  > MovieOrder order = movie.Orders.Post(orderRequest);
                  >
                  > Comments:
                  >
                  > - The POST result in a redirect to the newly created order. The system
                  > GETs
                  > this new order and returns it. This means we loose the intermediate data
                  > returned from the POST.
                  >
                  >
                  > *Other verbs*
                  > The Link class is has built-in support for GET/PUT/POST/DELETE. Other
                  > verbs
                  > can be executed through a generic "Request" method:
                  >
                  > SomeType x = someLink.Request("SOMEVERB", somePayload);
                  >
                  >
                  > *Caching*
                  > The Link class and it's associted methods should of course respect ETag
                  > and
                  > if-not-modified-since etc. This would require the framework to be
                  > initialized with a cache implementation of some kind.
                  >
                  >
                  > *Error handling*
                  > I would suggest using execptions for error handling.
                  >
                  >
                  >
                  >
                  >
                • Jørn Wildt
                  ... That s a good point. ... It is my hope that such thing could be handled by a transparent caching layer. The cache will know what was returned last time,
                  Message 8 of 12 , Dec 10, 2009
                  • 0 Attachment
                    > For the trivial case, I don't see a reason why you should be having to set
                    > the Accept header -- framework should do that for you. It should set the
                    > content type on the way out properly, and set the accept header as well,
                    > since it "knows" you want the Movie info.

                    That's a good point.

                    > The common headers should be First Class. I shouldn't have to set an
                    > "If-Modified" myself, I should be able to link.setIfModifiedSince(myDate),
                    > so I don't have to marshal the dates myself.

                    It is my hope that such thing could be handled by a transparent caching
                    layer. The cache will know what was returned last time, and insert that
                    automatically in the headers. I do although not know if this is
                    possible/practical.

                    > Going back to the mime mapping, that should be controllable at a higher,
                    > "global"/framework level, but also at the request level.

                    Good point too.

                    Thanks, Jørn

                    ----- Original Message -----
                    From: "Will Hartung" <willh@...>
                    To: "Jørn Wildt" <jw@...>
                    Cc: "rest-discuss" <rest-discuss@yahoogroups.com>
                    Sent: Thursday, December 10, 2009 12:48 AM
                    Subject: Re: [rest-discuss] The "purist" C# REST client?


                    > Just a couple of thoughts out loud.
                    >
                    > I like the mime-type mapping framework, that would be a nice, generic
                    > piece
                    > of code all on its own, and it should marshal both ways.
                    >
                    > I think you will need to use that in many places. Not simply for GETs, but
                    > for pushing data as well.
                    >
                    > But another place that would be valuable is the fact that most any HTTP
                    > result can have a typed body. So it's easy to envision when you get some
                    > warning, or other error message (perhaps a redirect), that you can
                    > leverage
                    > the ability to send more interesting data than what is simply in the
                    > headers, and have that data marshaled for you automagically.
                    >
                    > I think the LINK infrastructure should be aware of things like redirects,
                    > and expose those things. If you hit a URI that gets a permanent or
                    > temporary
                    > redirect, it would be nice for the client to honor that at least somewhat
                    > transparently. And by that I don't me silently following the redirect, but
                    > I
                    > mean if it sees you hitting it again, will simply jump straight to the
                    > final
                    > destination.
                    >
                    > For the trivial case, I don't see a reason why you should be having to set
                    > the Accept header -- framework should do that for you. It should set the
                    > content type on the way out properly, and set the accept header as well,
                    > since it "knows" you want the Movie info.
                    >
                    > The common headers should be First Class. I shouldn't have to set an
                    > "If-Modified" myself, I should be able to link.setIfModifiedSince(myDate),
                    > so I don't have to marshal the dates myself.
                    >
                    > Going back to the mime mapping, that should be controllable at a higher,
                    > "global"/framework level, but also at the request level. I can easily see
                    > having to map "text/xml" to something different at the request level
                    > depending on the link.
                    >
                    > So, anyway, just some quick thoughts.
                    >
                    > Regards,
                    >
                    > Will Hartung
                    > (willh@...)
                    >
                  • Jon Hanna
                    ... I made a stab at wrapping the WebRequest object with a CachedWebRequest object that applied such functionality and then presented the same interface known
                    Message 9 of 12 , Dec 11, 2009
                    • 0 Attachment
                      Jørn Wildt wrote:
                      >> The common headers should be First Class. I shouldn't have to set an
                      >> "If-Modified" myself, I should be able to link.setIfModifiedSince(myDate),
                      >> so I don't have to marshal the dates myself.
                      >
                      > It is my hope that such thing could be handled by a transparent caching
                      > layer. The cache will know what was returned last time, and insert that
                      > automatically in the headers. I do although not know if this is
                      > possible/practical.

                      I made a stab at wrapping the WebRequest object with a CachedWebRequest
                      object that applied such functionality and then presented the same
                      interface known to all C# coders. I never took it very far, but was
                      happy enough that it could certainly be done (all I wanted to know at
                      the time).

                      Allowing your framework to have it's means of obtaining a WebRequest
                      overridden, may be all you need to allow for such cache handling as a
                      separate component.
                    • Jon Hanna
                      ... Oh wait. Now I remember wanting to have caching at the level just above this (object caching) based on HTTP caching declarations. I never did entirely
                      Message 10 of 12 , Dec 11, 2009
                      • 0 Attachment
                        Jon Hanna wrote:
                        > Allowing your framework to have it's means of obtaining a WebRequest
                        > overridden, may be all you need to allow for such cache handling as a
                        > separate component.

                        Oh wait. Now I remember wanting to have caching at the level just above
                        this (object caching) based on HTTP caching declarations. I never did
                        entirely decide whether that would be a good idea or not.
                      • mike amundsen
                        My experience was that binding caching too tightly to the request object (burying it, really) was not a good idea. When I m coding my HTTP apps, I want
                        Message 11 of 12 , Dec 11, 2009
                        • 0 Attachment
                          My experience was that binding caching too tightly to the request
                          object (burying it, really) was not a good idea. When I'm coding my
                          HTTP apps, I want control over this, not auto-magic stuff. Also,
                          sometimes I can count on an existing cache infrastructure between my
                          app (client or server) and the WWW. When that happens, I need very
                          little caching work done within the library itself.

                          IMO, the really important item in this area is proper support for
                          conditional requests. Supporting GET is pretty straight-forward, PUT
                          gets messy.

                          mca
                          http://amundsen.com/blog/




                          On Fri, Dec 11, 2009 at 10:34, Jon Hanna <jon@...> wrote:
                          > Jon Hanna wrote:
                          >> Allowing your framework to have it's means of obtaining a WebRequest
                          >> overridden, may be all you need to allow for such cache handling as a
                          >> separate component.
                          >
                          > Oh wait. Now I remember wanting to have caching at the level just above
                          > this (object caching) based on HTTP caching declarations. I never did
                          > entirely decide whether that would be a good idea or not.
                          >
                          >
                          >
                          > ------------------------------------
                          >
                          > Yahoo! Groups Links
                          >
                          >
                          >
                          >
                        • Will Hartung
                          ... Observationally, it seems to me that the Hard part about REST via HTTP is at the protocol layer, especially since a lot of the operational burden is on
                          Message 12 of 12 , Dec 11, 2009
                          • 0 Attachment
                            On Fri, Dec 11, 2009 at 7:45 AM, mike amundsen <mamund@...> wrote:

                            > My experience was that binding caching too tightly to the request
                            > object (burying it, really) was not a good idea. When I'm coding my
                            > HTTP apps, I want control over this, not auto-magic stuff. Also,
                            > sometimes I can count on an existing cache infrastructure between my
                            > app (client or server) and the WWW. When that happens, I need very
                            > little caching work done within the library itself.
                            >
                            > IMO, the really important item in this area is proper support for
                            > conditional requests. Supporting GET is pretty straight-forward, PUT
                            > gets messy.

                            Observationally, it seems to me that the "Hard" part about REST via
                            HTTP is at the protocol layer, especially since a lot of the
                            operational burden is on the client.

                            On the server, the logic is reasonably straightforward, especially
                            since the transaction is stateless. But the client has to handle the
                            task of behaving properly, and it is NOT stateless. A simple GET isn't
                            necessarily so simple when you consider all of the possible result
                            cases and caching. Similarly, POST and PUT have their struggles as
                            well, such as redirects, conditional operations, and even things like
                            100-Continue.

                            Amplifying this is the fact that most folks use so little of the HTTP
                            protocol, and suddenly the "ubquitous", "oh it's just HTTP" simplicity
                            become "Oh, you mean THAT HTTP, this is harder than I thought".

                            Regards,

                            Will Hartung
                            (willh@...)
                          Your message has been successfully submitted and would be delivered to recipients shortly.