SlideShare a Scribd company logo
1 of 58
What is the ServiceStack
What is the ServiceStack
http://www.servicestack.net                                                https://github.com/ServiceStack

                                         Demis Bellot
                                             @demisbellot
                                     https://github.com/mythz
                              http://www.servicestack.net/mythz_blog/
                                                                                                      Core Team
                                                                                                       Steffen Müller
                                                                                                            @arxisos
                                   http://careers.stackoverflow.com/mythz
                                                                                                   Sergey Bogdanov
                                                                                                           @desunit
What is the ServiceStack

    • What is it?
    • Where did it come from?
    • What does it do?
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 Interfaces
SQL 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
More than Services
            Simple - Fast - Lightweight - Testable - Clean

     ServiceStack.Text                                                                           ServiceStack.Redis
   .NET’s fastest JSON, JSV, CSV Text Serilaizers                                                     .NET’s leading Redis Client
                                                            Code-First
                                                             POCOs
  ServiceStack.OrmLite                                                                        ServiceStack.Caching
         Fast, typed, Code-First Micro ORM                                                         Clean Caching Provider Interfaces
SQL 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
Simple Demo


  Poco Power
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();
                                                                                      }
Benchmarks
                                                      https://github.com/mythz/ScalingDotNET




Brad Abrams (Google employee, former Microsoft PM and co-author of .NET Framework Design Guidelines)
OrmLite Benchmarks
JSON Benchmarks
Redis vs RavenDB Benchmarks
@ServiceStack favorites:
 Popular
                                      114 Contributors




                      Since July 2011
https://github.com/ServiceStack/ServiceStack/wiki/Contributors   http://www.servicestack.net/100k-downloads/
Where it began?
Enterprise .NET 2007
Where it began?

Followed the .NET Enterprise Play Book
•   Leveraged external Enterprise consultants
•   Adopted Microsoft's 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 -> XSD's -> DTOs -> used in WCF Service Contracts -> WSDLs -> Service Reference Proxies
•   CSF's state-full session was used as a Bus orchestrating communication between services
•   Services were discoverable, participating in CSF's Session
•   Service endpoints were WCF Services, leveraged SOAP headers for extra WS-* compliance
•   Wrote code Designed perfectly normalized databases
What happened? Disaster

            Code-gen DTO's 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
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
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
What is a Service?
What is a Service?


What it’s not
It's NOT to force the use of a particular technology or platform
It's NOT to conform to a pre-defined specification or constraints
It's NOT to use a pre-determined format or follow a pre-scribed architecture
What is a Service?




                     It's to provide a service
What is a Service?


It's to provide a service
to encapsulate some re-usable capabilities and make them available remotely
What is a Service?


It's to provide a service
to 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-use


Good characteristics
   ★ Version-able, tolerant and resilient to changes
   ★ End-to-end productivity

                                                                          Legend:
                                                                              ★   Goals that ServiceStack is optimized for :)
mflow

Less 1/2 development team
  Magnitude more results

Best-Practices SOA Platform
Faster, more scalable services




   ServiceStack was born
Visualizing ServiceStack

Built 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
Visualizing ServiceStack
Visualizing ServiceStack
Advantages of Message-based Services



• They're easy to version and evolve as you're freely able to add/remove functionality without error
• They're easy to route, chain, hijack and decorate through to different handlers and pipelines
• They're easy to serialize and proxy through to remote services
• They're easy to log, record, defer and replay
• They're easy to map and translate to and from domain models
• Ideal for concurrency as immutable messages are thread-safe and are easily multiplexed

• They're easy to extend with generic solutions and re-usable functionality around




                                           https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services
Message-based remote services are everywhere
Concurrency in F# – Part III – Erlang Style Message Passing
   type Message = Word of string | Fetch of IChannel<Map<string,int>> | Stop

type 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))
                                                                 http://strangelights.com/blog/archive/2007/10/24/1601.aspx
Message-based remote services are everywhere
Google Protocol Buffer Messages                                          http://code.google.com/p/protobuf/

message 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 SimpleDB
SelectRequest selectRequest = new SelectRequest()
    .WithSelectExpression("select * from `petboard-public`");

SelectResponse selectResponse = _simpleDBClient.Select(selectRequest);


                                                                         http://aws.amazon.com/articles/3592
Message-based remote services are everywhere
 Scala Actors                                                          Actors in Go
                                                                       type ReadReq struct {
 import scala.actors.Actor._
                                                                         key string
 import java.net.{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
   }
                                                                           }
 }
                                                                         }
                                                                       }()


http://www.cs.helsinki.fi/u/wikla/OTS/Sisalto/examples/html/ch30.html   https://docs.google.com/present/view?id=df36r82q_5gdq5gzth
non-message-based service examples
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));
                                                                                             }
                                                                                         }
                                                                                     }
http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
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()                                        public string Category { get; set; }
        {                                                                                   public decimal? PriceGreaterThan { get; set; }
            return products;                                                            }
        }
                                                                                        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
        //Extending existing services by adding 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);
        }                                                                                    //Design of new services based on calling semantics and Return type,
    }                                                                                        //e.g. Find* filters results, whilst Get* fetches unique records:
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 encourages
Fewer 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 more
resilient to changes as you're able to safely add more functionality or return more data without breaking or needing to re-gen existing clients. Message-based APIs also lend them
better for cached, asynchronous, deferred, proxied and reliable execution with the use of brokers and proxies.
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
                                                                                                                     }
                                                                                                                 ]
                                                                                                           */
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
                                                                                                                  }
                                                                                                            */
Testable

                                                              New API 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));
                                                                         }


              https://github.com/ServiceStack/ServiceStack/blob/master/tests/RazorRockstars.Console.Files/ReqStarsService.cs




                Same Unit Test can be re-used in JSON, XML, JSV, SOAP 1.1/1.2 Integration Tests

        https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Tests/WebServicesTests.cs
Frictionless




               Productive end-to-end typed pipeline
ServiceStack Demo


      Hello, World!


   http://tinyurl.com/hellomonkeyspace
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);
    public string Name { get; set; }               }
}                                                  [AddHeader(ContentType = "text/plain")]
                                                   public object Get(HelloText request) {
[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);
    public string Name { get; set; }                       return ms;
}                                                      }
                                                   }
public 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" });
ServiceStack Demo


     SMessage
SMessage Implementation
    public partial class SMessageService : Service                                 	   public partial class SMessageService : Service
    {                                                                              	   {
        public EmailProvider Email { get; set; }                                          public object Any(EmailMessage request)
        public FacebookGateway Facebook { get; set; }                                     {
        public TwitterGateway Twitter { get; set; }                                           var sw = Stopwatch.StartNew();
        public IMessageFactory MsgFactory { get; set; }                                       Db.InsertAll(Email.Process(request));
                                                                                              return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds };
        public object Any(SMessage request)                                               }
        {
            var sw = Stopwatch.StartNew();                                                 public object Any(CallFacebook request)
                                                                                           {
            if (!request.Defer)                                                                var sw = Stopwatch.StartNew();
            {                                                                                  Db.InsertAll(Facebook.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));                                  public object Any(PostStatusTwitter request)
                 Db.InsertAll(results);                                                    {
            }                                                                                  var sw = Stopwatch.StartNew();
            else                                                                               Db.InsertAll(Twitter.Process(request));
            {                                                                                  return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds };
                 using (var producer = MsgFactory.CreateMessageProducer())                 }
                 {
                     Email.CreateMessages(request).ForEach(producer.Publish);              public object Any(FindReceipts request)
                     Facebook.CreateMessages(request).ForEach(producer.Publish);           {
                     Twitter.CreateMessages(request).ForEach(producer.Publish);                var skip = request.Skip.GetValueOrDefault(0);
                 }                                                                             var take = request.Take.GetValueOrDefault(20);
            }                                                                                  return Db.Select<SMessageReceipt>(q => q.Limit(skip, take));
                                                                                           }
            return new SMessageResponse {                                              }
                TimeTakenMs = sw.ElapsedMilliseconds,
            };
        }
	   }
Why Mono?
Why Mono?




               Scale at $0 licensing cost
            Bring .NET to exciting Platforms
Why Mono?

              Scale at $0 licensing cost

            • Redis
            • PostgreSQL, MySQL, SQLite, Firebird

            Lets build the next Instagram!
Why Mono?

            Scale at $0 licensing cost




                   Where to host
                  servicestack.net?
Why Mono?

                 Scale at $0 licensing cost




    2.67 GHz                                    1.67 GHz
    2GB RAM             Where to host         1.75GB RAM
                       servicestack.net?
    80GB HDD                                   100GB HDD
    4TB traffic                                  2TB traffic
Why Mono?

                 Scale at $0 licensing cost




    2.67 GHz                                    1.67 GHz
    2GB RAM             Where to host         1.75GB RAM
                       servicestack.net?
    80GB HDD                                   100GB HDD
    4TB traffic                                  2TB traffic

   €19.90 mo          > 11x Cheaper!           €219.50 mo
   €238.8 year                                 €2,634 year
Why Mono?

            Bring .NET to exciting Platforms
Features:
Sergey Bogdanov
                                        @desunit



Features: Swagger Integration
Sergey Bogdanov
                                        @desunit



Features: Swagger Integration
https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization




Features: 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
                 }));




                                          https://github.com/ServiceStack/SocialBootstrapApi/
https://github.com/ServiceStack/ServiceStack/wiki/Validation




Features: 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)
               	       */
               	   }




                                                                                  https://github.com/ServiceStack/ServiceStack/wiki/Validation
https://github.com/ServiceStack/ServiceStack/wiki/Caching




Features: 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 doesn't 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

                                http://www.servicestack.net/ServiceStack.Northwind/
https://github.com/ServiceStack/ServiceStack/wiki/Request-logger




Features: Request Logger




                       Query String Filters
https://github.com/ServiceStack/ServiceStack/wiki/Built-in-profiling




Features: 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();
   }
http://careers.stackoverflow.com/mythz




@ServiceStack
                              Thank You
http://www.servicestack.net                   https://github.com/ServiceStack


                               @demisbellot


                               Questions?                                    Core Team
                                                                              Steffen Müller
                                                                                   @arxisos
                                                                          Sergey Bogdanov
                                                                                  @desunit

More Related Content

What's hot

Scala for scripting
Scala for scriptingScala for scripting
Scala for scriptingday
 
Morphia, Spring Data & Co.
Morphia, Spring Data & Co.Morphia, Spring Data & Co.
Morphia, Spring Data & Co.Tobias Trelle
 
MongoDB: Easy Java Persistence with Morphia
MongoDB: Easy Java Persistence with MorphiaMongoDB: Easy Java Persistence with Morphia
MongoDB: Easy Java Persistence with MorphiaScott Hernandez
 
Java Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBJava Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBTobias Trelle
 
MongoDB Live Hacking
MongoDB Live HackingMongoDB Live Hacking
MongoDB Live HackingTobias Trelle
 
MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know Norberto Leite
 
Redis - Usability and Use Cases
Redis - Usability and Use CasesRedis - Usability and Use Cases
Redis - Usability and Use CasesFabrizio Farinacci
 
Java Development with MongoDB
Java Development with MongoDBJava Development with MongoDB
Java Development with MongoDBScott Hernandez
 
glance replicator
glance replicatorglance replicator
glance replicatoririx_jp
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Hermann Hueck
 
POCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewPOCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewGünter Obiltschnig
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.jsAdrien Guéret
 
Tribal Nova Docker workshop
Tribal Nova Docker workshopTribal Nova Docker workshop
Tribal Nova Docker workshopNicolas Degardin
 
Bring your infrastructure under control with Infrastructor
Bring your infrastructure under control with InfrastructorBring your infrastructure under control with Infrastructor
Bring your infrastructure under control with InfrastructorStanislav Tiurikov
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Eelco Visser
 
Scalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBScalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBWilliam Candillon
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSuzquiano
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGuillaume Laforge
 

What's hot (19)

Scala for scripting
Scala for scriptingScala for scripting
Scala for scripting
 
Morphia, Spring Data & Co.
Morphia, Spring Data & Co.Morphia, Spring Data & Co.
Morphia, Spring Data & Co.
 
MongoDB: Easy Java Persistence with Morphia
MongoDB: Easy Java Persistence with MorphiaMongoDB: Easy Java Persistence with Morphia
MongoDB: Easy Java Persistence with Morphia
 
Java Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDBJava Persistence Frameworks for MongoDB
Java Persistence Frameworks for MongoDB
 
MongoDB Live Hacking
MongoDB Live HackingMongoDB Live Hacking
MongoDB Live Hacking
 
MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know
 
Redis - Usability and Use Cases
Redis - Usability and Use CasesRedis - Usability and Use Cases
Redis - Usability and Use Cases
 
Java Development with MongoDB
Java Development with MongoDBJava Development with MongoDB
Java Development with MongoDB
 
Hazelcast
HazelcastHazelcast
Hazelcast
 
glance replicator
glance replicatorglance replicator
glance replicator
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8
 
POCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewPOCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and Overview
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
Tribal Nova Docker workshop
Tribal Nova Docker workshopTribal Nova Docker workshop
Tribal Nova Docker workshop
 
Bring your infrastructure under control with Infrastructor
Bring your infrastructure under control with InfrastructorBring your infrastructure under control with Infrastructor
Bring your infrastructure under control with Infrastructor
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
 
Scalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBScalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDB
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
 

Similar to What istheservicestack

What is the ServiceStack?
What is the ServiceStack?What is the ServiceStack?
What is the ServiceStack?Demis Bellot
 
jclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Colejclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian ColeEverett Toews
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disquszeeg
 
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...DataStax Academy
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationBen Hall
 
Connect + Docker + AWS = Bitbucket Pipelines
Connect + Docker + AWS = Bitbucket PipelinesConnect + Docker + AWS = Bitbucket Pipelines
Connect + Docker + AWS = Bitbucket PipelinesAtlassian
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++Amazon Web Services
 
Microservices with containers in the cloud
Microservices with containers in the cloudMicroservices with containers in the cloud
Microservices with containers in the cloudEugene Fedorenko
 
jclouds overview
jclouds overviewjclouds overview
jclouds overviewAdrian Cole
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)lennartkats
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinSigma Software
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesSreenivas Makam
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusEmily Jiang
 
Mongo+java (1)
Mongo+java (1)Mongo+java (1)
Mongo+java (1)MongoDB
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.Mike Brevoort
 
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun..."ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...Julia Cherniak
 

Similar to What istheservicestack (20)

What is the ServiceStack?
What is the ServiceStack?What is the ServiceStack?
What is the ServiceStack?
 
jclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Colejclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Cole
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
 
Liferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for DevelopersLiferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for Developers
 
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS Application
 
Connect + Docker + AWS = Bitbucket Pipelines
Connect + Docker + AWS = Bitbucket PipelinesConnect + Docker + AWS = Bitbucket Pipelines
Connect + Docker + AWS = Bitbucket Pipelines
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++
 
Microservices with containers in the cloud
Microservices with containers in the cloudMicroservices with containers in the cloud
Microservices with containers in the cloud
 
jclouds overview
jclouds overviewjclouds overview
jclouds overview
 
Couchbas for dummies
Couchbas for dummiesCouchbas for dummies
Couchbas for dummies
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita Galkin
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
 
Mongo+java (1)
Mongo+java (1)Mongo+java (1)
Mongo+java (1)
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun..."ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
 

What istheservicestack

  • 1. What is the ServiceStack
  • 2. What is the ServiceStack http://www.servicestack.net https://github.com/ServiceStack Demis Bellot @demisbellot https://github.com/mythz http://www.servicestack.net/mythz_blog/ Core Team Steffen Müller @arxisos http://careers.stackoverflow.com/mythz Sergey Bogdanov @desunit
  • 3. What is the ServiceStack • What is it? • Where did it come from? • What does it do?
  • 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 Interfaces SQL 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. More than Services Simple - Fast - Lightweight - Testable - Clean ServiceStack.Text ServiceStack.Redis .NET’s fastest JSON, JSV, CSV Text Serilaizers .NET’s leading Redis Client Code-First POCOs ServiceStack.OrmLite ServiceStack.Caching Fast, typed, Code-First Micro ORM Clean Caching Provider Interfaces SQL 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
  • 6. Simple Demo Poco Power
  • 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. Benchmarks https://github.com/mythz/ScalingDotNET Brad Abrams (Google employee, former Microsoft PM and co-author of .NET Framework Design Guidelines)
  • 11. Redis vs RavenDB Benchmarks
  • 12. @ServiceStack favorites: Popular 114 Contributors Since July 2011 https://github.com/ServiceStack/ServiceStack/wiki/Contributors http://www.servicestack.net/100k-downloads/
  • 14. Where it began? Followed the .NET Enterprise Play Book • Leveraged external Enterprise consultants • Adopted Microsoft's 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 -> XSD's -> DTOs -> used in WCF Service Contracts -> WSDLs -> Service Reference Proxies • CSF's state-full session was used as a Bus orchestrating communication between services • Services were discoverable, participating in CSF's Session • Service endpoints were WCF Services, leveraged SOAP headers for extra WS-* compliance • Wrote code Designed perfectly normalized databases
  • 15. What happened? Disaster Code-gen DTO's 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. 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. 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. What is a Service?
  • 19. What is a Service? What it’s not It's NOT to force the use of a particular technology or platform It's NOT to conform to a pre-defined specification or constraints It's NOT to use a pre-determined format or follow a pre-scribed architecture
  • 20. What is a Service? It's to provide a service
  • 21. What is a Service? It's to provide a service to encapsulate some re-usable capabilities and make them available remotely
  • 22. What is a Service? It's to provide a service to 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-use Good characteristics ★ Version-able, tolerant and resilient to changes ★ End-to-end productivity Legend: ★ Goals that ServiceStack is optimized for :)
  • 23. mflow Less 1/2 development team Magnitude more results Best-Practices SOA Platform Faster, more scalable services ServiceStack was born
  • 24. Visualizing ServiceStack Built 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
  • 27. Advantages of Message-based Services • They're easy to version and evolve as you're freely able to add/remove functionality without error • They're easy to route, chain, hijack and decorate through to different handlers and pipelines • They're easy to serialize and proxy through to remote services • They're easy to log, record, defer and replay • They're easy to map and translate to and from domain models • Ideal for concurrency as immutable messages are thread-safe and are easily multiplexed • They're easy to extend with generic solutions and re-usable functionality around https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services
  • 28. Message-based remote services are everywhere Concurrency in F# – Part III – Erlang Style Message Passing type Message = Word of string | Fetch of IChannel<Map<string,int>> | Stop type 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)) http://strangelights.com/blog/archive/2007/10/24/1601.aspx
  • 29. Message-based remote services are everywhere Google Protocol Buffer Messages http://code.google.com/p/protobuf/ message 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 SimpleDB SelectRequest selectRequest = new SelectRequest()     .WithSelectExpression("select * from `petboard-public`"); SelectResponse selectResponse = _simpleDBClient.Select(selectRequest); http://aws.amazon.com/articles/3592
  • 30. Message-based remote services are everywhere Scala Actors Actors in Go type ReadReq struct { import scala.actors.Actor._   key string import java.net.{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   }     } }   } }() http://www.cs.helsinki.fi/u/wikla/OTS/Sisalto/examples/html/ch30.html https://docs.google.com/present/view?id=df36r82q_5gdq5gzth
  • 32. 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));         }     } } http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
  • 33. 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()         public string Category { get; set; }         {         public decimal? PriceGreaterThan { get; set; }             return products;     }         }     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         //Extending existing services by adding 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);         } //Design of new services based on calling semantics and Return type,     } //e.g. Find* filters results, whilst Get* fetches unique records:
  • 34. 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 encourages Fewer 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 more resilient to changes as you're able to safely add more functionality or return more data without breaking or needing to re-gen existing clients. Message-based APIs also lend them better for cached, asynchronous, deferred, proxied and reliable execution with the use of brokers and proxies.
  • 35. 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 } ] */
  • 36. 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 } */
  • 37. Testable New API 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)); } https://github.com/ServiceStack/ServiceStack/blob/master/tests/RazorRockstars.Console.Files/ReqStarsService.cs Same Unit Test can be re-used in JSON, XML, JSV, SOAP 1.1/1.2 Integration Tests https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Tests/WebServicesTests.cs
  • 38. Frictionless Productive end-to-end typed pipeline
  • 39. ServiceStack Demo Hello, World! http://tinyurl.com/hellomonkeyspace
  • 40. 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); public string Name { get; set; } } } [AddHeader(ContentType = "text/plain")] public object Get(HelloText request) { [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); public string Name { get; set; } return ms; } } } public 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" });
  • 41. ServiceStack Demo SMessage
  • 42. SMessage Implementation public partial class SMessageService : Service public partial class SMessageService : Service { { public EmailProvider Email { get; set; } public object Any(EmailMessage request) public FacebookGateway Facebook { get; set; } { public TwitterGateway Twitter { get; set; } var sw = Stopwatch.StartNew(); public IMessageFactory MsgFactory { get; set; } Db.InsertAll(Email.Process(request)); return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds }; public object Any(SMessage request) } { var sw = Stopwatch.StartNew(); public object Any(CallFacebook request) { if (!request.Defer) var sw = Stopwatch.StartNew(); { Db.InsertAll(Facebook.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)); public object Any(PostStatusTwitter request) Db.InsertAll(results); { } var sw = Stopwatch.StartNew(); else Db.InsertAll(Twitter.Process(request)); { return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds }; using (var producer = MsgFactory.CreateMessageProducer()) } { Email.CreateMessages(request).ForEach(producer.Publish); public object Any(FindReceipts request) Facebook.CreateMessages(request).ForEach(producer.Publish); { Twitter.CreateMessages(request).ForEach(producer.Publish); var skip = request.Skip.GetValueOrDefault(0); } var take = request.Take.GetValueOrDefault(20); } return Db.Select<SMessageReceipt>(q => q.Limit(skip, take)); } return new SMessageResponse { } TimeTakenMs = sw.ElapsedMilliseconds, }; } }
  • 44. Why Mono? Scale at $0 licensing cost Bring .NET to exciting Platforms
  • 45. Why Mono? Scale at $0 licensing cost • Redis • PostgreSQL, MySQL, SQLite, Firebird Lets build the next Instagram!
  • 46. Why Mono? Scale at $0 licensing cost Where to host servicestack.net?
  • 47. Why Mono? Scale at $0 licensing cost 2.67 GHz 1.67 GHz 2GB RAM Where to host 1.75GB RAM servicestack.net? 80GB HDD 100GB HDD 4TB traffic 2TB traffic
  • 48. Why Mono? Scale at $0 licensing cost 2.67 GHz 1.67 GHz 2GB RAM Where to host 1.75GB RAM servicestack.net? 80GB HDD 100GB HDD 4TB traffic 2TB traffic €19.90 mo > 11x Cheaper! €219.50 mo €238.8 year €2,634 year
  • 49. Why Mono? Bring .NET to exciting Platforms
  • 51. Sergey Bogdanov @desunit Features: Swagger Integration
  • 52. Sergey Bogdanov @desunit Features: Swagger Integration
  • 53. https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization Features: 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                 })); https://github.com/ServiceStack/SocialBootstrapApi/
  • 54. https://github.com/ServiceStack/ServiceStack/wiki/Validation Features: 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) */ } https://github.com/ServiceStack/ServiceStack/wiki/Validation
  • 55. https://github.com/ServiceStack/ServiceStack/wiki/Caching Features: 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 doesn't 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 http://www.servicestack.net/ServiceStack.Northwind/
  • 57. https://github.com/ServiceStack/ServiceStack/wiki/Built-in-profiling Features: 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(); }
  • 58. http://careers.stackoverflow.com/mythz @ServiceStack Thank You http://www.servicestack.net https://github.com/ServiceStack @demisbellot Questions? Core Team Steffen Müller @arxisos Sergey Bogdanov @desunit

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n