Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

What is the ServiceStack?


Published on

What is it?
Where did it come from?
What does it do?

Published in: Technology
  • Dating direct: ❶❶❶ ❶❶❶
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ ❤❤❤
    Are you sure you want to  Yes  No
    Your message goes here
  • key Files are annoying
    Are you sure you want to  Yes  No
    Your message goes here
  • do you make a power point file? thankyou!
    Are you sure you want to  Yes  No
    Your message goes here

What is the ServiceStack?

  1. 1. What is the ServiceStack
  2. 2. What is the ServiceStack Core Team Demis Bellot @demisbellot Steffen Müller @arxisos Sergey Bogdanov @desunit
  3. 3. What is the ServiceStack • What is it? • Where did it come from? • What does it do?
  4. 4. More than Services Simple - Fast - Lightweight - Testable - Clean ServiceStack.Text ServiceStack.Redis .NET’s fastest JSON, JSV, CSV Text Serializers .NET’s leading Redis Client ServiceStack.OrmLite ServiceStack.Caching Fast, typed, Code-First Micro ORM Clean Caching Provider InterfacesSQL Server, Sqlite, PostgreSQL, MySQL, Oracle, Firebird In-Memory, Redis, Memcached, Azure, Disk More: node.js-powered Bundler, Logging, Auto-Mappers, Service Clients, Markdown Razor, Configuration Providers, Enhanced Funq IOC
  5. 5. More than Services Simple - Fast - Lightweight - Testable - Clean ServiceStack.Text ServiceStack.Redis .NET’s fastest JSON, JSV, CSV Text Serializers .NET’s leading Redis Client Code-First POCOs ServiceStack.OrmLite ServiceStack.Caching Fast, typed, Code-First Micro ORM Clean Caching Provider Interfaces Re-use same POCOs in allSQL Server, Sqlite, PostgreSQL, MySQL, Oracle, Firebird ServiceStack libs In-Memory, Redis, Memcached, Azure, Disk More: node.js-powered Bundler, Logging, Auto-Mappers, Service Clients, Markdown Razor, Configuration Providers, Enhanced Funq IOC, ...
  6. 6. Simple Demo Poco Power
  7. 7. Implementation var appSettings = new AppSettings(); var config = appSettings.Get<Config>("my.config", new Config { GitHubName = "mythz", TwitterName = "ServiceStack" });Object graphs in Config deserialize into clean POCOs:<appSettings name=”my.config” value=”{GitHubName:mythz,TwitterName:ServiceStack}”/> var github = new GithubGateway(); var repos = github.GetAllUserAndOrgsReposFor(config.GitHubName);Avoid Web.Config completely with sensible default values var twitter = new TwitterGateway(); var tweets = twitter.GetTimeline(config.TwitterName); External providers to return clean POCOs "Loaded {0} repos and {1} tweets...".Print(repos.Count, tweets.Count); OrmLiteConfig.DialectProvider = SqliteDialect.Provider; //using (IDbConnection db = "~/db.sqlite".MapAbsolutePath().OpenDbConnection()) Use Extension methods to: using (IDbConnection db = ":memory:".OpenDbConnection()) { db.DropAndCreateTable<Tweet>(); • DRY logic db.DropAndCreateTable<GithubRepo>(); • Create readable code • Avoid abstractions / restrictions "nInserting {0} Tweets into Sqlite:".Print(tweets.Count); db.InsertAll(tweets); • Allow extensibility "nLatest {0} Tweets from Sqlite:".Print(Show); db.Select<Tweet>(q => q.OrderByDescending(x => x.Id).Limit(Show)).PrintDump(); "nInserting {0} Repos into Sqlite:".Print(repos.Count); Code-First POCOs db.InsertAll(repos); "nLatest {0} Repos from Sqlite:".Print(Show); • Master authority of your models db.Select<GithubRepo>(q => q.OrderByDescending(x => x.Id).Limit(Show)).PrintDump(); • Start from C# project out } • Schema’s inferred from POCO’s using (var redis = new RedisClient()) • Reduce industrial knowledge { • Use Conventions where possible "nInserting {0} Tweets into Redis:".Print(tweets.Count); redis.StoreAll(tweets); • Typed API "n{0} Tweets from Redis:".Print(Show); • Intelli-sense & productivity redis.GetAll<Tweet>().Take(Show).PrintDump(); • Refactoring "nInserting {0} Repos into Redis:".Print(repos.Count); • Correctness redis.StoreAll(repos); "n{0} Repos from Redis:".Print(Show); redis.GetAll<GithubRepo>().Take(Show).PrintDump(); }
  8. 8. Benchmarks Abrams (Google employee, former Microsoft PM and co-author of .NET Framework Design Guidelines)
  9. 9. OrmLite Benchmarks
  10. 10. JSON Benchmarks
  11. 11. Redis vs RavenDB Benchmarks
  12. 12. @ServiceStack favorites: Popular 114 Contributors Since July 2011
  13. 13. Where it began?Enterprise .NET 2007
  14. 14. Where it began?Followed the .NET Enterprise Play Book• Leveraged external Enterprise consultants• Adopted Microsofts prescribed Enterprise SOA solution at the time: CSF, WCF and BizTalk• We had an Enterprise / Technical Architect round-table• Split Internal systems into different independent SOA services (we really wanted to do SOA :)• Enterprise architects defined web service contracts using UML and XSDs: • XSD Messages were implementation ignorant • Explicitly validated XSD conformance at runtime • Leveraged SOAP/XML/XSD: Headers, Inheritance, Namespaces • UML -> XSDs -> DTOs -> used in WCF Service Contracts -> WSDLs -> Service Reference Proxies• CSFs state-full session was used as a Bus orchestrating communication between services• Services were discoverable, participating in CSFs Session• Service endpoints were WCF Services, leveraged SOAP headers for extra WS-* compliance• Wrote code Designed perfectly normalized databases
  15. 15. What happened? Disaster Code-gen DTOs were:• Brittle: A simple namespace change would break existing messages• Infectious: Domain logic binded to code-gen DTOs and version changes led to multiple parallel implementations• Friction-encumbered: Services needed to be built/ deployed in lock-step with each other We pioneered:• Xml everywhere: We had XML config to manage our XML- configured services and resources• Week-long downtimes: between breaking major upgrades, required to flush old messages out of the system• Glacial Development: The turn-around time to get a field from UML/XSD/dll to C# was measured in days• Enterprise Hacks: Added "ViewBags" to most messages to allow us to stuff arbitrary data in existing messages without changing the schema
  16. 16. What happened?• SOAP • Frail, Slow, Poor programmatic fit, Only accessible to SOAP Clients, Incompatible impls• RPC method signatures • Brittle, promotes lots of chatty client-specific API, Typed-API mandates code-gen, blurred service layer• Code-Gen • Changes breaks code, inhibits DRY, forces abstraction, multiple versions results in parallel implementations• Bus / State-full Sessions • Less accessible, harder to debug and test, easier to fail
  17. 17. What we did right?• SOA Design: Coarse-grained, well-defined, self-describing, time-decoupled, re-usable messages• Pub/Sub: Promotes the most loosely coupled architecture i.e. Sender decoupled from Receiver• Message Queues: Replay-able async idempotent messages provide the most reliable and durable inter-service communications• Martin Fowler & Co knew what the best-practices for remote services were: • Remote Facade: Using message-based, coarse-grained/batch-full interfaces minimizing round-trips, promoting creation of fewer but tolerant and version-able service interfaces • DTOs: Avoid any effort expended dealing with wire-format in application code • Gateway: Removes comms logic in app code and provides a swappable comms layer with a good isolation and testing abstraction
  18. 18. What is a Service?
  19. 19. What is a Service?What it’s notIts NOT to force the use of a particular technology or platformIts NOT to conform to a pre-defined specification or constraintsIts NOT to use a pre-determined format or follow a pre-scribed architecture
  20. 20. What is a Service? Its to provide a service
  21. 21. What is a Service?Its to provide a serviceto encapsulate some re-usable capabilities and make them available remotely
  22. 22. What is a Service?Its to provide a serviceto encapsulate some re-usable capabilities and make them available remotely ★ To as many clients as possible ★ In the most accessible and interoperable way ★ With the least amount of effort ★ With maximum amount of re-useGood characteristics ★ Version-able, tolerant and resilient to changes ★ End-to-end productivity Legend: ★ Goals that ServiceStack is optimized for :)
  23. 23. What is a Service?Its to provide a serviceto encapsulate some re-usable capabilities and make them available remotely ★ To as many clients as possible Services offer the highest level of software ★ In the most accessible and interoperable way re-use. Being able to easily take advantage ★ With the least amount of effort of these capabilities is where benefits of ★ With maximum amount of re-use SOA are ultimately derived. To maximize the benefits, ServiceStack isGood characteristics optimized in reducing the burden in creating and consuming services, end-to-end. ★ Version-able, tolerant and resilient to changes ★ End-to-end productivity Legend: ★ Goals that ServiceStack is optimized for :)
  24. 24. mflowLess 1/2 development team Magnitude more resultsBest-Practices SOA PlatformFaster, more scalable services ServiceStack was born
  25. 25. Visualizing ServiceStackBuilt on raw ASP.NET IHttpHandler’s Stand-alone HttpListener, MQ, RCON hosts Runs Everywhere Clean Slate using Code-First POCO’s New Auth, Caching, Session Providers
  26. 26. Visualizing ServiceStack
  27. 27. Visualizing ServiceStack
  28. 28. Advantages of Message-based Services• Theyre easy to version and evolve as youre freely able to add/remove functionality without error• Theyre easy to route, chain, hijack and decorate through to different handlers and pipelines• Theyre easy to serialize and proxy through to remote services• Theyre easy to log, record, defer and replay• Theyre easy to map and translate to and from domain models• Ideal for concurrency as immutable messages are thread-safe and are easily multiplexed• Theyre easy to extend with generic solutions and enhance with re-usable functionality
  29. 29. Message-based remote services are everywhereConcurrency in F# – Part III – Erlang Style Message Passing type Message = Word of string | Fetch of IChannel<Map<string,int>> | Stoptype WordCountingAgent() =    let counter = MailboxProcessor.Start(fun inbox ->             let rec loop(words : Map<string,int>) =                async { let! msg = inbox.Receive()                        match msg with                        | Word word ->                            if words.ContainsKey word then                                let count = words.[word]                                let words = words.Remove word                                return! loop(words.Add (word, (count + 1)) )                            else                                return! loop(words.Add (word, 1) )                        | Stop ->                            return ()                        | Fetch replyChannel ->                            do replyChannel.Post(words) //post to reply channel and continue                            return! loop(words) }              loop(Map.empty)) //The initial state     member a.AddWord(n) = counter.Post(Word(n))    member a.Stop() = counter.Post(Stop)    member a.Fetch() = counter.PostSync(fun replyChannel -> Fetch(replyChannel))
  30. 30. Message-based remote services are everywhereGoogle Protocol Buffer Messages Person {  required int32 id = 1;  required string name = 2;  optional string email = 3;}Amazon C# SDK Petboard: An ASP.NET Sample Using Amazon S3 and Amazon SimpleDBSelectRequest selectRequest = new SelectRequest()    .WithSelectExpression("select * from `petboard-public`");SelectResponse selectResponse = _simpleDBClient.Select(selectRequest);
  31. 31. Message-based remote services are everywhere Scala Actors Actors in Go type ReadReq struct { import scala.actors.Actor._   key string import{InetAddress, UnknownHostException}   ack chan<- string } case class LookupIP(name: String, respondTo: Actor) type WriteReq struct { case class LookupResult(   key, val string   name: String, }   address: Option[InetAddress] ) c := make(chan interface{}) object NameResolver extends Actor { go func() {   def act() {   m := make(map[string]string)     loop {   for {       react {     switch r := (<-c).(type) {         case LookupIP(name, actor) =>     case ReadReq:           actor ! LookupResult(name, getIp(name))       r.ack <- m[r.key]       }     case WriteReq:     }       m[r.key] = r.val   }     } }   } }()
  32. 32. non-message-based service examples
  33. 33. non-message-based service examples namespace HelloWebAPI.Controllers Your First ASP.NET Web API (C#) Tutorial: {     public class ProductsController : ApiController     {         Product[] products = new Product[]         {             new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },             new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },             new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }         };         public IEnumerable<Product> GetAllProducts()         {             return products;         }         public Product GetProductById(int id)         {             var product = products.FirstOrDefault((p) => p.Id == id);             if (product == null)             {                 throw new HttpResponseException(HttpStatusCode.NotFound);             }             return product;         }         public IEnumerable<Product> GetProductsByCategory(string category)         {             return products.Where(                 (p) => string.Equals(p.Category, category,                     StringComparison.OrdinalIgnoreCase));         }     } }
  34. 34. Your First ASP.NET Web API (C#) Tutorial: The Same Services in ServiceStack: public class ProductsControllerV2 : ApiController public class FindProducts : IReturn<List<Product>>    {     {        public IEnumerable<Product> GetAllProducts() 5 vs 2         public string Category { get; set; }        {            return products; Services &         public decimal? PriceGreaterThan { get; set; }     }        } Entry Points     public class GetProduct : IReturn<Product>        public Product GetProductById(int id)     {        {         public int? Id { get; set; }            var product = products.FirstOrDefault((p) => p.Id == id);         public string Name { get; set; }            if (product == null)     }            {                throw new HttpResponseException(HttpStatusCode.NotFound);     public class ProductsService : IService            }     {            return product;         public object Get(FindProducts request)        }         {             var ret = products.AsQueryable();        public Product GetProductByName(string categoryName)             if (request.Category != null)        {                 ret = ret.Where(x => x.Category == request.Category);            var product = products.FirstOrDefault((p) => p.Name == categoryName);             if (request.PriceGreaterThan.HasValue)            if (product == null)                 ret = ret.Where(x => x.Price > request.PriceGreaterThan.Value);            {             return ret;                throw new HttpResponseException(HttpStatusCode.NotFound);         }            }            return product;         public object Get(GetProduct request)        }         {             var product = request.Id.HasValue        //Adding existing services with more RPC method calls                 ? products.FirstOrDefault(x => x.Id == request.Id.Value)        public IEnumerable<Product> GetProductsByCategory(string category)                 : products.FirstOrDefault(x => x.Name == request.Name);        {            return products.Where(             if (product == null)                (p) => string.Equals(p.Category, category,                 throw new HttpError(HttpStatusCode.NotFound, "Product does not exist");                    StringComparison.OrdinalIgnoreCase));        }             return product;         }        public IEnumerable<Product> GetProductsByPriceGreaterThan(decimal price)     }        {            return products.Where((p) => p.Price > price);        } SOA Design: Services differentiated by calling semantics and Return type:    } e.g. Find* filters results, whilst Get* fetches unique records:
  35. 35. Familiar?WCF-Style Services vs ServiceStack Web Services public class Customers {public interface IService int[] Ids;{ string[] UserNames; Customer GetCustomerById(int id); string[] Emails; Customer[] GetCustomerByIds(int[] id); } Customer GetCustomerByUserName(string userName); Customer[] GetCustomerByUserNames(string[] userNames); public class CustomersResponse { Customer GetCustomerByEmail(string email); Customer[] Results; Customer[] GetCustomerByEmails(string[] emails); }}Any combination of the above can be fulfilled by 1 remote call, by the same single web service - i.e what ServiceStack encouragesFewer and more batch-full services require less maintenance and promote the development of more re-usable and efficient services. In addition, message APIs are much moreresilient to changes as youre able to safely add more functionality or return more data without breaking or needing to re-gen existing clients. Message-based APIs also lend thembetter for cached, asynchronous, deferred, proxied and reliable execution with the use of brokers and proxies.
  36. 36. Calling the Product Services in ServiceStack     private const string BaseUri = "http://localhost:1337";   /* All Products:     IRestClient client = new JsonServiceClient(BaseUri); [ {     "nAll Products:".Print(); Id: 1,     client.Get(new FindProducts()).PrintDump(); Name: Tomato Soup, Category: Groceries, Price: 1 }, { Id: 2, Name: Yo-yo, Category: Toys, // Notes: Price: 3.75 // - No Code-Gen: Same generic service client used for all operations }, // - When Custom Routes are specified it uses those, otherwise falls back to pre-defined routes { // - IRestClient interface implemented by JSON, JSV, Xml, MessagePack, ProtoBuf Service Clients Id: 3, // - Service returns IEnumerable[Product] but JSON, JSV serializers happily handles List[Product] fine Name: Hammer, Category: Hardware, Price: 16.99 } ] */     /* Toy Products:     List<Product> toyProducts = client.Get(new FindProducts { Category = "Toys" }); [     "nToy Products:".Print(); {     toyProducts.PrintDump(); Id: 2, Name: Yo-yo, Category: Toys, Price: 3.75 } ] */
  37. 37. Calling the Product Services in ServiceStack    List<Product> productsOver2Bucks = client.Get(new FindProducts { PriceGreaterThan = 2 });     /* Products over $2:    "nProducts over $2:".Print(); [    productsOver2Bucks.PrintDump(); { Id: 2, Name: Yo-yo, Category: Toys, Price: 3.75 }, { Id: 3, Name: Hammer, Category: Hardware, Price: 16.99 } ] */    var hardwareOver2Bucks = client.Get(new FindProducts {PriceGreaterThan=2, Category="Hardware"});     /* Hardware over $2:    "nHardware over $2:".Print(); [    hardwareOver2Bucks.PrintDump(); { Id: 3, Name: Hammer, Category: Hardware, Price: 16.99 } ] */    Product product1 = client.Get(new GetProduct { Id = 1 });    /* Product with Id = 1:    "nProduct with Id = 1:".Print(); {    product1.PrintDump(); Id: 1, Name: Tomato Soup, Category: Groceries, Price: 1 } */
  38. 38. Testable All Clients share same IRestClient & IServiceClient interfaces for New API Tests easy mocking and integration tests protected static IRestClient[] RestClients = [Test, TestCaseSource("RestClients")] { public void Can_GET_AllReqstars(IRestClient client) new JsonServiceClient(BaseUri), { new XmlServiceClient(BaseUri), var allReqstars = client.Get<List<Reqstar>>("/reqstars"); new JsvServiceClient(BaseUri), Assert.That(allReqstars.Count, Is.EqualTo(ReqstarsService.SeedData.Length)); new MsgPackServiceClient(BaseUri), } } ; [Test, TestCaseSource("ServiceClients")] protected static IServiceClient[] ServiceClients = public void Can_SEND_AllReqstars_PrettyTypedApi(IServiceClient client) RestClients.OfType<IServiceClient>().ToArray(); { var allReqstars = client.Send(new AllReqstars()); Assert.That(allReqstars.Count, Is.EqualTo(ReqstarsService.SeedData.Length)); } Same Unit Test can be re-used in JSON, XML, JSV, SOAP 1.1/1.2 Integration Tests
  39. 39. Frictionless Easy to serialize form into a model and send to Ser vice Gateway and bind results to Response Productive end-to-end typed pipeline
  40. 40. ServiceStack Demo Hello, World!
  41. 41. Hello World Implementation[Route("/hellohtml/{Name}")] public class HelloService : Service {public class HelloHtml public object Get(HelloHtml request) {{ return "<h1>Hello, {0}!</h1>".Fmt(request.Name); Override Content-Type public string Name { get; set; } }} [AddHeader(ContentType = "text/plain")] return raw strings, bytes, public object Get(HelloText request) { Streams, etc.[Route("/hellotext/{Name}")] return "<h1>Hello, {0}!</h1>".Fmt(request.Name);public class HelloText }{ [AddHeader(ContentType = "image/png")] public string Name { get; set; } public object Get(HelloImage request) {} var width = request.Width.GetValueOrDefault(640); var height = request.Height.GetValueOrDefault(360);[Route("/helloimage/{Name}")] var bgColor = request.Background != null ? Color.FromName(request.Background) : Color.ForestGreen;public class HelloImage var fgColor = request.Foreground != null ? Color.FromName(request.Foreground) : Color.White;{ var image = new Bitmap(width, height); public string Name { get; set; } using (var g = Graphics.FromImage(image)) { g.Clear(bgColor); public int? Width { get; set; } var drawString = "Hello, {0}!".Fmt(request.Name); public int? Height { get; set; } var drawFont = new Font("Times", request.FontSize.GetValueOrDefault(40)); public int? FontSize { get; set; } var drawBrush = new SolidBrush(fgColor); public string Foreground { get; set; } var drawRect = new RectangleF(0, 0, width, height); public string Background { get; set; } var drawFormat = new StringFormat {} LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }; [Route("/hello/{Name}")] g.DrawString(drawString, drawFont, drawBrush, drawRect, drawFormat);public class Hello : IReturn<HelloResponse> var ms = new MemoryStream();{ image.Save(ms, ImageFormat.Png); Get Content-Negotiation public string Name { get; set; } return ms; and typed C# clients when} } } returning DTOspublic class HelloResponse public object Get(Hello request) {{ return new HelloResponse { Result = "Hello, {0}!".Fmt(request.Name) }; public string Result { get; set; } }} } C# Client calls with: var response = client.Get(new Hello { Name = "ServiceStack" });
  42. 42. ServiceStack Demo SMessage
  43. 43. SMessage Implementation public partial class SMessageService : Service public partial class SMessageService : Service { { public EmailProvider Email { get; set; } public object Any(FindReceipts request) public FacebookGateway Facebook { get; set; } { public TwitterGateway Twitter { get; set; } var skip = request.Skip.GetValueOrDefault(0); public IMessageFactory MsgFactory { get; set; } var take = request.Take.GetValueOrDefault(20); return Db.Select<SMessageReceipt>(q => q.Limit(skip, take)); public object Any(SMessage request) } { var sw = Stopwatch.StartNew(); public object Any(EmailMessage request) { if (!request.Defer) var sw = Stopwatch.StartNew(); { Db.InsertAll(Email.Process(request)); var results = new List<SMessageReceipt>(); return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds }; results.AddRange(Email.Send(request)); } results.AddRange(Facebook.Send(request)); results.AddRange(Twitter.Send(request)); Easily defer execution public object Any(CallFacebook request) Db.InsertAll(results); by dropping DTOs in { } registered MQs var sw = Stopwatch.StartNew(); else Db.InsertAll(Facebook.Process(request)); { return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds }; using (var producer = MsgFactory.CreateMessageProducer()) } { Email.CreateMessages(request).ForEach(producer.Publish); public object Any(PostStatusTwitter request) Facebook.CreateMessages(request).ForEach(producer.Publish); { Twitter.CreateMessages(request).ForEach(producer.Publish); var sw = Stopwatch.StartNew(); } Db.InsertAll(Twitter.Process(request)); } return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds }; } return new SMessageResponse { } Deferred messages TimeTakenMs = sw.ElapsedMilliseconds, are picked up by MQ }; } broker that calls back into } existing services
  44. 44. Why Mono?
  45. 45. Why Mono? Scale at $0 licensing cost Bring .NET to exciting Platforms
  46. 46. Why Mono? Scale at $0 licensing cost • Redis • PostgreSQL, MySQL, SQLite, Firebird Lets build the next Instagram!
  47. 47. Why Mono? Scale at $0 licensing cost Where to host
  48. 48. Why Mono? Scale at $0 licensing cost 2.67 GHz 1.67 GHz 2GB RAM Where to host 1.75GB RAM 80GB HDD 100GB HDD 4TB traffic 2TB traffic
  49. 49. Why Mono? Scale at $0 licensing cost 2.67 GHz 1.67 GHz 2GB RAM Where to host 1.75GB RAM 80GB HDD 100GB HDD 4TB traffic 2TB traffic €19.90 mo > 11x Cheaper! €219.50 mo €238.8 year €2,634 year
  50. 50. Why Mono? Bring .NET to exciting Platforms
  51. 51. Features:
  52. 52. Sergey Bogdanov @desunitFeatures: Swagger Integration
  53. 53. Sergey Bogdanov @desunitFeatures: Swagger Integration
  54. 54. Authentication Providers var appSettings = new AppSettings(); Plugins.Add(new AuthFeature( () => new CustomUserSession(), //Use your own typed Custom UserSession type new IAuthProvider[] { new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials new TwitterAuthProvider(appSettings), //Sign-in with Twitter new FacebookAuthProvider(appSettings), //Sign-in with Facebook new DigestAuthProvider(appSettings), //Sign-in with Digest Auth new BasicAuthProvider(), //Sign-in with Basic Auth new GoogleOpenIdOAuthProvider(appSettings), //Sign-in with Google OpenId new YahooOpenIdOAuthProvider(appSettings), //Sign-in with Yahoo OpenId new OpenIdOAuthProvider(appSettings), //Sign-in with Custom OpenId }));
  55. 55. Validation End-to-end typed API for exceptions try { var client = new JsonServiceClient(BaseUri); var response = client.Send<UserResponse>(new User()); } catch (WebServiceException webEx) { /* webEx.StatusCode = 400 webEx.ErrorCode = ArgumentNullException webEx.Message = Value cannot be null. Parameter name: Name webEx.StackTrace = (your Server Exception StackTrace - if DebugMode is enabled) webEx.ResponseDto = (your populated Response DTO) webEx.ResponseStatus = (your populated Response Status DTO) webEx.GetFieldErrors() = (individual errors for each field if any) */ }
  56. 56. Caching Providers container.Register<ICacheClient>(new MemoryCacheClient()); public class OrdersService : Service { public object Get(CachedOrders request) { var cacheKey = "unique_key_for_this_request"; return base.RequestContext.ToOptimizedResultUsingCache(base.Cache, cacheKey, () => { //Delegate is executed if item doesnt exist in cache //Any response DTO returned here will be cached automatically } ); } } Redis, Memcached, Disk and Azure Caching Providers also available Sessions works with any Cache Provider
  57. 57. Request Logger Query String Filters
  58. 58. Mini Profiler Built-in protected void Application_BeginRequest(object src, EventArgs e) { if (Request.IsLocal) Profiler.Start(); } protected void Application_EndRequest(object src, EventArgs e) { Profiler.Stop(); }
  59. 59. @ServiceStack Thank You Core Team Demis Bellot @demisbellot Steffen Müller @arxisos Sergey Bogdanov @desunit