Skip to content

Instantly share code, notes, and snippets.

@ianbattersby
Created July 5, 2012 20:42
Show Gist options
  • Save ianbattersby/3056291 to your computer and use it in GitHub Desktop.
Save ianbattersby/3056291 to your computer and use it in GitHub Desktop.
ServiceStackReSTExample: Trying to figure out 300 Multiple Choices return
namespace ServiceStackReSTExample
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Threading;
using ServiceStack.Common.Web;
using ServiceStack.Logging;
using ServiceStack.Logging.Support.Logging;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.ServiceModel;
using ServiceStack.WebHost.Endpoints;
// Warning: Contrived example ahead
public class Movie
{
public string Title { get; set; }
public List<string> Actors { get; set; }
}
public class MovieResponse
{
public string Id { get; set; }
public ResponseStatus ResponseStatus { get; set; }
public List<Movie> Movies { get; set; }
}
[Description("Movie web service")]
[RestService("/movies", "GET,OPTIONS")]
[DataContract]
public class MovieLookup
{
}
public class MovieLookupService : RestServiceBase<MovieLookup>
{
public override object OnGet(MovieLookup request)
{
// So what I really want to do here is return a 300 Multiple Chocies with links to the other two model-based services.
// It seems sensible to use HttpResult opposed to hijacking IHasOptions directly, however I get caught in a loop. Possible
// HEAD issue? Most likely.
return new HttpResult(new object(), base.RequestContext.ContentType, HttpStatusCode.MultipleChoices);
// Obviously I would be returned an empty object here in practice, but some links to the services.
// As we don't have a preferred link we won't be using the LOCATION header (as per RFC2616).
}
}
[Description("Movie by title web service")]
[RestService("/movies/title/{title}", "GET,OPTIONS")]
[DataContract]
public class MovieLookupTitle
{
[DataMember]
public string Title { get; set; }
}
public class MovieLookupTitleService : RestServiceBase<MovieLookupTitle>
{
public override object OnGet(MovieLookupTitle request)
{
return new MovieResponse()
{
// Lookup in DB for this title..
Id = Guid.NewGuid().ToString(),
Movies = new List<Movie> { new Movie() { Title = "Nelly packs her trunk", Actors = new List<string> { "Demis Bellot", "Ian Battersby" } } },
};
}
}
[Description("Movie by actor web service")]
[RestService("/movies/actor/{actor}", "GET,OPTIONS")]
[DataContract]
public class MovieLookupActor
{
[DataMember]
public string Actor { get; set; }
}
public class MovieLookupActorService : RestServiceBase<MovieLookupActor>
{
public override object OnGet(MovieLookupActor request)
{
return new MovieResponse()
{
// Lookup in DB for this actor
Id = Guid.NewGuid().ToString(),
Movies = new List<Movie> {
new Movie() { Title = "Nelly packs her trunk", Actors = new List<string> { "Demis Bellot", "Ian Battersby" }},
new Movie() { Title = "Planes, Trains, and Strawberries", Actors = new List<string> { "Ian Battersby", "Rob Ashton" }}
},
};
}
}
public class AppListenerHost
: AppHostHttpListenerBase
{
private static ILog log;
public AppListenerHost(string appName)
: base(appName, typeof(Movie).Assembly)
{
LogManager.LogFactory = new DebugLogFactory();
log = LogManager.GetLogger(typeof(AppListenerHost));
}
public override void Configure(Funq.Container container)
{
SetConfig(new EndpointHostConfig
{
GlobalResponseHeaders =
{
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
},
WsdlServiceNamespace = "http://www.servicestack.net/types",
});
}
}
class Program
{
public const string AppName = @"Ian's Movie App";
public const string ListeningOn = @"http://localhost:83/";
static void Main(string[] args)
{
using (var appHost = new AppListenerHost(AppName))
{
appHost.Init();
appHost.Start(ListeningOn);
Console.WriteLine("Started listening on: " + ListeningOn);
Console.WriteLine("AppHost Created at {0}, listening on {1}", DateTime.Now, ListeningOn);
Thread.Sleep(System.Threading.Timeout.Infinite);
}
System.Console.WriteLine("ReadLine()");
System.Console.ReadLine();
}
}
}
@ianbattersby
Copy link
Author

Realise the above example is XML based, HEADER-version most likely something like;

Link: </movie/title>; rel="http://localhost:83/rels/movie/title"
Link: </movie/actor>; rel="http://localhost:83/rels/movie/actor"

@mythz
Copy link

mythz commented Jul 5, 2012

In which case you can just return a custom contentType, headers and body, e.g:

new HttpResult { 
    ContentType = "application/xml",
    Headers = {
        {"Link","</movie/title>; rel=\"http://localhost:83/rels/movie/title\""},
        {"Link","</movie/actor>; rel=\"http://localhost:83/rels/movie/actor\""},
    },
    ResponseText = "<link rel=...",      //If you also want to return it in the body.
};

@ianbattersby
Copy link
Author

Thanks Demis, been tied up but will follow this up tomorrow.

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