# Why ServiceStack Source: https://docs.servicestack.net/why-servicestack Developed in the modern age, ServiceStack provides an alternate, cleaner POCO-driven way of creating web services. ### Features Overview ServiceStack is a simple, fast, versatile and highly-productive full-featured [Web](https://razor.netcore.io) and [Web Services](/web-services) Framework that's thoughtfully-architected to [reduce artificial complexity](/autoquery/why-not-odata#why-not-complexity) and promote [remote services best-practices](/advantages-of-message-based-web-services) with a [message-based design](/what-is-a-message-based-web-service) that allows for maximum re-use that can leverage an integrated [Service Gateway](/service-gateway) for the creation of loosely-coupled [Modularized Service](/modularizing-services) Architectures. ServiceStack Services are consumable via an array of built-in fast data formats (inc. [JSON](https://github.com/ServiceStack/ServiceStack/tree/main/ServiceStack.Text/src/ServiceStack.Text), XML, [CSV](/csv-format), [JSONL](/jsonl-format), [JSV](/jsv-format), [ProtoBuf](/protobuf-format) and [MsgPack](/messagepack-format)) as well as XSD/WSDL for [SOAP endpoints](/soap-support) and [Rabbit MQ](/rabbit-mq), [Redis MQ](/redis-mq), [Azure Service Bus](/azure-service-bus-mq), [Amazon SQS](/aws#sqsmqserver) and [Background MQ](/background-mq), MQ hosts. Its design and simplicity focus offers an unparalleled suite of productivity features that can be declaratively enabled without code, from creating fully queryable Web API's with just a single Typed Request DTO with [Auto Query](/autoquery/) supporting [every major RDBMS](/ormlite/#ormlite-rdbms-providers) to the built-in support for [Auto Batched Requests](/auto-batched-requests) or effortlessly enabling rich [HTTP Caching](/http-caching) and [Encrypted Messaging](/auth/encrypted-messaging) for all your existing services via [Plugins](/plugins). Your same Services also serve as the Controller in ServiceStack's [Smart Razor Views](https://razor.netcore.io/) reducing the effort to serve both [Web and Single Page Apps](https://github.com/ServiceStackApps/LiveDemos) as well as [Rich Desktop and Mobile Clients](https://github.com/ServiceStackApps/HelloMobile) that are able to deliver instant interactive experiences using ServiceStack's real-time [Server Events](/server-events). ServiceStack Services also maximize productivity for consumers providing an [instant end-to-end typed API without code-gen](/csharp-client) enabling the most productive development experience for developing .NET to .NET Web Services. ### Benefits - **Simplicity** - All features are centered around APIs that accept and return Typed DTOs - **Speed** - Built for speed on high-performance components utilizing performance APIs available in each .NET runtime - **Web Services Best Practices** - Adopts time-tested SOA Integration Patterns for APIs and client integrations - **Message-based Services** - Model-driven, code-first, friction-free development - **Native Clients** - Clean, end-to-end typed idiomatic APIs for most major platforms - **Modern** - No XML config, IOC built-in, no code-gen, conventional defaults - **Smart** - Infers greater intelligence from your strongly typed DTOs - **Effortless Features** - Most features enhance your existing DTOs making them trivial to enable - **Multi Platform** - Supports .NET 4.5 and .NET Core platforms for hosting on Windows, OSX, Linux - **Multiple Hosts** - Run in Web, Console, native Windows/OSX Desktop Apps, Windows Services - **Host Agnostic** - Services are decoupled from HTTP and can be hosted in MQ Services - **Highly testable** - Typed, idiomatic client APIs enable succinct, intuitive Integration tests - **Mature** - Stable with over 10+ years of development - **Preserve Investment** - modern libraries that are [Continuously Improved](/release-notes-history) (not abandoned or replaced) - **Dependable** - Commercially supported and actively developed - **Increasing Value** - ServiceStack's [ever-growing features](https://servicestack.net/features) adds more capabilities around your Services with each release ### Generate Instant Typed APIs from within all Major IDEs! ServiceStack now [integrates with all Major IDE's](/add-servicestack-reference.html) used for creating the best native experiences on the most popular platforms to enable a highly productive dev workflow for consuming Web Services, making ServiceStack the ideal back-end choice for powering rich, native iPhone and iPad Apps on iOS with Swift, Mobile and Tablet Apps on the Android platform with Java, OSX Desktop Applications as well as targeting the most popular .NET PCL platforms including Xamarin.iOS, Xamarin.Android, Windows Store, WPF, WinForms and Silverlight: [![](./img/pages/servicestack-reference/ide-plugins-splash.png)](https://www.youtube.com/watch?v=JKsgrstNnYY) #### [JetBrains Rider ServiceStack Plugin](https://www.youtube.com/watch?v=JKsgrstNnYY) The **ServiceStack** Rider plugin is installable directly from JetBrains Marketplace and enables seamless integration with JetBrains Rider for easily generating C#, TypeScript, F# and VB.NET Typed APIs from just a remote ServiceStack Base URL. #### [VS.NET integration with ServiceStackVS](/create-your-first-webservice#step-1-download-and-install-servicestackvs) Providing instant Native Typed API's for [C#](/csharp-add-servicestack-reference.html), [TypeScript](/typescript-add-servicestack-reference.html), [F#](/fsharp-add-servicestack-reference.html) and [VB.NET](/vbnet-add-servicestack-reference.html) directly in Visual Studio for the [most popular .NET platforms](https://github.com/ServiceStackApps/HelloMobile) including iOS and Android using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) on Windows. #### [Xamarin Studio integration with ServiceStackXS](/csharp-add-servicestack-reference.html#xamarin-studio) Providing [C# Native Types](/csharp-add-servicestack-reference.html) support for developing iOS and Android mobile Apps using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) with [Xamarin Studio](https://www.xamarin.com/studio) on OSX. The **ServiceStackXS** plugin also provides a rich web service development experience developing Client applications with [Mono Develop on Linux](/csharp-add-servicestack-reference.html#xamarin-studio-for-linux) #### [Android Studio integration with ServiceStack Plugin](/java-add-servicestack-reference.html) Providing [an instant Native Typed API in Java](/java-add-servicestack-reference.html) and [Kotlin](/kotlin-add-servicestack-reference.html) including idiomatic Java Generic Service Clients supporting Sync and Async Requests by leveraging Android's AsyncTasks to enable the creation of services-rich and responsive native Java or Kotlin Mobile Apps on the Android platform - directly from within Android Studio! #### [JetBrains IDEs integration with ServiceStack IDEA plugin](/java-add-servicestack-reference.html#install-servicestack-idea-from-the-plugin-repository) The ServiceStack IDEA plugin is installable directly from IntelliJ's Plugin repository and enables seamless integration with IntelliJ Java Maven projects for generating a Typed API to quickly and effortlessly consume remote ServiceStack Web Services from pure cross-platform Java or Kotlin Clients. #### [Eclipse integration with ServiceStackEclipse](https://github.com/ServiceStack/ServiceStack.Java/tree/master/src/ServiceStackEclipse#eclipse-integration-with-servicestack) The unmatched productivity offered by [Java Add ServiceStack Reference](/java-add-servicestack-reference.html) is also available in the [ServiceStackEclipse IDE Plugin](https://github.com/ServiceStack/ServiceStack.Java/tree/master/src/ServiceStackEclipse#eclipse-integration-with-servicestack) that's installable from the [Eclipse MarketPlace](https://marketplace.eclipse.org/content/servicestackeclipse) to provide deep integration of Add ServiceStack Reference with Eclipse Java Maven Projects enabling Java Developers to effortlessly Add and Update the references of their evolving remote ServiceStack Web Services. #### [Simple command-line utilities for ServiceStack](/add-servicestack-reference.html#simple-command-line-utilities) In addition to our growing list of supported IDE's, the [x dotnet tool](/dotnet-tool) allows VS Code and other cross-platform IDEs, build servers, shell scripts and other automated tasks to easily Add and Update ServiceStack References with a single command. #### [Invoke ServiceStack APIs from the command-line](/post-command) Easily inspect and invoke C# .NET Web APIs from the command-line with Post Command which allows you to both inspect and call any ServiceStack API with just its name and a JS Object literal. API Responses returned in human-friendly markdown tables by default or optionally as JSON & raw HTTP. ## Simple Customer Database REST Services Example This example is also available as a [stand-alone integration test](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/CustomerRestExample.cs): ```csharp //Web Service Host Configuration public class AppHost : AppSelfHostBase { public AppHost() : base("Customer REST Example", typeof(CustomerService).Assembly) {} public override void Configure(Container container) { //Register which RDBMS provider to use container.Register(c => new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider)); using (var db = container.Resolve().Open()) { //Create the Customer POCO table if it doesn't already exist db.CreateTableIfNotExists(); } } } //Web Service DTOs [Route("/customers", "GET")] public class GetCustomers : IReturn {} public class GetCustomersResponse { public List Results { get; set; } } [Route("/customers/{Id}", "GET")] public class GetCustomer : IReturn { public int Id { get; set; } } [Route("/customers", "POST")] public class CreateCustomer : IReturn { public string Name { get; set; } } [Route("/customers/{Id}", "PUT")] public class UpdateCustomer : IReturn { public int Id { get; set; } public string Name { get; set; } } [Route("/customers/{Id}", "DELETE")] public class DeleteCustomer : IReturnVoid { public int Id { get; set; } } // POCO DB Model public class Customer { [AutoIncrement] public int Id { get; set; } public string Name { get; set; } } //Web Services Implementation public class CustomerService : Service { public object Get(GetCustomers request) { return new GetCustomersResponse { Results = Db.Select() }; } public object Get(GetCustomer request) { return Db.SingleById(request.Id); } public object Post(CreateCustomer request) { var customer = new Customer { Name = request.Name }; Db.Save(customer); return customer; } public object Put(UpdateCustomer request) { var customer = Db.SingleById(request.Id); if (customer == null) throw HttpError.NotFound($"Customer '{request.Id}' does not exist"); customer.Name = request.Name; Db.Update(customer); return customer; } public void Delete(DeleteCustomer request) { Db.DeleteById(request.Id); } } ``` ### [Calling the above REST Service from any C#/.NET Client](/csharp-add-servicestack-reference.html) No code-gen required, can re-use above Server DTOs: ```csharp var client = new JsonServiceClient(BaseUri); //GET /customers var all = client.Get(new GetCustomers()); // Count = 0 //POST /customers var customer = client.Post(new CreateCustomer { Name = "Foo" }); //GET /customer/1 customer = client.Get(new GetCustomer { Id = customer.Id }); // Name = Foo //GET /customers all = client.Get(new GetCustomers()); // Count = 1 //PUT /customers/1 customer = client.Put( new UpdateCustomer { Id = customer.Id, Name = "Bar" }); // Name = Bar //DELETE /customers/1 client.Delete(new DeleteCustomer { Id = customer.Id }); //GET /customers all = client.Get(new GetCustomers()); // Count = 0 ``` Same code also works with [Android, iOS, Xamarin.Forms, UWP and WPF clients](https://github.com/ServiceStackApps/HelloMobile). ::: info [F#](/fsharp-add-servicestack-reference.html) and [VB.NET](/vbnet-add-servicestack-reference.html) can re-use same [.NET Service Clients](/csharp-client.html) and DTOs ::: ### [Calling from TypeScript](/typescript-add-servicestack-reference.html#ideal-typed-message-based-api) ```ts const client = new JsonServiceClient(baseUrl); const { results } = await client.get(new GetCustomers()); ``` ### [Calling from Swift](/swift-add-servicestack-reference.html#jsonserviceclientswift) ```swift let client = JsonServiceClient(baseUrl: BaseUri) client.getAsync(GetCustomers()) .then { let results = $0.results; } ``` ### [Calling from Java](/java-add-servicestack-reference.html#jsonserviceclient-usage) ```java JsonServiceClient client = new JsonServiceClient(BaseUri); GetCustomersResponse response = client.get(new GetCustomers()); List results = response.results; ``` ### [Calling from Kotlin](/kotlin-add-servicestack-reference.html#jsonserviceclient-usage) ```kotlin val client = JsonServiceClient(BaseUri) val response = client.get(GetCustomers()) val results = response.results ``` ### Calling the from [Dart](/dart-add-servicestack-reference#example-usage) ```dart var client = new JsonServiceClient(baseUri); var response = await client.get(new GetCustomers()); ``` ### [Calling from jQuery using TypeScript Definitions](/typescript-add-servicestack-reference.html#typescript-interface-definitions) ```js $.getJSON($.ss.createUrl("/customers", request), request, function (r: dtos.GetCustomersResponse) { alert(r.Results.length == 1); }); ``` ### Calling from jQuery ```js $.getJSON(baseUri + "/customers", function(r) { alert(r.Results.length == 1); }); ``` That's all the application code required to create and consume a simple database-enabled REST Web Service! ### Define web services following Martin Fowlers Data Transfer Object Pattern ServiceStack was heavily influenced by [**Martin Fowlers Data Transfer Object Pattern**](http://martinfowler.com/eaaCatalog/dataTransferObject): >When you're working with a remote interface, such as Remote Facade (388), each call to it is expensive. >As a result you need to reduce the number of calls, and that means that you need to transfer more data >with each call. One way to do this is to use lots of parameters. >However, this is often awkward to program - indeed, it's often impossible with languages such as Java >that return only a single value. > >The solution is to create a Data Transfer Object that can hold all the data for the call. It needs to be serializable to go across the connection. >Usually an assembler is used on the server side to transfer data between the DTO and any domain objects. The Request- and Response DTO's used to define web services in ServiceStack are standard POCO's while the implementation just needs to inherit from a testable and dependency-free `IService` marker interface. As a bonus for keeping your DTO's in a separate dependency-free .dll, you're able to re-use them in your C#/.NET clients providing a strongly-typed API without any code-gen what-so-ever. Also your DTO's *define everything* ServiceStack does not pollute your web services with any additional custom artifacts or markup. ### Multiple Clients Our generic Service clients covers the most popular Mobile, Desktop and Server platforms with first-class implementations for Xamarin, Android, Java and TypeScript which now includes: - [.NET Service Clients](/csharp-client) - C# / VB.NET / F# - .NET Core 2.1+ - .NET Framework 4.5+ - Blazor WASM - Xamarin.iOS - Xamarin.Android - UWP - Silverlight - [TypeScript Service Client](/typescript-add-servicestack-reference#typescript-serviceclient) - Web - Node.js Server - React Native - iOS - Android - [Python Service Client](/python-add-servicestack-reference) - [Dart](/dart-add-servicestack-reference) - Flutter - iOS - Android - Web / Angular.dart - [Java Service Client](/java-add-servicestack-reference#jsonserviceclient-api) - Android - JVM 1.7+ (Java, Kotlin, Scala, etc) - Java Clients - Java Servers - [Kotlin Service Client](/kotlin-add-servicestack-reference) - [Swift Service Client](/swift-add-servicestack-reference#swift-client-usage) - iOS - OSX - [Swift Package Manager Apps](https://github.com/ServiceStackApps/swift-techstacks-console) - [JavaScript (jQuery)](/ss-utils-js) - Web - [MQ Clients](/messaging#mq-client-architecture) - Background MQ - Rabbit MQ - Redis MQ - Amazon SQS - Azure Service Bus ### Multiple pluggable Formats ServiceStack re-uses the custom artifacts above and with zero-config and without imposing any extra burden on the developer adds discoverability and provides hosting of your web service on a number of different formats, including: - [JSON]/json-format) - XML - [JSV](/jsv-format) - [CSV](/csv-format) - [MsgPack](/messagepack-format) - [ProtoBuf](/protobuf-format) - [gRPC](/grpc/) - [SOAP 1.1/1.2](/soap-support) - HTML - [HTML5 Report Format](/html5reportformat) - [Sharp Pages](https://sharpscript.net/docs/script-pages) - [Razor](https://razor.netcore.io/) - [Markdown Razor](/markdown-razor) ### Multiple Endpoints Whilst ServiceStack is fundamentally a premier HTTP Framework, its Services can also be consumed from new [gRPC](/grpc/) as well as legacy [SOAP 1.1 and 1.2](/soap-support) endpoints as well as a number of [MQ Servers](/messaging): - [Background MQ Service](/background-mq) - [Rabbit MQ Server](/rabbit-mq) - [Redis MQ Server](/redis-mq) - [Amazon SQS MQ Server](/amazon-sqs-mq) - [Azure Service Bus MQ](/azure-service-bus-mq) ### Multiple Hosting Options In addition to supporting multiple formats and endpoints, ServiceStack can also be hosted within a multitude of different hosting options: #### Windows, OSX or Linux - **.NET Core 2.1+** - [Web App or SelfHost](https://github.com/NetCoreApps/LiveDemos#servicestack-net-core-live-demos) - [Worker Service](/messaging#worker-service-templates) #### Windows - **.NET Framework 4.5+** - [ASP.NET Core 2.1 LTS](/templates/corefx) - [Classic ASP.NET System.Web](https://github.com/ServiceStackApps/LiveDemos#live-servicestack-demos) - [Stand-alone, Self-Hosted HttpListener](/self-hosting) - [Stand-alone Windows Service](/templates/windows-service) - [Hosted inside WinForms with Chromium Embedded Framework](https://github.com/ServiceStack/ServiceStack.Gap#winforms-with-chromium-embedded-framework) - [Windows and Azure Service Fabric](https://github.com/ServiceStackApps/HelloServiceFabric) #### OSX - [Hosted inside Mac OSX Cocoa App with Xamarin.Mac](https://github.com/ServiceStack/ServiceStack.Gap#mac-osx-cocoa-app-with-xmarainmac) ### Target Multiple platforms With multi-targeted projects creating both .NET Framework and .NET Standard builds you can optionally run your same ServiceStack App on multiple platforms as seen with the [Hello Mobile Shared Gateway](/releases/v5_0_0#run-aspnet-core-apps-on-the-net-framework) project where its same shared [ServiceStack Server.Common project](https://github.com/ServiceStackApps/HelloMobile#servicestack-server-app) is used to host the same App running on: - [Server.NetCore](https://github.com/ServiceStackApps/HelloMobile/tree/master/src/Server.NetCore) - hosting the ServiceStack Services in a **ASP.NET Core 2.1 App** - [Server.NetCoreFx](https://github.com/ServiceStackApps/HelloMobile/tree/master/src/Server.NetCoreFx) - hosting in a **ASP.NET Core App** on the **.NET Framework** - [Server.AspNet](https://github.com/ServiceStackApps/HelloMobile/tree/master/src/Server.AspNet) - hosting classic **ASP.NET Framework** Web Applications - [Server.HttpListener](https://github.com/ServiceStackApps/HelloMobile/tree/master/src/Server.HttpListener) - host in a .NET Framework Self-Hosting **HttpListener** AppHost ### VS.NET Templates There's a [VS.NET Template](/templates/) for creating solutions targeting most of the above platforms. E.g. the [React Desktop Apps](https://github.com/ServiceStackApps/ReactDesktopApps) VS.NET Template provides an easy and integrated way to host a Single Page React App on multiple platforms. ## Goals of Service Design The primary benefits of Services are that they offer the highest level of software re-use, they're [Real Computers all the way down](https://mythz.servicestack.net/#messaging) retaining the ability to represent anything. Especially at this level, encapsulation and its external interactions are paramount which sees the [Service Layer as its most important Contract](http://stackoverflow.com/a/15369736/85785), constantly evolving to support new capabilities whilst serving and outliving its many consumers. Extra special attention should be given to Service design with the primary goals of exposing its capabilities behind [consistent and self-describing](/why-servicestack#goals-of-service-design), intent-based [tell-dont-ask](https://pragprog.com/articles/tell-dont-ask) APIs. A Services ability to encapsulate complexity is what empowers consumers to be able to perform higher-level tasks like provisioning a cluster of AWS servers or being able to send a tweet to millions of followers in seconds with just a simple HTTP request, i.e. being able to re-use existing hardened functionality without the required effort, resources and infrastructure to facilitate the request yourself. To maximize accessibility it's recommended for Service Interfaces to be orientated around resources and verbs, retain a flat structure, customizable with key value pairs so they're accessible via the built-in QueryString and FormData support present in all HTTP clients, from HTML Forms to command-line utilities like [curl](https://curl.haxx.se). ### WCF the anti-DTO Web Services Framework Unfortunately this best-practices convention is effectively discouraged by Microsoft's WCF SOAP Web Services framework as they encourage you to develop API-specific RPC method calls by mandating the use of method signatures to define your web services API. This results in less re-usable, more client-specific APIs that encourages more remote method calls. Unhappy with this perceived anti-pattern in WCF, ServiceStack was born providing a Web Service framework that embraces best-practices for calling remote services, using config-free, convention-based DTO's. ### Encourages development of message-style, re-usable and batch-full web services Entire POCO types are used to define the request- and response DTO's to promote the creation well-defined coarse-grained web services. Message-based interfaces are best-practices when dealing with out-of-process calls as they can batch more work using less network calls and are ultimately more re-usable as the same operation can be called using different calling semantics. This is in stark contrast to WCF's Operation or Service contracts which encourage RPC-style, application-specific web services by using method signatures to define each operation. As it stands in general-purpose computing today, there is nothing more expensive you can do than a remote network call. Although easier for the newbie developer, by using _methods_ to define web service operations, WCF is promoting bad-practices by encouraging them to design and treat web-service calls like normal function calls even though they are millions of times slower. Especially at the app-server tier, nothing hurts performance and scalability of your client and server than multiple dependent and synchronous web service calls. Batch-full, message-based web services are ideally suited in development of SOA services as they result in fewer, richer and more re-usable web services that need to be maintained. RPC-style services normally manifest themselves from a *client perspective* that is the result of the requirements of a single applications data access scenario. Single applications come and go over time while your data and services are poised to hang around for the longer term. Ideally you want to think about the definition of your web service from a *services and data perspective* and how you can expose your data so it is more re-usable by a number of your clients. ## Difference between an RPC-chatty and message-based API ```csharp public interface IWcfCustomerService { Customer GetCustomerById(int id); List GetCustomerByIds(int[] id); Customer GetCustomerByUserName(string userName); List GetCustomerByUserNames(string[] userNames); Customer GetCustomerByEmail(string email); List GetCustomerByEmails(string[] emails); } ``` ### contrast with an equivalent message based service: ```csharp public class Customers : IReturn> { public int[] Ids { get; set; } public string[] UserNames { get; set; } public string[] Emails { get; set; } } ``` **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. Comparatively there is almost no win for a remote RPC API, except to maybe [hide a remote service even exists](https://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing) by making a remote call look like a method call even though they're millions of times slower, leading new developers to develop inefficient, brittle systems from the start. # Architecture Overview Source: https://docs.servicestack.net/architecture-overview Ultimately behind-the-scenes ServiceStack is just built on top of ASP.NET's Raw [IHttpAsyncHandler](https://msdn.microsoft.com/en-us/library/ms227433.aspx). Existing abstractions and [xmlconfig-encumbered legacy ASP.NET providers](http://mono.servicestack.net/mvc-powerpack/) have been abandoned, in favour of fresh, simple and clean [Caching](/caching), [Session](/auth/sessions) and [Authentication](/auth/authentication-and-authorization) providers all based on clean POCOs, supporting multiple back-ends and all working seamlessly together. Our best-practices architecture is purposely kept simple, introduces minimal new concepts or artificial constructs that can all be eloquently captured in the diagram below: ## Server Architecture ![ServiceStack Logical Architecture View](/img/pages/overview/servicestack-logical-view-02.png) ## Client Architecture ServiceStack's [Message-based design](/advantages-of-message-based-web-services) allows us to easily support [typed, generic and re-usable Service Clients](/clients-overview) for all our popular formats: ![ServiceStack HTTP Client Architecture](/img/pages/overview/servicestack-httpclients.png) Having all clients share the same interface allow them to be hot-swappable at run-time without code changes and keep them highly testable where the same unit test can also [serve as an XML, JSON, JSV, SOAP Integration Test](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Tests/WebServicesTests.cs). By promoting clean (endpoint-ignorant and dependency-free) Service and DTO classes, your web services are instantly re-usable and can be hosted in non-http contexts as well. E.g. The client architecture when one of the [built-in MQ Host is enabled](/redis-mq): ![ServiceStack MQ Client Architecture](/img/pages/overview/servicestack-mqclients.png) ## Implementation The entry point for all ASP.NET and HttpListener requests is in the [ServiceStack.HttpHandlerFactory](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/HttpHandlerFactory.cs) whose purpose is to return the appropriate IHttpHandler for the incoming request. There are 2 distinct modes in any ServiceStack application: 1. AppHost Setup and Configuration - Only done once for all services. Run only once on App StartUp. 1. Runtime - Run on every request: uses dependencies, plugins, etc. defined in the AppHost. Each new request re-binds all IOC dependencies to a new service instance which gets disposed at the end of each request. The implementation of this can be visualized below: ![ServiceStack Overview](/img/pages/overview/servicestack-overview-01.png) After the `IHttpHandler` is returned, it gets executed with the current ASP.NET or HttpListener request wrapped in a common [IRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequest.cs) instance. # Instantly Servicify existing Systems Source: https://docs.servicestack.net/servicify In addition to [AutoQuery](/autoquery/rdbms) automatically providing your Services implementations, [Studio](/studio) providing its instant UI, ServiceStack also gained the capability to **[generate your entire API](/autoquery/autogen)** including Typed API contracts, data models, implementations & human-friendly pluralized HTTP API routes over an existing System RDBMS's tables. ## AutoGen ServiceStack's [AutoGen](/autoquery/autogen) enables a number of exciting possibilities, predominantly it's the fastest way to ServiceStack-ify an existing systems RDBMS where it will serve as an invaluable tool for anyone wanting to quickly migrate to ServiceStack and access its functionality ecosystem around ServiceStack Services: **[AutoGen's](/autoquery/autogen)** code generation is programmatically customizable where the generated types can be easily augmented with additional declarative attributes to inject your App's conventions into the auto generated Services & Types to apply custom behavior like Authorization & additional validation rules. After codifying your system conventions the generated classes can optionally be "ejected" where code-first development can continue as normal. This feature enables rewriting parts or modernizing legacy systems with the least amount of time & effort, once Servicified you can take advantage of declarative features like Multitenancy, Optimistic Concurrency & Validation, enable automatic features like Executable Audit History, allow business users to maintain validation rules in its RDBMS, manage them through **Studio** & have them applied instantly at runtime and visibly surfaced through ServiceStack's myriad of [client UI auto-binding options](/world-validation). **Studio** can then enable stakeholders with an instant UI to quickly access and search through their data, import custom queries directly into Excel or access them in other registered Content Types through a custom UI where fine-grained app-level access can be applied to customize which tables & operations different users have. ### gRPC's Typed protoc Universe **AutoGen** also enables access to ServiceStack's ecosystem of metadata services & connectivity options where it's now become the **fastest way to generate gRPC endpoints** over an existing system. This is especially exciting as in addition to enabling high-performance connectivity to your Systems data, it opens it up to [all languages in gRPC's protoc universe](https://grpc.io/docs/languages/). Whilst the Smart, Generic [C# / F# / VB.NET Service Clients](/grpc/generic) continue to provide the best UX for consuming gRPC Services, one of the nicest **protoc generated** clients languages is [Dart](http://dart.dev) - a modern high-level language with native class performance & script-like productivity where individual source files can be run immediately without compilation, it's quality tooling, static analysis & high-level features like async/await make it an ideal exploratory language for consuming gRPC endpoints. ### Dart gRPC Script Playground This quick demo shows an example of instantly Servicifying a database & accesses it via gRPC in minutes, starting with a new [grpc](https://github.com/NetCoreTemplates/grpc) project from scratch, it [mixes](/mix-tool) in [autocrudgen](https://gist.github.com/gistlyn/464a80c15cb3af4f41db7810082dc00c) to configure **AutoGen** to generate AutoQuery services for the registered [sqlite](https://gist.github.com/gistlyn/768d7b330b8c977f43310b954ceea668) RDBMS that's copied into the project from the [northwind.sqlite](https://gist.github.com/gistlyn/97d0bcd3ebd582e06c85f8400683e037) gist. Once the servicified App is running it accesses the gRPC Services in a new Dart Console App using the UX-friendly [Dart gRPC support in the x dotnet tool](/grpc/dart) to call the protoc generated Services: > YouTube: [youtu.be/5NNCaWMviXU](https://youtu.be/5NNCaWMviXU) [![](/img/pages/release-notes/v5.9/autogen-grpc.png)](https://youtu.be/5NNCaWMviXU) ### Flutter gRPC Android App And if you can access it from Dart, you can access it from all platforms Dart runs on - the most exciting is Google's [Flutter](https://flutter.dev) UI Kit for building beautiful, natively compiled applications for Mobile, Web, and Desktop from a single codebase: > YouTube: [youtu.be/3iz9aM1AlGA](https://youtu.be/3iz9aM1AlGA) [![](/img/pages/release-notes/v5.9/autogen-grpc-flutter.jpg)](https://youtu.be/3iz9aM1AlGA) ## React Native Typed Client gRPC is just [one of the endpoints ServiceStack Services](/why-servicestack#multiple-clients) can be accessed from, for an even richer & more integrated development UX they're also available in all popular Mobile, Web & Desktop languages [Add ServiceStack Reference](/add-servicestack-reference) supports. Like [TypeScript](/typescript-add-servicestack-reference) which can be used in Browser & Node TypeScript code-bases as well as JavaScript-only code-bases like [React Native](https://reactnative.dev) - a highly productive Reactive UI for developing iOS and Android Apps: [![](/img/pages/release-notes/v5.9/autogen-react-native.png)](https://youtu.be/6-SiLAbY63w) ::: info YouTube [youtu.be/6-SiLAbY63w](https://youtu.be/6-SiLAbY63w) ::: # Explore ServiceStack Source: https://docs.servicestack.net/explore-servicestack If you're completely new to ServiceStack, the [YouTube channel](https://www.youtube.com/channel/UC0kXKGVU4NHcwNdDdRiAJSA/videos) is a great way to explore some of the possibilities easily enabled with ServiceStack: [![](/img/pages/overview/servicestack-youtube.png)](https://www.youtube.com/channel/UC0kXKGVU4NHcwNdDdRiAJSA/videos) ## Explore ServiceStack Apps A great way to learn new technology is to explore existing Apps built with it, where for ServiceStack you can find a number of simple focused Apps at: ### [.NET Core Apps](https://github.com/NetCoreApps/LiveDemos) ### [.NET Framework Apps](https://github.com/ServiceStackApps/LiveDemos#live-servicestack-demos) ### [Sharp Apps](https://sharpscript.net/sharp-apps/app-index) Many Apps are well documented like [World Validation](/world-validation) which covers how to re-implement a simple Contacts App UI in **10 popular Web Development approaches** - all calling the same ServiceStack Services. ServiceStack is a single code-base implementation that supports [.NET's most popular Server platforms](/why-servicestack#multiple-hosting-options) with near perfect source-code [compatibility with .NET Core](/netcore) so all .NET Frameworks Apps are still relevant in .NET Core, e.g. the [EmailContacts guidance](https://github.com/ServiceStackApps/EmailContacts) walks through the recommended setup and physical layout structure of typical medium-sized ServiceStack projects, including complete documentation of how to create the solution from scratch, whilst explaining all the ServiceStack features it makes use of along the way. ## Starting Project Templates Once you've familiarized yourself with ServiceStack and are ready to use it in action, get started with a customized starting project template from our online template builder at:

servicestack.net/start

[![](/img/pages/overview/servicestack-start.png)](https://servicestack.net/start) # ServiceStack v8.6 Source: https://docs.servicestack.net/releases/v8_06
![](/img/pages/release-notes/v8.6/bg-text-to-blazor.jpeg) Text to Blazor is our first initiative for harnessing AI to help to rapidly generate new Blazor Admin CRUD Apps from just a text description. [![](/img/pages/okai/text-to-blazor-prompt.webp)](https://servicestack.net/text-to-blazor) This will query 5 different high quality AI models to generate 5 different Data Models, APIs, DB Migrations and Admin UIs which you can browse to find the one that best matches your requirements. [![](/img/pages/okai/text-to-blazor-gen.webp)](https://servicestack.net/text-to-blazor) ## Using AI to generate Data Models for Inspiration Whilst the result is a working CRUD App, the approach taken is very different from most AI tools which uses AI to generate the entire App that ends up with a whole new code-base developers didn't write which they'd now need to maintain. Instead AI is only used to **generate the initial Data Models** within a **TypeScript Declaration file** which we've found is the best format supported by AI models that's also the best typed DSL for defining data models with minimal syntax that's easy for humans to read and write. ### Download preferred Blazor Vue CRUD App Once you've decided on the Data Models that best matches your requirements, you can download your preferred generated Blazor Vue CRUD App: [![](/img/pages/okai/text-to-blazor-download.webp)](https://servicestack.net/text-to-blazor) ### Blazor Admin App **Admin Only** - is ideal for internal Admin Apps where the Admin UI is the Primary UI ![](/img/pages/okai/okai-blazor-admin.webp) ### Blazor Vue App **UI + Admin** - Creates a new [blazor-vue](https://blazor-vue.web-templates.io) template, ideal for Internet or public facing Apps which sports a full-featured content rich UI for a Web App's users whilst providing a back-office Admin UI for Admin Users to manage the App's data. ![](/img/pages/okai/okai-blazor-vue.webp) Clicking on the **Admin UI** button will take you to the Admin UI at `/admin`: ![](/img/pages/okai/okai-blazor-vue-admin.webp) ## Run Migrations After downloading you'll then need to run the DB Migrations to create the App's Identity Auth and DB Tables: :::sh npm run migrate ::: ## Instant CRUD UI Upon which you can hit the ground running and start using the Admin UI to manage the new Data Model RDBMS Tables! :::youtube 8buo_ce3SNM Using AutoQuery CRUD UI in a Text to Blazor App ::: ### Create new Records from Search Dialog We're continually improving the UX of the [AutoQueryGrid Component](/vue/autoquerygrid) used in generating CRUD UIs to enable a more productive and seamless workflow. A change added to that end that you can see in the above video is the ability to add new Records from a Search dialog: ![](/img/pages/autoquery/autoquerygrid-new2.webp) This now lets you start immediately creating new records without needing to create any lookup entries beforehand. ### References using non Foreign Key Properties Another declarative feature added is being able to define Foreign Key References in Data Models using non-Primary Keys. A good use-case for this is returning User Info for tables that store a Username instead of a User Id, e.g: ```csharp public class Booking : AuditBase { //.. [Reference(SelfId=nameof(CreatedBy), RefId=nameof(User.UserName), RefLabel=nameof(User.Name))] public User Employee { get; set; } } ``` Which works the same as a Foreign Key Primary Key Reference in returning the Referenced Data in API Responses, e.g: :::{.not-prose .text-lg .font-semibold .text-indigo-600 .hover:text-indigo-800} [/api/QueryBookings?Id=1](https://blazor-vue.web-templates.io/api/QueryBookings?Id=1) ::: ```json { "id": 1, "name": "First Booking!", "roomType": "Queen", "roomNumber": 10, "bookingStartDate": "2024-12-01T00:45:50.9098005Z", "bookingEndDate": "2024-12-08T00:45:50.9098123Z", "cost": 100, "couponId": "BOOK10", "employee": { "id": "684201c8-733a-453c-9f91-2004ccf23366", "userName": "employee@email.com", "firstName": "Test", "lastName": "Employee", "displayName": "Test Employee", "profileUrl": "/img/profiles/user2.svg" }, "createdDate": "2024-11-21T00:45:50.9098513Z", "createdBy": "employee@email.com", "modifiedDate": "2024-11-21T00:45:50.9098722Z", "modifiedBy": "employee@email.com" } ``` ### Lookup Input Component Lookup Input fields are implicitly assigned to Foreign Key properties by AutoQuery which is customizable using [Reference Fields](/vue/autoquerygrid#reference-fields). They can also now be assigned to other properties like [Custom Input Component](/vue/custom-inputs#custom-declarative-input-components) with `[Input(Type="lookup")]` ```csharp public class UpdateBooking : IPatchDb, IReturn { [Input(Type="lookup")] public int Id { get; set; } } ``` This could be assigned to Primary Key properties to replace its Text field with a modal lookup dialog for providing a GUI to search for a specified record's Primary Key. ![](/img/pages/vue/servicestackvue-lookup.webp) Input Options can be used to customize the `RefInfo` property of a Lookup Input, e.g: `refLabel` can be used to show a different label for the selected record: ```csharp [Input(Type="lookup", Options="{refLabel:'RoomNumber'}")] public int Id { get; set; } ``` Or you could choose to lookup a different Table by changing the `model`: ```csharp [Input(Type="lookup", Options = "{refId:'id',model:'Coupon',refLabel:'RoomNumber'}")] public int Id { get; set; } ``` This can also be applied in TypeScript Definitions with the `@input()` attribute, which by default is applied to all AutoQuery APIs: ```ts export class Booking extends AuditBase { @input({type:"lookup",options:"{refLabel:'RoomNumber'}"}) id: number } ``` Alternatively targeted attributes can be used to apply them to a single API, e.g: ```ts export class Booking extends AuditBase { @Update.input({type:"lookup",options:"{refLabel:'RoomNumber'}"}) id: number } ``` ## Audited Data Models The TypeScript Data Models enable a rapid development experience for defining an App's Data Models which are used to generate the necessary AutoQuery CRUD APIs to support an Admin UI. An example of the productivity of this approach is the effortless support for maintaining a detailed audit history for changes to select tables by inheriting from the `AuditBase` base class, e.g: ```ts export class Job extends AuditBase { ... } ``` Which can then be regenerated using the name of the TypeScript Model definitions: :::sh npx okai Jobs.d.ts ::: This will include additional `CreatedBy`, `CreatedDate`, `ModifiedBy`, `ModifiedDate`, `DeletedBy` and `DeletedDate` properties to the specified Table and also generates the necessary [Audit Behaviors](https://docs.servicestack.net/autoquery/crud#apply-generic-crud-behaviors) on the AutoQuery APIs to maintain the audit history for each CRUD operation. ### AutoQuery CRUD Audit Log As the **blazor-admin** and **blazor-vue** templates are configured to use [AutoQuery's Audit Log](/autoquery/audit-log) in its [Configure.AutoQuery.cs](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp/Configure.AutoQuery.cs) the Audit Behaviors also maintains an Audit Trail of all CRUD operations, viewable in the Admin UI: ![](/img/pages/okai/okai-audit-form.webp) ## AI powered Rapid App Development Workflow The `okai` npm tool works similar to the online [Text to Blazor App](https://servicestack.net/text-to-blazor) creator except it's a local tool that can add additional functionality to an existing project: The syntax for adding a new feature to your ServiceStack App is simply calling it with a text prompt: `npx okai ` :::sh npx okai "The kind of Feature you would like to add" ::: Where it will generate the Data Models, AutoQuery CRUD APIs, DB Migrations and Admin UI for the selected feature which you'll see after selecting the LLM Data Models you want to use, e.g: ```sh Selected 'deepseek-r1:70b' data models Saved: /projects/MyApp/MyApp.ServiceModel/Jobs.d.ts Saved: /projects/MyApp/MyApp.ServiceModel/Jobs.cs Saved: /projects/MyApp/wwwroot/admin/sections/Jobs.mjs Saved: /projects/MyApp/wwwroot/admin/sections/index.mjs Saved: /projects/MyApp/Migrations/Migration1001.cs Run 'dotnet run --AppTasks=migrate' to apply new migration and create tables To regenerate classes, update 'Jobs.d.ts' then run: $ okai Jobs.d.ts ``` Where okai will generate everything needed to support the feature in your App, including: - `MyApp.ServiceModel/Jobs.d.ts` - TypeScript Data Models - `MyApp.ServiceModel/Jobs.cs` - AutoQuery CRUD APIs and Data Models - `wwwroot/admin/sections/Jobs.mjs` - Admin UI Section - requires `blazor-admin` or `blazor-vue` template - `MyApp/Migrations/Migration1001.cs` - DB Migrations - requires project with [OrmLite DB Migrations](https://docs.servicestack.net/ormlite/db-migrations) ## Creating Data Models from Scratch You can also choose to create your TypeScript Data Models from scratch if you prefer not to start with generated AI Models, by running: :::sh npx okai init Todos.d.ts ::: This will create a basic Data Model and run the code generation to generate the necessary files for it: ```txt Saved: /projects/Acme/Acme.ServiceModel/api.d.ts Saved: /projects/Acme/Acme.ServiceModel/Todos.cs Saved: /projects/Acme/Acme/Migrations/Migration1002.cs Saved: /projects/Acme/Acme/wwwroot/admin/sections/Todos.mjs Saved: /projects/Acme/Acme/wwwroot/admin/sections/index.mjs Saved: /projects/Acme/Acme.ServiceModel/Todos.d.ts Run 'npm run migrate' to apply the new migration and create the new tables or: $ dotnet run --AppTasks=migrate ``` With `Todos.d.ts` include the a reference to the [api.d.ts](https://okai.servicestack.com/api.d.ts) schema and the necessary header config specifying which files it should generate along with an empty class where you can start adding your Data Models for this feature: ```ts /// export type Config = { prompt: "New Todo" api: "~/Acme.ServiceModel/Todos.cs" migration: "~/Acme/Migrations/Migration1002.cs" uiMjs: "~/Acme/wwwroot/admin/sections/Todos.mjs" } @tag("Todos") export class Todo { id: number name: string } ``` ## Removing Data Models If for whatever reason don't want the generated Data Models anymore, you can remove them from your code-base with: :::sh npx okai rm Todos.d.ts ::: Which will remove the `*.d.ts` Data Models and all its associated generated files. ## Run Migrations In order to create the necessary tables for any new functionality, you'll need to run the DB Migrations. If migrations have never been run before, you can run the `migrate` npm script to create the initial database: :::sh npm run migrate ::: This also lets you recreate it from scratch by running it after deleting the App's database (e.g. `App_Data/app.db`) ### Rerun Last Migration If migrations have already been run, run the `rerun:last` npm script instead to **drop** and **re-run** the last migration: :::sh npm run rerun:last ::: ## Customize Data Models The data models defined in the TypeScript Declaration file e.g. `Jobs.d.ts` is what drives the generation of the Data Models, APIs, DB Migrations and Admin UIs. This can be further customized by editing the TypeScript Declaration file and re-running the `okai` tool with the name of the TypeScript Declaration file, e.g. `Jobs.d.ts`: :::sh npx okai Jobs.d.ts ::: Which will re-generate the Data Models, APIs, DB Migrations and Admin UIs based on the updated Data Models. ![](/img/pages/okai/okai-Employees.webp) :::tip You only need to specify the `Jobs.d.ts` TypeScript filename (i.e. not the filepath) from anywhere within your .NET solution ::: ### Live Code Generation If you'd prefer to see the generated code in real-time you can add the `--watch` flag to watch the TypeScript Declaration file for changes and automatically re-generate the generated files on Save: :::sh npx okai Jobs.d.ts --watch ::: ## Declarative AI powered Features The approach okai uses is very different from most AI tools in which okai only uses AI to generate the initial Data Models within a TypeScript Declaration `*.d.ts` file. This is possible in ServiceStack since a significant portion of an App's functionality can be [declaratively applied](https://docs.servicestack.net/locode/declarative) inc. [AutoQuery CRUD APIs](https://docs.servicestack.net/autoquery/crud) which only requires a typed Request DTOs to define the shape of the API to be implemented. From the Data Models, the rest of the feature is generated using declarative classes depending on the template used. ### Generated Admin CRUD UI To generate a CRUD Admin UI you'll need to use okai within a new Blazor Admin project or Blazor Vue ([blazor-vue](https://blazor-vue.web-templates.io)) project: :::sh x new blazor-admin Acme ::: Which support a "Modular no-touch" Admin UI that will appear under a new group in the Admin Sidebar: ![](/img/pages/okai/okai-blazor-admin.webp) ## Modular Code Generation Instead of unleashing AI on your code-base unabated, okai only uses AI to generate isolated functionality into grouped "no touch" source files that can be easily maintained and extended. Creating a new Project with a similar prompt above would create a new project with the new source files (marked `*`) added to the existing project: ### APIs ```files /MyApp.ServiceModel Bookings.cs api.d.ts* Employees.cs* Employees.d.ts* ``` ### Migration ```files /MyApp/Migrations Migration1000.cs Migration1001.cs* ``` ### UI ```files /MyApp/wwwroot/admin /sections Bookings.mjs Employees.mjs* index.mjs* index.html ``` ## TypeScript Schema In addition to being a great DSL for defining Data Models, using TypeScript also lets us define a schema containing all the C# Types, interfaces, and attributes used in defining APIs, DTOs and Data Models in the accompanying [api.d.ts](https://okai.servicestack.com/api.d.ts) file. This now lets us use TypeScript to define the [Bookings.cs](https://github.com/NetCoreTemplates/blazor-vue/blob/main/MyApp.ServiceModel/Bookings.cs) AutoQuery APIs and Data Models which blazor-admin uses instead in its [Bookings.d.ts](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp.ServiceModel/Bookings.d.ts): ```ts /// export type Config = { prompt: "New Booking" api: "~/MyApp.ServiceModel/Bookings.cs" migration: "~/MyApp/Migrations/Migration1001.cs" uiMjs: "~/MyApp/wwwroot/admin/sections/Bookings.mjs" } export enum RoomType { Single, Double, Queen, Twin, Suite, } @Read.route("/bookings","GET") @Read.route("/bookings/{Id}","GET") @Read.description("Find Bookings") @Create.route("/bookings","POST") @Create.description("Create a new Booking") @Update.notes("Find out how to quickly create a C# Bookings App from Scratch") @Update.route("/booking/{Id}","PATCH") @Update.description("Update an existing Booking") @Delete.route("/booking/{Id}","DELETE") @Delete.description("Delete a Booking") @tag("Bookings") @icon({svg:"..."}) @notes("Captures a Persons Name & Room Booking information") @description("Booking Details") @validateHasRole("Employee") export class Booking extends AuditBase { @autoIncrement() id: number @Create.description("Name this Booking is for") @validateNotEmpty() name: string roomType: RoomType @validateGreaterThan(0) roomNumber: number @intlDateTime(DateStyle.Long) bookingStartDate: Date @intlRelativeTime() bookingEndDate?: Date @intlNumber({currency:"USD"}) @validateGreaterThan(0) cost: decimal @ref({model:"nameof(Coupon)",refId:"nameof(Coupon.Id)",refLabel:"nameof(Coupon.Description)"}) @references("typeof(Coupon)") couponId?: string @reference() discount?: Coupon @input({type:"textarea"}) notes?: string cancelled?: boolean @reference({selfId:"nameof(CreatedBy)",refId:"nameof(User.UserName)",refLabel:"nameof(User.DisplayName)"}) employee: User } @tag("Bookings") @icon({svg:"..."}) export class Coupon extends AuditBase { id: string description: string discount: number expiryDate: Date } ``` The benefit of this approach being that you can make a change to the Data Models and rerun the okai tool to regenerate the AutoQuery APIs, DB Migrations and Admin UIs. :::sh npx okai Bookings.d.ts ::: Which will regenerate its: - APIs: [MyApp.ServiceModel/Bookings.cs](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp.ServiceModel/Bookings.cs) - DB Migration: [MyApp/Migrations/Migration1000.cs](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp/Migrations/Migration1000.cs) - Admin UI: [/wwwroot/admin/sections/Bookings.mjs](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp/wwwroot/admin/sections/Bookings.mjs) What files will be generated is controlled by its `Config` section: ```ts export type Config = { prompt: "New Booking" api: "~/MyApp.ServiceModel/Bookings.cs" migration: "~/MyApp/Migrations/Migration1001.cs" uiMjs: "~/MyApp/wwwroot/admin/sections/Bookings.mjs" } ``` So if no longer want the code regeneration to update the DB Migration for it, you can just remove it from the Config. ## Rerunning Code Generation The data models defined in the TypeScript Declaration file e.g. `Bookings.d.ts` is what drives the generation of the Data Models, APIs, DB Migrations and Admin UIs. This can be further customized by editing the TypeScript Declaration file and re-running the `okai` tool with the name of the TypeScript Declaration file, e.g. `Bookings.d.ts`: :::sh npx okai Bookings.d.ts ::: Which will re-generate the Data Models, APIs, DB Migrations and Admin UIs based on the updated Data Models. ![](/img/pages/okai/okai-Employees.webp) Or add `--watch` to watch the TypeScript `*.d.ts` file for changes and automatically run code generation on Save: :::sh npx okai Bookings.d.ts --watch ::: :::tip You only need to specify the `Bookings.d.ts` TypeScript filename (i.e. not the filepath) from anywhere within your .NET solution ::: ### Single Data Model One challenge with this approach is that there's only a single class used to define attributes for the Data Model, Request and Response DTOs for all AutoQuery CRUD APIs. ### Smart API and Data Model attributes The okai tool resolves some issues with smart generation of attributes where any **"Data Model Attributes"** like `[Icon]` class and `[AutoIncrement]` property attributes are only generated on the Data Model: ```ts @icon({svg:"..."}) export class Booking { @autoIncrement() id: number @intlNumber({currency:"USD"}) cost: decimal } ``` Whilst **"API Attributes"** like `[Tag]` and `[ValidateHasRole]` class attribute and `[ValidateGreaterThan]` property attributes and are only generated on the APIs Request DTOs: ```ts @tag("Bookings") @validateHasRole("Employee") export class Booking { @validateGreaterThan(0) cost: decimal } ``` ### Using C# Types in TypeScript Models As JavaScript only has a limited set of types, the TypeScript **api.d.ts** schema also includes the built-in C# Types used when defining APIs, DTOs and Data Models which you'll be able to use when your APIs need to use a specific .NET type, e.g: ```ts export class Booking extends AuditBase { id: number name: string roomNumber: number bookingStartDate: Date bookingEndDate?: DateOnly cost: decimal cancelled?: boolean } ``` Which uses the `DateOnly` and `decimal` .NET Types in its code generation: ```csharp public class Booking : AuditBase { [AutoIncrement] public int Id { get; set; } public string Name { get; set; } public int RoomNumber { get; set; } public DateTime BookingStartDate { get; set; } public DateOnly? BookingEndDate { get; set; } public decimal Cost { get; set; } public bool? Cancelled { get; set; } } ``` ### API Targeted Attributes When you need to add attributes to a specific API Request DTO you can use a **CRUD prefix** to have it only applied to that specific AutoQuery API, e.g: ```ts @Read.route("/bookings","GET") @Read.route("/bookings/{Id}","GET") @Create.route("/bookings","POST") ``` Where it would only the generated on the AutoQuery API that it targets, e.g: ```csharp [Route("/bookings", "GET")] [Route("/bookings/{Id}", "GET")] public class QueryBookings : QueryDb { ... } [Route("/bookings", "POST")] public class CreateBooking : ICreateDb, IReturn { ... } ``` In addition to `Create.*`, `Read.*`, `Update.*`, `Delete.*` attributes to target specific AutoQuery CRUD APIs, you can also use `Write.*` to target all `Create`, `Update`, `Delete` write APIs. ### Ambiguous Attributes Attributes that can be annotated on both the Data Model and API Request DTOs like `[Notes]` and `[Description]` are only generated on the Data Model and require using targeted attributes to apply to them to API Request DTOs, e.g: ```ts @Read.description("Find Bookings") @Create.description("Create a new Booking") @Update.notes("Find out how to quickly create a C# Bookings App from Scratch") @Update.description("Update an existing Booking") @Delete.description("Delete a Booking") @notes("Captures a Persons Name & Room Booking information") @description("Booking Details") export class Booking extends AuditBase { ... } ``` Where the non-prefixed `@notes` and `@description` attributes are only generated on the Data Model whilst the targeted attributes are generated on their respective DTOs, e.g: ```csharp [Description("Find Bookings")] public class QueryBookings : QueryDb { ... } [Description("Create a new Booking")] public class CreateBooking : ICreateDb, IReturn { ... } [Notes("Find out how to quickly create a C# Bookings App from Scratch")] [Description("Update an existing Booking")] public class UpdateBooking : IPatchDb, IReturn { ... } [Description("Delete a Booking")] public class DeleteBooking : IDeleteDb, IReturnVoid { ... } [Description("Booking Details")] [Notes("Captures a Persons Name & Room Booking information")] public class Booking : AuditBase { ... } ``` ### Special Attribute Values There's special behavior for `"nameof(...)"` and `"typeof(...)"` string attribute values where: ```ts export class Booking extends AuditBase { @ref({model: "nameof(Coupon)", refId: "nameof(Coupon.Id)", refLabel: "nameof(Coupon.Description)"}) @references("typeof(Coupon)") couponId?: string } ``` Will be generated with native C# syntax, i.e. instead of as strings: ```csharp public class Booking : AuditBase { [Ref(Model=nameof(Coupon),RefId=nameof(Coupon.Id),RefLabel=nameof(Coupon.Description))] [References(typeof(Coupon))] public string? CouponId { get; set; } } ``` ### Changing Default Attributes To improve the default out-of-the-box experience some attributes are included by default, including: - `[Icon]` attribute on Data Models based on the Data Model name - prevent by adding empty `@icon()` attribute - `[AutoIncrement]` on `id` number properties if no other `[PrimaryKey]` attribute is defined - prevent by adding `@primaryKey()` or `@autoId()` - `[Validate*]` attributes added to Create/Update APIs on non-nullable properties - prevent by adding empty `@validate()` attribute Here's an example which changes the default behavior for the default attributes above: ```ts @icon() export class Todo { @primaryKey() id: number @validate() name: string } ``` Which will generate the C# APIs without the `[Icon]` and `[Validate]` attributes and replace `[AutoIncrement]` with `[PrimaryKey]`, e.g: ```csharp public class CreateTodo : ICreateDb, IReturn { [ValidateGreaterThan(0)] public int Id { get; set; } public string Name { get; set; } } public class Todo { [PrimaryKey] public int Id { get; set; } public string Name { get; set; } } ``` ### Modifying ApplicationUser In many cases the AI Models will want to generate a `User` class for their AI models. But as Blazor Apps are already configured to use an `ApplicationUser` Identity Auth User class, the C# code generation only generates the `User` class in a block comment with an instruction to merge it with your existing `User` class if you want to, e.g: ```csharp /* merge with User DTO /// /// Interface defining the structure for a JobApplication. /// Represents a user's application to a specific job. /// public class User { [AutoIncrement] public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } /// /// Optional URL to the user's resume /// public string? ResumeUrl { get; set; } } */ ``` If you wish to add additional properties, you'll first need to add it your `ApplicationUser` class, e.g: ```csharp public class ApplicationUser : IdentityUser { public string? FirstName { get; set; } public string? LastName { get; set; } public string? DisplayName { get; set; } public string? ProfileUrl { get; set; } /// /// Optional URL to the user's resume /// public string? ResumeUrl { get; set; } } ``` ### Regenerating Identity Auth EF Migrations You'll then need to regenerate the EF Migration to update the `AspNetUsers` table with the new columns by running the `init-ef` npm script: :::sh npm run init-ef ::: Which will delete the existing Migrations and create a new Migration to update the Identity Auth tables: ```json { "scripts": { "init-ef": "node -e 'fs.readdirSync(`Migrations`).filter(x => !x.startsWith(`Migration`)).forEach(x => fs.rmSync(`Migrations/${x}`))' && dotnet ef migrations add CreateIdentitySchema", } } ``` You can then delete your Primary Database (e.g. App_Data/app.db) and re-run the `migrate` npm script to recreate it: :::sh npm run migrate ::: If you want the additional property to also be included in API Responses you'll also need to add it to your `User` DTO, e.g: ```csharp /// /// Public User DTO /// [Alias("AspNetUsers")] public class User { public string Id { get; set; } public string UserName { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public string? DisplayName { get; set; } public string? ProfileUrl { get; set; } public string? ResumeUrl { get; set; } } ``` Which OrmLite and AutoQuery will use to query Identity Auth's `AspNetUsers` table. ### Custom APIs When you need more fine-grained control over the generated APIs, you can "takeover" the generation of an AutoQuery API by explicitly defining it yourself. So if you prefer to use explicit API Request DTOs or need to control the exact properties generated in each API, you can define the API Request DTOs yourself where when exists will skip generation for that API, e.g: ```ts @tag("Bookings") @notes("Captures a Persons Name & Room Booking information") @route("/bookings","GET") @route("/bookings/{Id}","GET") @autoApply(Behavior.AuditQuery) @description("Find Bookings") export class QueryBookings extends QueryDb { id?: number } ``` See [Custom APIs docs](/autoquery/okai-models#custom-apis) for the full example. ## Generate CRUD APIs and UIs for existing DBs A core piece of functionality in the [Text to Blazor CRUD App](/autoquery/text-to-blazor) feature is distilling an AI Prompt into TypeScript classes that can be [further customized](/autoquery/okai-models#customize-data-models) to generate AutoQuery CRUD APIs and Admin UIs for managing the underlying RDBMS tables. ### Blueprint for Code Generation The TypeScript Data Models serve as the blueprint for generating everything needed to support the feature in your App, including the AutoQuery **CRUD APIs**, **Admin UIs** and **DB Migrations** that can re-create the necessary tables from scratch. ## 1. Generate RDBMS Metadata The first step in generating TypeScript Data Models is to capture the metadata from the existing RDBMS tables which we can do with the `App.json` [AppTask](https://docs.servicestack.net/app-tasks) below which uses your App's configured RDBMS connection to generate the Table Definitions for all tables in the specified RDBMS connection and schema to the file of your choice (e.g `App_Data/App.json`): ```csharp AppTasks.Register("App.json", args => appHost.VirtualFiles.WriteFile("App_Data/App.json",ClientConfig.ToSystemJson( migrator.DbFactory.GetTables(namedConnection:null, schema:null)))); ``` This task can then be run from the command line with: :::sh dotnet run --AppTasks=App.json ::: Which generates `App_Data/App.json` containing the table definition metadata for all tables in the specified RDBMS, e.g: ```json [ { "name": "AspNetUserClaims", "columns": [ { "columnName": "Id", "columnOrdinal": 0, "columnSize": -1, "numericPrecision": 0, "numericScale": 0, "isUnique": true, "isKey": true, "baseCatalogName": "techstacks", "baseColumnName": "Id", "baseSchemaName": "public", "baseTableName": "AspNetUserClaims", "dataType": "System.Int32", "allowDBNull": false, "providerType": 9, "isAliased": false, "isExpression": false, "isAutoIncrement": true, "isRowVersion": false, "isHidden": false, "isLong": false, "isReadOnly": false, "dataTypeName": "integer", "columnDefinition": "INTEGER PRIMARY KEY AUTOINCREMENT" }, ], ... ] ``` ### Different Connection or DB Schema If you prefer to generate the metadata for a different connection or schema, you can create a new AppTask with your preferred `namedConnection` and/or `schema`, e.g: ```csharp AppTasks.Register("Sales.json", args => appHost.VirtualFiles.WriteFile("Sales.json", ClientConfig.ToSystemJson( migrator.DbFactory.GetTables(namedConnection:"reports",schema:"sales")))); ``` That you could then generate with: :::sh dotnet run --AppTasks=Sales.json ::: ## 2. Generate TypeScript Data Models The next step is to generate TypeScript Data Models from the captured metadata which can be done with the `okai` tool by running the `convert` command with the path to the `App.json` JSON table definitions which will generate the TypeScript Data Models to stdout which can be redirected to a file in your **ServiceModel** project, e.g: :::sh npx okai convert App_Data/App.json > ../MyApp.ServiceModel/App.d.ts ::: ## 3. Generate CRUD APIs and Admin UIs The data models defined in the `App.d.ts` TypeScript Declaration file is what drives the generation of the Data Models, APIs, DB Migrations and Admin UIs. This can be further customized by editing the TypeScript Declaration file and re-running the `okai` tool with just the filename, e.g: :::sh npx okai App.d.ts ::: Which will re-generate the Data Models, APIs, DB Migrations and Admin UIs based on the updated Data Models. ![](/img/pages/okai/npx-okai-App.png) :::tip You only need to specify the `App.d.ts` TypeScript filename (i.e. not the filepath) from anywhere within your .NET solution ::: ## Free LLM Chat Prompts As part of the development of okai, we've also made available a generic **chat** prompt that can be used as a convenient way to conduct personal research against many of the worlds most popular Large Language Models - for Free! :::{.px-8} ![](/img/pages/okai/okai-chat.webp) ::: You can just start immediately using the `npx okai chat` script to ask LLMs for assistance: :::sh npx okai chat "command to copy a folder with rsync?" ::: This will use the default model (currently codestral:22b) to answer your question. ### Select Preferred Model You can also use your preferred model with the `-m ` flag with either the model **name** or its **alias**, e.g you can use [Microsoft's PHI-4 14B](https://techcommunity.microsoft.com/blog/aiplatformblog/introducing-phi-4-microsoft%E2%80%99s-newest-small-language-model-specializing-in-comple/4357090) model with: :::sh npx okai -m phi chat "command to copy folder with rsync?" ::: ### List Available Models We're actively adding more great performing and leading experimental models as they're released. You can view the list of available models with `ls models`: :::sh npx okai ls models ::: Which at this time will return the following list of available models along with instructions for how to use them: ```txt USAGE (5 models max): a) OKAI_MODELS=codestral,llama3.3,flash b) okai -models codestral,llama3.3,flash c) okai -m flash chat FREE MODELS: claude-3-haiku (alias haiku) codestral:22b (alias codestral) deepseek-r1:32b deepseek-r1:671b (alias deepseek-r1) deepseek-r1:70b deepseek-r2:32b deepseek-v3:671b (alias deepseek) gemini-flash-1.5 gemini-flash-1.5-8b (alias flash-8b) gemini-flash-2.0 (alias flash) gemini-flash-lite-2.0 (alias flash-lite) gemini-flash-thinking-2.0 (alias flash-thinking) gemini-pro-2.0 (alias gemini-pro) gemma2:9b (alias gemma) gpt-3.5-turbo (alias gpt-3.5) gpt-4o-mini llama3.1:70b (alias llama3.1) llama3.3:70b (alias llama3.3) llama3:8b (alias llama3) mistral-nemo:12b (alias mistral-nemo) mistral-small:24b (alias mistral-small) mistral:7b (alias mistral) mixtral:8x22b mixtral:8x7b (alias mixtral) nova-lite nova-micro phi-4:14b (alias phi,phi-4) qwen-plus qwen-turbo qwen2.5-coder:32b (alias qwen2.5-coder) qwen2.5:32b qwen2.5:72b (alias qwen2.5) qwq:32b (alias qwq) qwq:72b PREMIUM MODELS: * claude-3-5-haiku claude-3-5-sonnet claude-3-7-sonnet (alias sonnet) claude-3-sonnet gemini-pro-1.5 gpt-4 gpt-4-turbo gpt-4o mistral-large:123b nova-pro o1-mini o1-preview o3-mini qwen-max * requires valid license: a) SERVICESTACK_LICENSE= b) SERVICESTACK_CERTIFICATE= c) okai -models -license ``` Where you'll be able to use any of the great performing inexpensive models listed under `FREE MODELS` for Free. Whilst ServiceStack customers with an active commercial license can also use any of the more expensive and better performing models listed under `PREMIUM MODELS` by either: a) Setting the `SERVICESTACK_LICENSE` Environment Variable with your **License Key** b) Setting the `SERVICESTACK_CERTIFICATE` Variable with your **License Certificate** c) Inline using the `-license` flag with either the **License Key** or **Certificate** ### FREE for Personal Usage To be able to maintain this as a free service we're limiting usage as a tool that developers can use for personal assistance and research by limiting usage to **60 requests /hour** which should be more than enough for most personal usage and research whilst deterring usage in automated tools. :::tip info Rate limiting is implemented with a sliding [Token Bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket) that replenishes 1 additional request every 60s ::: ## AI Server Improvements We've continued making improvements to [AI Server](/ai-server/) with fixes to Background Jobs filtering and also including support for these newer models: | Provider | Models | |----------|--------| | OpenAI | `o3-mini` | | Qwen | `qwq` `qwen-turbo` `qwen-plus` `qwen-max` `qwen-vl-plus` | | DeepSeek | `deepseek-v3` `deepseek-r1` | | Google | `gemini-flash-2.0` `gemini-flash-lite-2.0` `gemini-flash-thinking-2.0` `gemini-pro-2.0` | | Amazon | `nova-micro` `nova-lite` `nova-pro` | | Others | `llama3.3` `phi4` `mistral-small` | We've also published a new Video with configuring AI Server to use Ollama endpoints: :::youtube S1Xw0iQLa2c Using Ollama with AI Server ::: ## Reported Vulnerabilities We've received and resolved 2 Vulnerability Reports during this release. ### ZDI-CAN-25837 The report for this vulnerability reads: > This advisory presents a Remote Code Execution vulnerability in ServiceStack JSON/JSV deserialization. Attack complexity was evaluated as High in case of a remote exploitation, because the attacker needs a possibility to drop the DLL or EXE file to the filesystem. Typically, this can be achieved in two different ways: > * Using a different vulnerability in targeted application, which allows to drop a file to the filesystem, or > * Using a legitimate functionality that an application may expose, which allows to upload a file to the filesystem (upload location does not matter). > > The root-cause for this vulnerability exists in the type resolving mechanism implemented in the `ServiceStack.NetFxPclExport.FindType(string, string)` method. ### Resolution This vulnerability was resolved in [this commit](https://github.com/ServiceStack/ServiceStack/commit/0338d1d45aadd6d14e3bcda125fcdb61e7ec89af) where it's no longer possible to reference a Type on the local filesystem to instantiate. This validation can be overridden with: ```csharp AssemblyUtils.ValidateTypeName = typeName => ... ``` ### ZDI-CAN-25834 The report for this vulnerability reads: > This advisory presents an NTLM Relaying vulnerability in ServiceStack `HttpUtils.GetErrorResponse` method. Attack Complexity for this vulnerability was assessed as High, because I think that usage of the `GetErrorResponse` method with the attacker-controlled input is rather rare. With the issue being some of our [HTTP Utils](/http-utils) convenience wrappers over .NET APIs not casting to `HttpWebRequest` to prevent File URLs: > At `[1]`, the `WebRequest` is created with the `WebRequest.Create` method. This is a root-cause for this vulnerability. This operation is missing a cast to the `HttpWebRequest`. According to this, the attacker can e.g. provide a URL with `file://` protocol, and the `FileWebRequest` object will be created. #### Proof of concept: This code implements a minimal example, where we can pass the malicious URL to the `Main` method: ```csharp static void Main(string[] args) { HttpWebResponse resp = HttpUtils.GetErrorResponse(args[0]); } ``` ### Resolution As our HTTP Utils are just convenience wrapper over .NET APIs we don't believe this is a real vulnerability since the Proof of Concept could just as easily call the `WebRequest.Create(url)` .NET API directly instead of our wrapper. But in the interest of marking it as resolved we've replaced our usages of `WebRequest.Create(url)` with ` WebRequest.CreateHttp(url)` which now prevents our convenience APIs for being used to access files in [this commit](https://github.com/ServiceStack/ServiceStack/commit/e849525018527d4503770019f12ea6f84177f4ff). # Release Notes History Source: https://docs.servicestack.net/release-notes-history ## 2025 - [v8.6](/releases/v8_06) ## 2024 - [v8.5](/releases/v8_05) - [v8.4](/releases/v8_04) - [v8.3](/releases/v8_03) - [v8.2](/releases/v8_02) - [v8.1](/releases/v8_01) ## 2023 - [v8](/releases/v8_00) - [v6.11](/releases/v6_11) - [v6.10](/releases/v6_10) - [v6.9](/releases/v6_09) - [v6.8](/releases/v6_08) - [v6.7](/releases/v6_07) - [v6.6](/releases/v6_06) ## 2022 - [v6.5](/releases/v6_05) - [v6.4](/releases/v6_04) - [v6.3](/releases/v6_03) - [v6.2](/releases/v6_02) - [v6.1](/releases/v6_01) - [v6](/releases/v6_00) ## 2021 - [v5.13](/releases/v5_13) - [v5.12](/releases/v5_12) - [v5.11](/releases/v5_11) ## 2020 - [v5.10](/releases/v5_10) - [v5.9](/releases/v5_9) - [v5.8](/releases/v5_8) ## 2019 - [v5.7](/releases/v5_7) - [v5.6](/releases/v5_6) - [v5.5](/releases/v5_5) ## 2018 - [v5.4](/releases/v5_4) - [v5.2](/releases/v5_2) - [v5.1.0](/releases/v5_1_0) - [v5.0.2](/releases/v5_0_0) ## 2017 - [v5.0.0](/releases/v5_0_0#v5-release-notes) - [v4.5.14](/releases/v4_5_14) - [v4.5.10](/releases/v4_5_10) - [v4.5.8](/releases/v4_5_8) - [v4.5.6](/releases/v4_5_6) ## 2016 - [v4.5.2](/releases/v4_5_2) - [v4.5.0](/releases/v4_5_0) - [v4.0.62](/releases/v4_0_62) - [v4.0.60](/releases/v4_0_60) - [v4.0.56](/releases/v4_0_56) - [v4.0.54](/releases/v4_0_54) - [v4.0.52](/releases/v4_0_52) ## 2015 - [v4.0.50](/releases/v4_0_50) - [v4.0.48](/releases/v4_0_48) - [v4.0.46](/releases/v4_0_46) - [v4.0.44](/releases/v4_0_44) - [v4.0.42](/releases/v4_0_42) - [v4.0.40](/releases/v4_0_40) - [v4.0.38](/releases/v4_0_38) - [v4.0.36](/releases/v4_0_36) ## 2014 - [v4.0.35](/releases/v4_0_35) - [v4.0.34](/releases/v4_0_34) - [v4.0.33](/releases/v4_0_33) - [v4.0.32](/releases/v4_0_32) - [v4.0.31](/releases/v4_0_31) - [v4.0.30](/releases/v4_0_30) - [v4.0.24](/releases/v4_0_24) - [v4.0.23](/releases/v4_0_23) - [v4.0.22](/releases/v4_0_22) - [v4.0.21](/releases/v4_0_21) - [v4.0.19](/releases/v4_0_19) - [v4.0.18](/releases/v4_0_18) - [v4.0.15](/releases/v4_0_15) - [v4.0.12](/releases/v4_0_12) - [v4.0.11](/releases/v4_0_11) - [v4.0.10](/releases/v4_0_10) - [v4.0.09](/releases/v4_0_09) - [v4.0.08](/releases/v4_0_08) - [v4.0.06](/releases/v4_0_06) - [v4.0.0](/releases/v4_0_0) ## 2013 and prior - [Older v3 Release Notes](/release-notes-v3) # Pre Release NuGet Packages Source: https://docs.servicestack.net/pre-release ## ServiceStack Pre-Release NuGet Packages Our interim pre-release NuGet packages in between major releases on NuGet are published to [Feedz.io](https://feedz.io/). ::: tip If preferred, the pre-release packages are also available in our [GitHub Packages Registry](/gh-nuget) ::: ### Add using Mix If you have the [dotnet x tool](/dotnet-tool) installed, you can configure your projects by downloading `NuGet.Config` in the same folder as your **.sln** :::sh x mix feedz ::: ### Add using VS .NET Instructions to add ServiceStack's Pre-Release packages feed to VS .NET are: 1. Go to **Tools** > **Options** > **Nuget Package Manager** > **Package Sources** 2. Add the Source `https://f.feedz.io/servicestack/pre-release/nuget/index.json` with the name of your choice, e.g. `ServiceStack Pre-Release` After registering the feed it will show up under NuGet package sources when opening the NuGet package manager dialog: ![NuGet Package Manager](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/wikis/myget/package-manager-ui.png) Which will allow you to search and install pre-release packages from the selected Pre Release packages feed. ### Adding Pre-Release NuGet feed without VS .NET If you're not using or don't have VS .NET installed, you can add the MyGet feed to your NuGet.config at `%AppData%\NuGet\NuGet.config`: ```xml ``` ## Redownloading Pre Release packages If you've already packages with the **same version number** from Feedz previously installed, you will need to manually delete the NuGet `/packages` folder for NuGet to pull down the latest packages. ### Clear NuGet Package Cache You can clear your local NuGet packages cache in any OS by running the command-line below in your favorite Terminal: :::sh nuget locals all -clear ::: If `nuget` is not in your Systems `PATH`, it can also be invoked from the `dotnet` tool: :::sh dotnet nuget locals all --clear ::: Within VS .NET you can clear them from **Tools** > **Options** > **Nuget Package Manager** and click **Clear All NuGet Cache(s)**: ![Clear Packages Cache](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/wikis/myget/clear-package-cache.png) Alternatively on Windows you can delete the Cached NuGet packages manually with: :::sh del %LOCALAPPDATA%\NuGet\Cache\*.nupkg /q ::: ### Full Package Clean In most cases clearing the NuGet packages cache will suffice, sometimes you'll also need to manually delete other local packages caches delete all NuGet packages in `/packages` folder: :::sh rd /q /s packages ::: delete `/bin` and `/obj` folders in host project :::sh rd /q /s bin obj ::: ## Versioning Scheme All ServiceStack packages are published together in "lockstep" with the same version number so the effort to upgrade ServiceStack projects can be done all at same time, with low frequency. ServiceStack Versions adopt the following 3-part versioning scheme: ``` {MAJOR}.{MINOR}.{PATCH} ``` ### Major versions The `{MAJOR}` is reserved for Major releases like [v5 containing structural changes](/releases/v5_0_0) that may require changes to external environment and/or project configurations. Major structural releases should be few and far between with currently no plans for any in the immediate future. ### Minor versions The `{MINOR}` version is used for major ServiceStack official releases which will have a `{PATCH}` version of **0**. #### Patch versions The `{PATCH}` version is used to distinguish updates from normal releases where a `{PATCH}` above **0** indicates an Enhancement Release. Whilst we want to minimize the effort for Customers to upgrade we also want to make any fixes or enhancements to the previous release available sooner as there are often fixes reported and resolved immediately after each release and made available in our **pre-release NuGet packages feed** that most Customers wont get until the next major Release on NuGet. To deliver updates sooner we dedicate time immediately after each release to resolving issues and adding enhancements to existing features so we can publish update releases before starting work on new major features. Update releases will be primarily additive and minimally disruptive so they're safe to upgrade. - An **even** `{PATCH}` version number indicates an "Update" release published to **NuGet**. - An **odd** version number indicates a "pre-release" version that's only **available on Feedz.io** or [GitHub Packages](/gh-nuget) Versioning scheme example: - **v5.0.0** - Current Major Release with structural changes - v5.0.2 - Enhancement of Major v5.0.0 Release - v5.0.3 - Pre-release packages published to MyGet only - v5.0.4? - Enhancement of Major v5.0.0 Release (if any) - **v5.1.0** - Next Major Release - v5.1.1 - Pre-release packages published to MyGet only - v5.1.2? - Enhancement of Major v5.1.0 Release (if any) - ... - **v6.0.0** - Next Major Release with structural changes # Create your first WebService Source: https://docs.servicestack.net/create-your-first-webservice This is a quick walkthrough of getting your first web service up and running whilst having a look at the how some of the different components work. ## Step 1: Install the x dotnet tool First we want to install the [x dotnet tool](/dotnet-tool): :::sh dotnet tool install --global x ::: The [dotnet tools](/dotnet-tool) are ServiceStack's versatile companion giving you quick access to a lot of its high-level features including generating mobile, web & desktop DTOs with [Add ServiceStack Reference](/add-servicestack-reference) generating [gRPC Clients and proto messages](/grpc/), quickly [apply gists](/mix-tool) to your project enabled by ServiceStack's effortless [no-touch Modular features](/modular-startup), [command-line API access](/post-command), it even includes a [lisp REPL](https://sharpscript.net/lisp/) should you need to explore your [remote .NET Apps in real-time](https://sharpscript.net/lisp/#techstacks-tcp-lisp-repl-demo). ## Step 2: Selecting a template Importantly, the dotnet tools lets you create [.NET 6, .NET Framework](/templates/dotnet-new) and [ASP.NET Core on .NET Framework](/templates/corefx) projects. Unless you're restricted to working with .NET Framework you'll want to start with a [.NET 6 project template](/templates/dotnet-new#usage), for this example we'll start with the Empty [web](https://github.com/NetCoreTemplates/web) template which implicitly uses the folder name for the Project Name: :::sh x new web WebApp ::: ## Step 3: Run your project Press `Ctrl+F5` to run your project! You should see an already working API integration using [@servicestack/client](/javascript-client) library to call your App's [JavaScript DTOs](/javascript-add-servicestack-reference) and links to calling your API from [API Explorer](/api-explorer): #### Watched builds A recommended alternative to running your project from your IDE is to run a watched build using `dotnet watch` from a terminal: :::sh dotnet watch ::: Where it will automatically rebuild & restart your App when it detects any changes to your App's source files. ### How does it work? Now that your new project is running, let's have a look at what we have. The template comes with a single web service route which comes from the Request DTO (Data Transfer Object) which is located in the [Hello.cs](https://github.com/NetCoreTemplates/web/blob/master/MyApp.ServiceModel/Hello.cs) file: ```csharp [Route("/hello/{Name}")] public class Hello : IReturn { public string Name { get; set; } } public class HelloResponse { public string Result { get; set; } } ``` The `Route` attribute is specifying what path `/hello/{Name}` where `{Name}` binds its value to the public string property of **Name**. Let's access the route to see what comes back. Go to the following URL in your address bar: /hello/world You will see a snapshot of the Result in a HTML response format. To change the return format to Json, simply add `?format=json` to the end of the URL. You'll learn more about [formats](/formats), endpoints (URLs, etc) when you continue reading the documentation. If we go back to the solution and find the WebApplication1.ServiceInterface and open the **MyServices.cs** file, we can have a look at the code that is responding to the browser, giving us the **Result** back. ```csharp public class MyServices : Service { public object Any(Hello request) { return new HelloResponse { Result = $"Hello, {request.Name}!" }; } } ``` If we look at the code above, there are a few things to note. The name of the method `Any` means the server will run this method for any of the valid HTTP Verbs. Service methods are where you control what returns from your service. ## Step 4: Exploring the ServiceStack Solution The Recommended structure below is built into all ServiceStackVS VS.NET Templates where creating any new ServiceStack project will create a solution with a minimum of 4 projects below ensuring ServiceStack solutions starts off from an optimal logical project layout, laying the foundation for growing into a more maintainable, cohesive and reusable code-base: ### Host Project The Host project contains your AppHost which references and registers all your App's concrete dependencies in its IOC and is the central location where all App configuration and global behavior is maintained. It also references all Web Assets like Razor Views, JS, CSS, Images, Fonts, etc. that's needed to be deployed with the App. The AppHost is the top-level project which references all dependencies used by your App whose role is akin to an orchestrator and conduit where it decides what functionality is made available and which concrete implementations are used. By design it references all other (non-test) projects whilst nothing references it and as a goal should be kept free of any App or Business logic. ### ServiceInterface Project The ServiceInterface project is the implementation project where all Business Logic and Services live which typically references every other project except the Host projects. Small and Medium projects can maintain all their implementation here where logic can be grouped under feature folders. Large solutions can split this project into more manageable cohesive and modular projects which we also recommend encapsulates any dependencies they might use. ### ServiceModel Project The ServiceModel Project contains all your Application's DTOs which is what defines your Services contract, keeping them isolated from any Server implementation is how your Service is able to encapsulate its capabilities and make them available behind a remote facade. There should be only one ServiceModel project per solution which contains all your DTOs and should be implementation, dependency and logic-free which should only reference the impl/dep-free **ServiceStack.Interfaces.dll** contract assembly to ensure Service contracts are decoupled from its implementation, enforces interoperability ensuring that your Services don't mandate specific client implementations and will ensure this is the only project clients need to be able to call any of your Services by either referencing the **ServiceModel.dll** directly or downloading the DTOs from a remote ServiceStack instance using [Add ServiceStack Reference](/add-servicestack-reference): ![](/img/pages/dtos-role.png) ### Test Project The Unit Test project contains all your Unit and Integration tests. It's also a Host project that typically references all other non-Host projects in the solution and contains a combination of concrete and mock dependencies depending on what's being tested. See the [Testing Docs](/testing) for more information on testing ServiceStack projects. ## Learn ServiceStack Guide If you're new to ServiceStack we recommend stepping through [ServiceStack's Getting Started Guide](https://servicestack.net/start/project-overview) to get familiar with the basics. ## API Client Examples ### jQuery Ajax ServiceStack's clean Web Services makes it simple and intuitive to be able to call ServiceStack Services from any ajax client, e.g. from a traditional [Bootstrap Website using jQuery](https://github.com/ServiceStack/Templates/blob/master/src/ServiceStackVS/BootstrapWebApp/BootstrapWebApp/default.cshtml): ```html

``` ### Rich JsonApiClient & Typed DTOs The modern recommended alternative to jQuery that works in all modern browsers is using your APIs built-in [JavaScript typed DTOs](/javascript-add-servicestack-reference) with the [@servicestack/client](/javascript-client) library from a [JavaScript Module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). We recommend using an [importmap](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) to specify where **@servicestack/client** should be loaded from, e.g: ```html ``` This lets us reference the **@servicestack/client** package name in our source code instead of its physical location: ```html
``` ```html ``` ### Enable static analysis and intelli-sense For better IDE intelli-sense during development, save the annotated Typed DTOs to disk with the [x dotnet tool](/dotnet-tool): :::sh x mjs ::: Then reference it instead to enable IDE static analysis when calling Typed APIs from JavaScript: ```js import { Hello } from '/js/dtos.mjs' client.api(new Hello({ name })) ``` To also enable static analysis for **@servicestack/client**, install the dependency-free library as a dev dependency: :::sh npm install -D @servicestack/client ::: Where only its TypeScript definitions are used by the IDE during development to enable its type-checking and intelli-sense. ### Rich intelli-sense support Where you'll be able to benefit from rich intelli-sense support in smart IDEs like [Rider](https://www.jetbrains.com/rider/) for both the client library: ![](/img/pages/mix/init-rider-ts-client.png) As well as your App's server generated DTOs: ![](/img/pages/release-notes/v6.6/mjs-intellisense.png) So even simple Apps without complex bundling solutions or external dependencies can still benefit from a rich typed authoring experience without any additional build time or tooling complexity. ## Create Empty ServiceStack Apps ::include empty-projects.md:: ### Any TypeScript or JavaScript Web, Node.js or React Native App The same TypeScript [JsonServiceClient](/javascript-client) can also be used in more sophisticated JavaScript Apps like [React Native](/typescript-add-servicestack-reference#react-native-jsonserviceclient) to [Node.js Server Apps](https://github.com/ServiceStackApps/typescript-server-events) such as this example using TypeScript & [Vue Single-File Components](https://vuejs.org/guide/scaling-up/sfc.html): ```html ``` Compare and contrast with other major SPA JavaScript Frameworks: - [Vue 3 HelloApi.mjs](https://github.com/NetCoreTemplates/blazor-vue/blob/main/MyApp/wwwroot/posts/components/HelloApi.mjs) - [Vue SSG using swrClient](https://github.com/NetCoreTemplates/vue-ssg/blob/main/ui/src/components/HelloApi.vue) - [Next.js with swrClient](https://github.com/NetCoreTemplates/nextjs/blob/main/ui/components/intro.tsx) - [React HelloApi.tsx](https://github.com/NetCoreTemplates/react-spa/blob/master/MyApp/src/components/Home/HelloApi.tsx) - [Angular HelloApi.ts](https://github.com/NetCoreTemplates/angular-spa/blob/master/MyApp/src/app/home/HelloApi.ts) - [Svelte Home.svelte](https://github.com/NetCoreTemplates/svelte-spa/blob/master/MyApp/src/components/Home.svelte) ### Web, Mobile and Desktop Apps Use [Add ServiceStack Reference](/add-servicestack-reference) to enable typed integrations for the most popular languages to develop Web, Mobile & Desktop Apps. ### Full .NET Project Templates The above `init` projects allow you to create a minimal web app, to create a more complete ServiceStack App with the recommended project structure, start with one of our C# project templates instead: ### [C# Project Templates Overview](/templates/) ## Simple, Modern Razor Pages & MVC Vue 3 Tailwind Templates The new Tailwind Razor Pages & MVC Templates enable rapid development of Modern Tailwind Apps without the [pitfalls plaguing SPAs](https://servicestack.net/posts/javascript): All Vue Tailwind templates are pre-configured with our rich [Vue 3 Tailwind Components](/vue/) library for maximum productivity: ## Advanced JAMStack Templates For more sophisticated Apps that need the best web tooling that npm can offer checkout our JAMStack Vite Vue & SSG templates: Or if you prefer Modern React Apps checkout the Next.js template: For Blazor WASM and Server checkout our comprehensive [Blazor projects & Tailwind components](/templates/blazor-tailwind). ### Integrated in Major IDEs and popular Mobile & Desktop platforms ServiceStack Services are also [easily consumable from all major Mobile and Desktop platforms](/why-servicestack#generate-instant-typed-apis-from-within-all-major-ides) including native iPhone and iPad Apps on iOS with Swift, Mobile and Tablet Apps on Android with Java or Kotlin, OSX Desktop Applications as well as targeting the most popular .NET Mobile and Desktop platforms including Xamarin.iOS, Xamarin.Android, Windows Store, WPF and WinForms. ## Instant Client Apps Generate working native client apps for your live ServiceStack services, in a variety of languages, instantly with our free managed service. This tool enables your developers, and even your customers, to open a working example native application straight from the web to their favorite IDE. ## Fundamentals - AppHost and Configuration Walk through configuring your ServiceStack Application's `AppHost`: ## Community Resources - [Creating A Simple Service Using ServiceStack](https://www.c-sharpcorner.com/UploadFile/shashijeevan/creating-a-simple-service-using-servicestack779/) by [Shashi Jeevan](http://shashijeevan.net/author/shashijeevan/) - [Introducing ServiceStack](https://www.dotnetcurry.com/aspnet/1056/introducing-service-stack-tutorial) by [@dotnetcurry](https://twitter.com/DotNetCurry) - [Create web services in .NET in a snap with ServiceStack](https://www.techrepublic.com/article/create-web-services-in-net-in-a-snap-with-servicestack/) by [@techrepublic](https://twitter.com/techrepublic) - [How to build web services in MS.Net using ServiceStack](https://kborra.wordpress.com/2014/07/29/how-to-build-web-services-in-ms-net-using-service-stack/) by [@kishoreborra](http://kborra.wordpress.com/about/) - [Getting started with ServiceStack – Creating a service](https://dilanperera.wordpress.com/2014/02/22/getting-started-with-servicestack-creating-a-service/) - [ServiceStack Quick Start](https://debuggers.domains/post/servicestack-quick-start/) by [@aarondandy](https://github.com/aarondandy) - [Getting Started with ASP.NET MVC, ServiceStack and Bootstrap](https://www.pluralsight.com/courses/getting-started-aspdotnet-mvcservice-stack-bootstrap) by [@pluralsight](http://twitter.com/pluralsight) - [Building Web Applications with Open-Source Software on Windows](https://www.pluralsight.com/courses/building-web-application-open-source-software-on-windows) by [@pluralsight](http://twitter.com/pluralsight) - [ServiceStack the way I like it](https://www.antonydenyer.co.uk/2012-09-20-servicestack-the-way-i-like-it/) by [@tonydenyer](https://twitter.com/tonydenyer) - [Generating a RESTful Api and UI from a database with LLBLGen](https://www.mattjcowan.com/funcoding/2013/03/10/rest-api-with-llblgen-and-servicestack/) by [@mattjcowan](https://twitter.com/mattjcowan) - [ServiceStack: Reusing DTOs](https://korneliuk.blogspot.com/2012/08/servicestack-reusing-dtos.html) by [@korneliuk](https://twitter.com/korneliuk) - [ServiceStack, Rest Service and EasyHttp](https://blogs.lessthandot.com/index.php/WebDev/ServerProgramming/servicestack-restservice-and-easyhttp) by [@chrissie1](https://twitter.com/chrissie1) - [Building a Web API in SharePoint 2010 with ServiceStack](https://www.mattjcowan.com/funcoding/2012/05/04/building-a-web-api-in-sharepoint-2010-with-servicestack/) - [REST Raiding. ServiceStack](https://dgondotnet.blogspot.com/2012/04/rest-raiding-servicestack.html) by [Daniel Gonzalez](http://www.blogger.com/profile/13468563783321963413) - [JQueryMobile and ServiceStack: EventsManager tutorial](https://kylehodgson.com/2012/04/21/jquerymobile-and-service-stack-eventsmanager-tutorial-post-2/) / [Part 3](https://kylehodgson.com/2012/04/23/jquerymobile-and-service-stack-eventsmanager-tutorial-post-3/) by Kyle Hodgson - [Like WCF: Only cleaner!](https://kylehodgson.com/2012/04/18/like-wcf-only-cleaner-9/) by Kyle Hodgson - [ServiceStack I heart you. My conversion from WCF to SS](https://www.philliphaydon.com/2012/02/21/service-stack-i-heart-you-my-conversion-from-wcf-to-ss/) by [@philliphaydon](https://twitter.com/philliphaydon) - [ServiceStack vs WCF Data Services](https://codealoc.wordpress.com/2012/03/24/service-stack-vs-wcf-data-services/) - [Buildiing a Tridion WebService with jQuery and ServiceStack](https://www.curlette.com/?p=161) by [@robrtc](https://twitter.com/#!/robrtc) - [Anonymous type + Dynamic + ServiceStack == Consuming cloud has never been easier](https://www.ienablemuch.com/2012/05/anonymous-type-dynamic-servicestack.html) by [@ienablemuch](https://twitter.com/ienablemuch) - [Handful of examples of using ServiceStack based on the ServiceStack.Hello Tutorial](https://github.com/jfoshee/TryServiceStack) by [@82unpluggd](https://twitter.com/82unpluggd) # Your first Web Service Explained Source: https://docs.servicestack.net/your-first-webservice-explained Let's look a bit deeper into the [Hello World service](/create-your-first-webservice#how-does-it-work) you created: As you have seen, the convention for response DTO is `RequestDTO` and `RequestDTOResponse`. **Note, request and response DTO should be in the same namespace if you want ServiceStack to recognize the DTO pair**. To support automatic exception handling, you also need to add a `ResponseStatus` property to the response DTO: ```csharp // Request DTO public class Hello : IReturn { public string Name { get; set; } } // Response DTO (follows naming convention) public class HelloResponse { public string Result { get; set; } public ResponseStatus ResponseStatus { get; set; } //Automatic exception handling } ``` Services are implemented in a class that either inherits from the `Service` base class or implements the `IService` empty marker interface. Inheriting from the convenient `Service` base class provides easy access to the most common functionality. ```csharp public class HelloService : Service { public object Any(Hello request) { return new HelloResponse { Result = $"Hello, {request.Name}" }; } } ``` The above service can be called with **Any** HTTP Verb (e.g. GET, POST,..) from any endpoint or format (e.g. JSON, XML, etc). You can also choose to handle a specific Verb by changing the method name to suit. E.g. you can limit the Service to only handle HTTP **GET** requests by using the `Get` method: ```csharp public class HelloService : Service { public object Get(Hello request) => new HelloResponse { Result = $"Hello, {request.Name}" }; } ``` ## Calling Web Services Thanks to the above `IReturn` interface marker you'll be able to use the terse, typed Service Client APIs, e.g: ```csharp var client = new JsonServiceClient(BaseUri); HelloResponse response = client.Get(new Hello { Name = "World" }); ``` Request DTOs that don't implement `IReturn` will need to explicitly specify the Response DTO on their call-site, e.g: ```csharp HelloResponse response = client.Get(new Hello { Name = "World" }); HelloResponse response = client.Get("/hello/World!"); ``` Alternatively you could use a general purpose HTTP Client like [HTTP Utils](/http-utils): ```csharp HelloResponse response = "http://base.url/hello/World" .GetJsonFromUrl() .FromJson(); ``` We highly recommend annotating Request DTO's with the above `IReturn` marker as it enables a generic typed API without clients having to know and specify the Response at each call-site, which would be invalidated and need to be manually updated if the Service Response Type changes. More details on the Service Clients is available on the [C#/.NET Service Clients page](/csharp-client). ### Registering Custom Routes If no routes are defined the .NET Service Clients will use the [pre-defined Routes](/routing#pre-defined-routes). You can annotate your Request DTO with the `[Route]` attribute to register additional Custom Routes, e.g: ```csharp //Request DTO [Route("/hello")] [Route("/hello/{Name}")] public class Hello : IReturn { public string Name { get; set; } } ``` The .NET ServiceClients will then use the best matching Route based on the populated properties on the Request DTO. ### Routing Tips No **?queryString** or POST Form Data should be included in the route as ServiceStack automatically populates Request DTOs with all matching params, e.g: ```csharp [Route("/hello")] ``` Matches both `/hello` and `/hello?name=World` with the latter populating the `Name` Request DTO **public property**. When the route includes a variable, e.g: ```csharp [Route("/hello/{Name}")] ``` It only matches: ``` /hello/name ``` Whereas using a wildcard: ```csharp [Route("/hello/{Name*}")] ``` Matches all routes: ``` /hello /hello/name /hello/my/name/is/ServiceStack ``` More details about Routing is available on the [Routing page](/routing). # ServiceStack API design Source: https://docs.servicestack.net/api-design The primary difference between developing RPC vs ServiceStack's [Message-based Services](/what-is-a-message-based-web-service) is that the Services entire contract is defined by its typed messages, specifically the Request DTO which defines both the System inputs and identifies the System output. Typically both are POCO DTOs however the [response can be any serializable object](/service-return-types). The simplest Service example that does this is: ```csharp public class MyRequest : IReturn {} public class MyServices : Service { public object Any(MyRequest request) => request; } ``` As only the `Any()` wildcard method is defined, it will get executed whenever the `MyRequest` Service is invoked via **any HTTP Verb**, [gRPC](/grpc/), [MQ](/messaging) or [SOAP](/soap-support) Request. The Request DTO is also all that's required to invoke it via any [Typed Generic Service Client](/clients-overview) in any supported language, e.g: ```csharp MyRequest response = client.Get(new MyRequest()); ``` All Services are accessible by their [pre-defined routes](/routing#pre-defined-routes), we can turn it into a functional data-driven Service by annotating it with a [user-defined route](/routing) and changing the implementation to return all App Contacts: ```csharp public class Contact { public int Id { get; set; } public string Name { get; set; } } [Route("/contacts")] public class GetContacts : IReturn> { } public class ContactsService : Service { public object Get(GetContacts request) => Db.Select(); } ``` Which your C# clients will still be able to call with: ```csharp List response = client.Get(new GetContacts()); ``` This will make a **GET** call to the custom `/contacts` URL and returns all rows from the `Contact` Table in the configured RDBMS using [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) `Select()` extension method on the `base.Db` ADO.NET `IDbConnection` property on ServiceStack's convenience `Service` base class. Using `Get()` limits access to this service from HTTP **GET** requests only, all other HTTP Verbs requests to `/contacts` will return a **404 NotFound** HTTP Error Response. ### Using explicit Response DTO Our recommendation instead of returning naked collections is returning an explicit predictable Response DTO, e.g: ```csharp [Route("/contacts")] public class GetContacts : IReturn { } public class GetContactsResponse { public List Results { get; set; } public ResponseStatus ResponseStatus { get; set; } } public class ContactsService : Service { public object Get(GetContacts request) => new GetContactsResponse { Results = Db.Select() }; } ``` Whilst slightly more verbose this style benefits from [more resilience in evolving and versioning](https://stackoverflow.com/a/12413091/85785) message-based Services and more coarse-grained APIs as additional results can be added to the Response DTO without breaking existing clients. You'll also need to follow the above convention if you also wanted to [support SOAP endpoints](/soap-support) or if you want to be able to handle Typed [Response Messages in MQ Services](/messaging#message-workflow). ### All APIs have a preferred default method Like the `Send*` APIs before them, both [API Explorer](/api-explorer) and the new [`Api*` methods](/csharp-client.html#high-level-api-and-apiasync-methods) send API requests using an APIs **preferred HTTP Method** which can be defined either: - Explicitly annotating Request DTOs with `IGet`, `IPost`, etc. **IVerb** interface markers - Using the verb specified in its user-defined `[Route]` attribute (if single verb specified) - Implicitly when using AutoQuery/CRUD Request DTOs - Using the Services **Verb()** implementation method if not using **Any()** If the HTTP Method can't be inferred, it defaults to using HTTP **POST**. But as good API documentation practice, we recommend specifying the HTTP Method each API should use, preferably using the `IVerb` interface marker, so it's embedded into the APIs Services Contract shared with clients (not required for AutoQuery APIs). ## ServiceStack's API Design We'll walk through a few examples here but for a more detailed look into the usages and capabilities of ServiceStack's API design checkout its [Comprehensive Test Suite](https://github.com/ServiceStack/ServiceStack/blob/master/tests/RazorRockstars.Console.Files/ReqStarsService.cs) At a minimum ServiceStack Services only need to implement the `IService` empty interface: ```csharp public interface IService {} ``` The interface is used as a Marker interface that ServiceStack uses to find, register and auto-wire your existing services. Although you're more likely going to want to inherit from ServiceStack's convenience concrete `Service` class which contains easy access to ServiceStack's providers: ```csharp public class Service : IService { IRequest Request { get; } // HTTP Request Context IResponse Response { get; } // HTTP Response Context IServiceGateway Gateway { get; } // Built-in Service Gateway IMessageProducer MessageProducer { get; } // Message Producer for Registered MQ Server void PublishMessage(T message); // Publish messages to Registered MQ Server IVirtualPathProvider VirtualFileSources { get; } // Virtual FileSystem Sources IVirtualFiles VirtualFiles { get; } // Writable Virtual FileSystem ICacheClient Cache { get; } // Registered Caching Provider ICacheClientAsync CacheAsync { get; } // Registered Async Caching Provider (or sync wrapper) MemoryCacheClient LocalCache { get; } // Local InMemory Caching Provider IDbConnection Db { get; } // Registered ADO.NET IDbConnection IRedisClient Redis { get; } // Registered RedisClient ValueTask GetRedisAsync(); // Registered Async RedisClient IAuthRepository AuthRepository { get; } // Registered User Repository IAuthRepositoryAsync AuthRepositoryAsync { get; } // Registered Async User Repository ISession SessionBag { get; } // Dynamic Session Bag ISessionAsync SessionBagAsync { get; } // Dynamic Async Session Bag Task SessionAsAsync(); // Resolve Typed UserSession Async TUserSession SessionAs(); // Resolve Typed UserSession IAuthSession GetSession() { get; } // Resolve base IAuthSession Task GetSessionAsync(); // Resolve base IAuthSession Async bool IsAuthenticated { get; } // Is Authenticated Request T TryResolve(); // Resolve dependency at runtime T ResolveService(); // Resolve an auto-wired service T GetPlugin(); // Resolve optional registered Plugin T AssertPlugin(); // Resolve required registered Plugin void Dispose(); // Override to implement custom IDispose ValueTask DisposeAsync(); // implement IAsyncDisposable (.NET v4.7.2+) } ``` ### Basic example - Handling Any HTTP Verb Lets revisit the Simple example from earlier: ```csharp [Route("/contacts")] public class GetContacts : IReturn> { } public class ContactsService : Service { public object Get(GetContacts request) => Db.Select(); } ``` ServiceStack maps HTTP Requests to your Services **Actions**. An Action is any method that: - Is `public` - Only contains a **single argument - the typed Request DTO** - Has a Method name matching a **HTTP Method** or **Any** (the fallback that can handle "ANY" method) - Methods can have **Format** suffix to handle specific formats, e.g. if exists `GetJson` will handle **GET JSON** requests - Can specify either `T` or `object` Return type, both have same behavior ### Content-Type Specific Service Implementations Service methods can also use `Verb{Format}` method names to provide a different implementation for handling a specific Content-Type. The Service below defines several different implementation for handling the same Request: ```csharp [Route("/my-request")] public class MyRequest { public string Name { get; set; } } public class ContentTypeServices : Service { public object GetJson(MyRequest request) => ..; // Handles GET /my-request for JSON responses public object GetHtml(MyRequest request) => // Handles GET /my-request for HTML Responses $@"

GetHtml {request.Name}

"; public object AnyHtml(MyRequest request) => // Handles other POST/PUT/etc Verbs for HTML Responses $@"

AnyHtml {request.Name}

"; public object Any(MyRequest request) => ...; // Handles all other unspecified Verbs/Formats } ``` ### Optional *Async Suffixes In addition your Services can optionally have the `*Async` suffix which by .NET Standard (and ServiceStack) guidelines is preferred for Async methods to telegraph to client call sites that its response should be awaited. ```csharp [Route("/contacts")] public class GetContacts : IReturn> { } public class ContactsService : Service { public async Task GetAsync(GetContacts request) => await Db.SelectAsync(); public object GetHtmlAsync(MyRequest request) => $@"

GetHtml {request.Name}

"; } ``` If both exists (e.g. `Post()` and `PostAsync()`) the `*Async` method will take precedence and be invoked instead. Allowing both is useful if you have internal services directly invoking other Services using `HostContext.ResolveService()` where you can upgrade your Service to use an Async implementation without breaking existing clients, e.g. this is used in [RegisterService.cs](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/RegisterService.cs): ```csharp [Obsolete("Use PostAsync")] public object Post(Register request) { try { var task = PostAsync(request); return task.GetResult(); } catch (Exception e) { throw e.UnwrapIfSingleException(); } } /// /// Create new Registration /// public async Task PostAsync(Register request) { //... async impl } ``` To change to use an async implementation whilst retaining backwards compatibility with existing call sites, e.g: ```csharp using var service = HostContext.ResolveService(Request); var response = service.Post(new Register { ... }); ``` This is important if the response is ignored as the C# compiler wont give you any hints to await the response which can lead to timing issues where the Services is invoked but User Registration hasn't completed as-is often assumed. Alternatively you can rename your method to use `*Async` suffix so the C# compiler will fail on call sites so you can replace the call-sites to `await` the async `Task` response, e.g: ```csharp using var service = HostContext.ResolveService(Request); var response = await service.PostAsync(new Register { ... }); ``` ### Group Services by Tag Related Services by can be grouped by annotating **Request DTOs** with the `[Tag]` attribute where they'll enable functionality in a number of ServiceStack's metadata services where they'll be used to [Group Services in Open API](https://swagger.io/docs/specification/grouping-operations-with-tags/). This feature could be used to tag which Services are used by different platforms: ```csharp [Tag("web")] public class WebApi : IReturn {} [Tag("mobile")] public class MobileApi : IReturn {} [Tag("web"),Tag("mobile")] public class WebAndMobileApi : IReturn {} ``` Where they'll appear as a tab to additionally filter APIs in metadata pages: ![](/img/pages/metadata/tag-groups.png) They're also supported in [Add ServiceStack Reference](/add-servicestack-reference) where it can be used in the [IncludeTypes](/csharp-add-servicestack-reference#includetypes) DTO customization option where tags can be specified using braces in the format `{tag}` or `{tag1,tag2,tag3}`, e.g: ``` /* Options: IncludeTypes: {web,mobile} ``` Or individually: ``` /* Options: IncludeTypes: {web},{mobile} ``` It works similar to [Dependent Type References wildcard syntax](/csharp-add-servicestack-reference#include-request-dto-and-its-dependent-types) where it expands all Request DTOs with the tag to include all its reference types so including a `{web}` tag would be equivalent to including all Request DTOs & reference types with that reference, e.g: ``` /* Options: IncludeTypes: WebApi.*,WebAndMobileApi.* ``` ### Micro ORMs and ADO.NET's IDbConnection Code-First Micro ORMS like [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) and [Dapper](https://github.com/StackExchange/Dapper) provides a pleasant high-level experience whilst working directly against ADO.NET's low-level `IDbConnection`. They both support all major databases so you immediately have access to a flexible RDBMS option out-of-the-box. At the same time you're not limited to using the providers contained in the `Service` class and can continue to use your own register IOC dependencies (inc. an alternate IOC itself). ### Micro ORM POCOs make good DTOs The POCOs used in Micro ORMS are particularly well suited for re-using as DTOs since they don't contain any circular references that the Heavy ORMs have (e.g. EF). OrmLite goes 1-step further and borrows pages from NoSQL's playbook where any complex property e.g. `List` is transparently blobbed in a schema-less text field, promoting the design of frictionless **Pure POCOS** that are uninhibited by RDBMS concerns. In many cases these POCO data models already make good DTOs and can be returned directly instead of mapping to domain-specific DTOs. ### Calling Services from a Typed C# Client In Service development your services DTOs provides your technology agnostic **Service Layer** which you want to keep clean and as 'dependency-free' for maximum accessibility and potential re-use. Our recommendation is to follow our [Recommended Physical Project Structure](/physical-project-structure) and keep your DTOs in a separate ServiceModel project which ensures a well-defined ServiceContract [decoupled from their implementation and accessible from any client](/service-complexity-and-dto-roles#data-transfer-objects---dtos). This recommended Physical project structure is embedded in each [ServiceStack VS.NET Template](/templates/). One of ServiceStack's strengths is its ability to re-use your Server DTOs on the client enabling ServiceStack's productive end-to-end typed API. ServiceStack's use of Typed DTOs in its message-based design enable greater resiliency for your Services where the exact DTOs aren't needed, only the shape of the DTOs is important and clients can also opt to use partial DTOs containing just the fields they're interested in. In the same way extending existing Services with new optional properties wont break existing clients using older DTOs. When developing both Server and Client applications the easiest way to call typed Services from clients is to just have them reference the same ServiceModel .dll the Server uses to define its Service Contract, or for clients that only need to call a couple of Service you can choose to instead copy the class definitions as-is, in both cases calling Services is exactly the same where the Request DTO can be used with any of the generic [C#/.NET Service Clients](/csharp-client) to call Services using a succinct typed API, e.g: #### Service Model Classes ```csharp [Route("/contacts")] public class GetContacts : IReturn> { } public class Contact { ... } ``` Which can used in any ServiceClient with: ```csharp var client = new JsonServiceClient(BaseUri); List response = client.Get(new GetContacts()); ``` Which makes a **GET** web request to the `/contacts` route. Custom Routes on Request DTO's are also not required as when none are defined the client automatically falls back to using ServiceStack's [pre-defined routes](/routing#pre-defined-routes). ### Generating Typed DTOs In addition to being able to share your `ServiceModel.dll` on .NET Clients enable a typed end-to-end API without code-gen, clients can alternatively choose to use [Add ServiceStack Reference](/csharp-add-servicestack-reference) support to provide an alternative way to get the Services typed DTOs on the client. In both cases the exact same source code is used to call the Services: ```csharp var client = new JsonServiceClient(BaseUri); var response = client.Get(new GetContacts()); ``` Add ServiceStack Reference is also available for [most popular languages](/add-servicestack-reference) used in developing Web, Mobile and Desktop Apps. #### Custom API Requests When preferred, you can also use the previous more explicit client API (ideal for when you don't have the `IReturn<>` marker) which lets you call the Service using just its route: ```csharp var response = client.Get>("/contacts"); ``` ::: info All these Service Client APIs **have async equivalents** with an `*Async` suffix ::: ### API QueryParams ServiceStack's message-based design is centered around sending a single message which is all that's required to invoke any Typed API, however there may be times when you need to send additional params where you can't change the API's Request DTO definition or in AutoQuery's case its [Implicit Conventions](/autoquery/rdbms#implicit-conventions) would require too many permutations to be able to type the entire surface area on each Request DTO. Typically this would inhibit being able to invoke these Services from a typed Service Client API that would instead need to either use the untyped [`Get(relativeUrl)`](https://reference.servicestack.net/api/ServiceStack/IRestClient/#-gettresponsestring) ServiceClient APIs or [HTTP Utils](/http-utils) to construct the API Request path manually. Alternatively Request DTOs can implement `IHasQueryParams` where any entries will be sent as additional query params along with the typed DTO: ```csharp public interface IHasQueryParams { Dictionary QueryParams { get; set; } } ``` Which is available in all AutoQuery DTOs where it's added as a non-serializable property so it's only included in the QueryString: ```csharp [DataContract] public abstract class QueryBase : IQuery, IHasQueryParams { //... [IgnoreDataMember] public virtual Dictionary QueryParams { get; set; } } ``` Which allows using existing ServiceClient typed APIs to send a combination of untyped queries in AutoQuery requests, e.g: ```csharp var api = await client.ApiAsync(new QueryContacts { IdsIn = new[]{ 1, 2, 3 }, QueryParams = new() { ["LastNameStartsWith"] = "A" } }); ``` ## Everything centered around Request DTOs A nice property of ServiceStack's message-based design is all functionality is centered around Typed Request DTOs which easily lets you take advantage of high-level value-added functionality like [Auto Batched Requests](/auto-batched-requests) or [Encrypted Messaging](/auth/encrypted-messaging) which are enabled automatically without any effort or easily opt-in to enhanced functionality by decorating Request DTOs or thier Services with Metadata and [Filter Attributes](/filter-attributes) and everything works together, binded against typed models naturally. E.g. you can take advantage of [ServiceStack's Razor support](https://razor.netcore.io/) and create a web page for this service by just adding a Razor view with the same name as the Request DTO in the `/Views` folder, which for the `GetContacts` Request DTO you can just add `/Views/GetContacts.cshtml` and it will get rendered with the Services Response DTO as its View Model when the Service is called from a browser (i.e. HTTP Request with `Accept: text/html`). Thanks to ServiceStack's built-in Content Negotiation you can fetch the HTML contents calling the same url: ```csharp var html = $"{BaseUri}/contacts".GetStringFromUrl(accept:"text/html"); ``` This [feature is particularly nice](https://razor.netcore.io/#unified-stack) as it lets you **re-use your existing services** to serve both Web and Native Mobile and Desktop clients. ### Action Filters Service actions can also contain fine-grained application of Request and Response filters, e.g: ```csharp public class ContactsService : Service { [ClientCanSwapTemplates] public object Get(GetContacts request) => Db.Select(); } ``` This Request Filter allows the client to [change the selected Razor **View** and **Template**](https://razor.netcore.io/#unified-stack) used at runtime. By default the view with the same name as the **Request** or **Response** DTO is used. ## Handling different HTTP Verbs ServiceStack Services lets you handle any HTTP Verb in the same way, e.g this lets you respond with CORS headers to a HTTP **OPTIONS** request with: ```csharp public class ContactsService : Service { [EnableCors] public void Options(GetContact request) {} } ``` Which if you now make an OPTIONS request to the above service, will emit the default `[EnableCors]` headers: ```csharp var webReq = (HttpWebRequest)WebRequest.Create(Host + "/contacts"); webReq.Method = "OPTIONS"; using var webRes = webReq.GetResponse(); webRes.Headers["Access-Control-Allow-Origin"] // * webRes.Headers["Access-Control-Allow-Methods"] // GET, POST, PUT, DELETE, OPTIONS webRes.Headers["Access-Control-Allow-Headers"] // Content-Type ``` ### PATCH request example Handling a PATCH request is just as easy, e.g. here's an example of using PATCH to handle a partial update of a Resource: ```csharp [Route("/contacts/{Id}", "PATCH")] public class UpdateContact : IReturn { public int Id { get; set; } public int Age { get; set; } } public Contact Patch(UpdateContact request) { var Contact = request.ConvertTo(); Db.UpdateNonDefaults(Contact); return Db.SingleById(request.Id); } ``` And the client call is just as easy as you would expect: ```csharp var response = client.Patch(new UpdateContact { Id = 1, Age = 18 }); ``` Although sending different HTTP Verbs are unrestricted in native clients, they're unfortunately not allowed in some web browsers and proxies. So to simulate a PATCH from an AJAX request you need to set the **X-Http-Method-Override** HTTP Header. ## Structured Error Handling When following the [explicit Response DTO Naming convention](/error-handling#error-response-types) ServiceStack will automatically populate the `ResponseStatus` property with a structured Error Response otherwise if returning other DTOs like naked collections ServiceStack will instead return a generic `ErrorResponse`, although this is mostly a transparent technical detail you don't need to know about as for schema-less formats like JSON they return the exact same wire-format. [Error Handling](/error-handling) works naturally in ServiceStack where you can simply throw C# Exceptions, e.g: ```csharp public List Post(Contact request) { if (!request.Age.HasValue) throw new ArgumentException("Age is required"); Db.Insert(request.ConvertTo()); return Db.Select(); } ``` This will result in an Error thrown on the client if it tried to create an empty Contact: ```csharp try { var response = client.Post(new Contact()); } catch (WebServiceException webEx) { webEx.StatusCode // 400 webEx.StatusDescription // ArgumentException webEx.ResponseStatus.ErrorCode // ArgumentException webEx.ResponseStatus.Message // Age is required webEx.ResponseDto is ErrorResponse // true } ``` The same Service Clients Exception handling is also used to handle any HTTP error generated in or outside of your service, e.g. here's how to detect if a HTTP Method isn't implemented or disallowed: ```csharp try { var response = client.Send(new SearchContacts()); } catch (WebServiceException webEx) { webEx.StatusCode // 405 webEx.StatusDescription // Method Not Allowed } ``` In addition to standard C# exceptions your services can also return multiple, rich and detailed validation errors as enforced by [Fluent Validation's validators](/validation). ### Overriding the default Exception handling You can override the default exception handling in ServiceStack by registering a `ServiceExceptionHandlers`, e.g: ```csharp void Configure(Container container) { this.ServiceExceptionHandlers.Add((req, reqDto, ex) => { return ...; }); } ``` ## Smart Routing For the most part you won't need to know about this as ServiceStack's routing works as you would expect. Although this should still serve as a good reference to describe the resolution order of ServiceStack's Routes: 1. Any exact Literal Matches are used first 2. Exact Verb match is preferred over All Verbs 3. The more variables in your route the less weighting it has 4. When Routes have the same weight, the order is determined by the position of the Action in the service or Order of Registration (FIFO) These Rules only come into play when there are multiple routes that matches the pathInfo of an incoming request. Lets see some examples of these rules in action using the routes defined in the [API Design test suite](https://github.com/ServiceStack/ServiceStack/blob/master/tests/RazorRockstars.Console.Files/ReqStarsService.cs): ```csharp [Route("/contacts")] public class Contact {} [Route("/contacts", "GET")] public class GetContacts {} [Route("/contacts/{Id}", "GET")] public class GetContact {} [Route("/contacts/{Id}/{Field}")] public class ViewContact {} [Route("/contacts/{Id}/delete")] public class DeleteContact {} [Route("/contacts/{Id}", "PATCH")] public class UpdateContact {} [Route("/contacts/reset")] public class ResetContact {} [Route("/contacts/search")] [Route("/contacts/aged/{Age}")] public class SearchContacts {} ``` These are results for these HTTP Requests ``` GET /contacts => GetContacts POST /contacts => Contact GET /contacts/search => SearchContacts GET /contacts/reset => ResetContact PATCH /contacts/reset => ResetContact PATCH /contacts/1 => UpdateContact GET /contacts/1 => GetContact GET /contacts/1/delete => DeleteContact GET /contacts/1/foo => ViewContact ``` And if there were multiple of the exact same routes declared like: ```csharp [Route("/req/{Id}", "GET")] public class Req2 {} [Route("/req/{Id}", "GET")] public class Req1 {} public class MyService : Service { public object Get(Req1 request) { ... } public object Get(Req2 request) { ... } } ``` The Route on the Action that was declared first gets selected, i.e: ``` GET /req/1 => Req1 ``` ### Populating Complex Type Properties on QueryString ServiceStack uses the [JSV-Format](/jsv-format) (JSON without quotes) to parse QueryStrings. JSV lets you embed deep object graphs in QueryString as seen [this example url](https://test.servicestack.net/json/reply/StoreLogs?Loggers=%5B%7BId:786,Devices:%5B%7BId:5955,Type:Panel,TimeStamp:1199303309,Channels:%5B%7BName:Temperature,Value:58%7D,%7BName:Status,Value:On%7D%5D%7D,%7BId:5956,Type:Tank,TimeStamp:1199303309,Channels:%5B%7BName:Volume,Value:10035%7D,%7BName:Status,Value:Full%7D%5D%7D%5D%7D%5D): ``` https://test.servicestack.net/json/reply/StoreLogs?Loggers=[{Id:786,Devices:[{Id:5955,Type:Panel, Channels:[{Name:Temperature,Value:58},{Name:Status,Value:On}]}, {Id:5956,Type:Tank,TimeStamp:1199303309, Channels:[{Name:Volume,Value:10035},{Name:Status,Value:Full}]}]}] ``` ## Advanced Usages ### Custom Hooks The ability to extend ServiceStack's service execution pipeline with Custom Hooks is an advanced customization feature that for most times is not needed as the preferred way to add composable functionality to your services is to use [Request / Response Filter attributes](/filter-attributes) or apply them globally with [Global Request/Response Filters](/request-and-response-filters). ### Custom Serialized Responses The new `IHttpResult.ResultScope` API provides an opportunity to execute serialization within a custom scope, e.g. this can be used to customize the serialized response of adhoc services that's different from the default global configuration with: ```csharp return new HttpResult(dto) { ResultScope = () => JsConfig.With(new Config { IncludeNullValues = true }) }; ``` Which enables custom serialization behavior by performing the serialization within the custom scope, equivalent to: ```csharp using (JsConfig.With(new Config { IncludeNullValues = true })) { var customSerializedResponse = Serialize(dto); } ``` ### Request and Response Converters The [Encrypted Messaging Feature](/auth/encrypted-messaging) takes advantage of Request and Response Converters that let you change the Request DTO and Response DTO's that get used in ServiceStack's Request Pipeline where: #### Request Converters Request Converters are executed directly after any [Custom Request Binders](/serialization-deserialization#create-a-custom-request-dto-binder): ```csharp appHost.RequestConverters.Add(async (req, requestDto) => { //Return alternative Request DTO or null to retain existing DTO }); ``` #### Response Converters Response Converters are executed directly after the Service: ```csharp appHost.ResponseConverters.Add(async (req, response) => //Return alternative Response or null to retain existing Service response }); ``` ### Intercept Service Requests As an alternative to creating a [Custom Service Runner](#using-a-custom-servicerunner) to intercept different events when processing ServiceStack Requests, you can instead override the `OnBeforeExecute()`, `OnAfterExecute()` and `OnExceptionAsync()` callbacks in your `Service` class (or base class) to intercept and modify Request DTOs, Responses or Error Responses, e.g: ```csharp class MyServices : Service { // Log all Request DTOs that implement IHasSessionId public override void OnBeforeExecute(object requestDto) { if (requestDto is IHasSessionId dtoSession) { Log.Debug($"{nameof(OnBeforeExecute)}: {dtoSession.SessionId}"); } } //Return Response DTO Name in HTTP Header with Response public override object OnAfterExecute(object response) { return new HttpResult(response) { Headers = { ["X-Response"] = response.GetType().Name } }; } //Return custom error with additional metadata public override Task OnExceptionAsync(object requestDto, Exception ex) { var error = DtoUtils.CreateErrorResponse(requestDto, ex); if (error is IHttpError httpError) { var errorStatus = httpError.Response.GetResponseStatus(); errorStatus.Meta = new Dictionary { ["InnerType"] = ex.InnerException?.GetType().Name }; } return Task.FromResult(error); } } ``` #### Async Callbacks For async callbacks your Services can implement `IServiceBeforeFilterAsync` and `IServiceAfterFilterAsync`, e.g: ```csharp public class MyServices : Service, IServiceBeforeFilterAsync, IServiceAfterFilterAsync { public async Task OnBeforeExecuteAsync(object requestDto) { //... } public async Task OnAfterExecuteAsync(object response) { //... return response; } } ``` If you're implementing `IService` instead of inheriting the concrete `Service` class, you can implement the interfaces directly: ```csharp // Handle all callbacks public class MyServices : IService, IServiceFilters { //.. } // Or individually, just the callbacks you want public class MyServices : IService, IServiceBeforeFilter, IServiceAfterFilter, IServiceErrorFilter { //.. } ``` ### Custom Service Runner The [IServiceRunner](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IServiceRunner.cs) decouples the execution of your service from the implementation of it which provides an alternative custom hook which lets you add custom behavior to all Services without needing to use a base Service class. To add your own Service Hooks you just need to override the default Service Runner in your AppHost from its default implementation: ```csharp public virtual IServiceRunner CreateServiceRunner(ActionContext actionContext) { return new ServiceRunner(this, actionContext); //Cached per Service Action } ``` With your own: ```csharp public override IServiceRunner CreateServiceRunner(ActionContext actionContext) { return new MyServiceRunner(this, actionContext); //Cached per Service Action } ``` Where `MyServiceRunner` is just a custom class implementing the custom hooks you're interested in, e.g: ```csharp public class MyServiceRunner : ServiceRunner { public override OnBeforeExecute(IRequest req, TRequest request, object service) { // Called just before any Action is executed } public override Task ExecuteAsync(IRequest req, object instance, TRequest requestDto) { // Called to execute the Service instance with the requestDto return base.ExecuteAsync(req, serviceInstance, requestDto); } public override object OnAfterExecute(IRequest req, object response, object service) { // Called just after any Action is executed, you can modify the response returned here as well } public override Task HandleExceptionAsync(IRequest req, TRequest requestDto, Exception ex, object instance) { // Called whenever an exception is thrown in your Services Action } } ``` ## Limitations One limitation of Services is that you can't split the handling of a single Resource (i.e. Request DTO) over multiple service implementations. If you find you need to do this because your service is getting too big, consider using partial classes to spread the implementation over multiple files. Another option is encapsulating some of the re-usable functionality into Logic dependencies and inject them into your service. ## Other Notes Although they're not needed or used anywhere [you can also use HTTP Verb interfaces](https://github.com/ServiceStack/ServiceStack/blob/34acc429ee04053ea766e4fb183e7aad7321ef5e/src/ServiceStack.Interfaces/IService.cs#L27) to enforce the correct signature required by the services, e.g: ```csharp public class MyService : Service, IAny, IGet, IPost { public object Any(GetContacts request) { .. } public object Get(SearchContacts request) { .. } public object Post(Contact request) { .. } } ``` This has no effect to the runtime behaviour and your services will work the same way with or without the added interfaces. # Service Return Types Source: https://docs.servicestack.net/service-return-types From a birds-eye view ServiceStack can return any of: - Any **DTO** object -> serialized to Response ContentType - `HttpResult`, `HttpError`, `CompressedResult` or other `IHttpResult` for Customized HTTP response #### Services should only return Reference Types If a Value Type like `int` or `long` response is needed, it's recommended to wrap the Value Type in a Response DTO, e.g: ```csharp public class MyResponse { public int Result { get; set; } } ``` Alternatively you can return a naked Value Type response by returning it as a `string`, e.g: ```csharp public object Any(MyRequest request) => "1"; ``` ## Different Return Types The following types are not converted (to different Content-Types) but get written directly to the Response Stream: - `String` - `Stream` - `IStreamWriter` - `byte[]` - with the `application/octet-stream` Content Type - `ReadOnlyMemory` - `ReadOnlyMemory` From the [HelloWorld ServiceStack.UseCase](https://github.com/ServiceStack/ServiceStack.UseCases/blob/master/HelloWorld/Global.asax.cs) demo: ```csharp public class HelloService : Service { public HelloResponse Get(Hello request) { return new HelloResponse { Result = $"Hello, {request.Name}!" }; //C# client can call with: //var response = client.Get(new Hello { Name = "ServiceStack" }); } public string Get(HelloHtml request) { return $"

Hello, {request.Name}!

"; } [AddHeader(ContentType = "text/plain")] public string Get(HelloText request) { return $"

Hello, {request.Name}!

"; } [AddHeader(ContentType = "image/png")] public Stream Get(HelloImage request) { var width = request.Width.GetValueOrDefault(640); var height = request.Height.GetValueOrDefault(360); var bgColor = request.Background != null ? Color.FromName(request.Background) : Color.ForestGreen; var fgColor = request.Foreground != null ? Color.FromName(request.Foreground) : Color.White; var image = new Bitmap(width, height); using (var g = Graphics.FromImage(image)) { g.Clear(bgColor); var drawString = $"Hello, {request.Name}!"; var drawFont = new Font("Times", request.FontSize.GetValueOrDefault(40)); var drawBrush = new SolidBrush(fgColor); var drawRect = new RectangleF(0, 0, width, height); var drawFormat = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }; g.DrawString(drawString, drawFont, drawBrush, drawRect, drawFormat); var ms = new MemoryStream(); image.Save(ms, ImageFormat.Png); return ms; } } } ``` #### Live Examples of the above Hello Service: - [/hello/ServiceStack](http://bootstrapapi.apphb.com/api/hello/ServiceStack) - [/hello/ServiceStack?format=json](http://bootstrapapi.apphb.com/api/hello/ServiceStack?format=json) - [/hellotext/ServiceStack](http://bootstrapapi.apphb.com/api/hellotext/ServiceStack) - [/hellohtml/ServiceStack](http://bootstrapapi.apphb.com/api/hellohtml/ServiceStack) - [/helloimage/ServiceStack?Width=600&height=300&Foreground=Yellow](http://bootstrapapi.apphb.com/api/helloimage/ServiceStack?Width=600&height=300&Foreground=Yellow) ### Content-Type Specific Service Implementations Service implementations can use `Verb{Format}` method names to provide a different implementation for handling a specific Content-Type, e.g. the Service below defines several different implementation for handling the same Request: ```csharp [Route("/my-request")] public class MyRequest { public string Name { get; set; } } public class ContentTypeServices : Service { // Handles all other unspecified Verbs/Formats to /my-request public object Any(MyRequest request) => ...; // Handles GET /my-request for JSON responses public object GetJson(MyRequest request) => ..; // Handles POST/PUT/DELETE/etc /my-request for HTML Responses public object AnyHtml(MyRequest request) => $@"

AnyHtml {request.Name}

"; // Handles GET /my-request for HTML Responses public object GetHtml(MyRequest request) => $@"

GetHtml {request.Name}

"; } ``` This convention can be used for any of the formats listed in `ContentTypes.KnownFormats`, which by default includes: - json - xml - jsv - csv - html - protobuf - msgpack - wire ## Partial Content Support Partial Content Support allows a resource to be split up an accessed in multiple chunks for clients that support HTTP Range Requests. This is a popular feature in download managers for resuming downloads of large files and streaming services for real-time streaming of content (e.g. consumed whilst it's being watched or listened to). [HTTP Partial Content Support](http://benramsey.com/blog/2008/05/206-partial-content-and-range-requests/) is added in true ServiceStack-style where it's now automatically and transparently enabled for any existing services returning: #### A Physical File ```csharp return new HttpResult(new FileInfo(filePath), request.MimeType); ``` #### A Virtual File ```csharp return new HttpResult(VirtualFileSources.GetFile(virtualPath)); ``` #### A Memory Stream ```csharp return new HttpResult(ms, "audio/mpeg"); ``` #### Raw Bytes ```csharp return new HttpResult(bytes, "image/png"); ``` #### Raw Text ```csharp return new HttpResult(customText, "text/plain"); ``` Partial Content was also added to static file downloads served directly through ServiceStack which lets you stream mp3 downloads or should you ever want to your static .html, .css, .js, etc. You can disable Partial Content support with `Config.AllowPartialResponses = false;`. See the [PartialContentResultTests](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/PartialContentResultTests.cs) for more examples. ## Writing directly to the Response Stream In addition to returning plain C# objects, ServiceStack allows you to return any **Stream** or `IStreamWriterAsync` (which is a bit more flexible on how you write to the response stream): ```csharp public interface IStreamWriterAsync { Task WriteToAsync(Stream responseStream, CancellationToken token=default); } ``` Both though allow you to write directly to the Response OutputStream without any additional conversion overhead. ### Customizing HTTP Headers If you want to customize the HTTP headers at the same time you just need to implement [IHasOptions](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IHasOptions.cs) where any Dictionary Entry is written to the Response HttpHeaders. ```csharp public interface IHasOptions { IDictionary Options { get; } } ``` Further than that, the IHttpResult allows even finer-grain control of the HTTP output (status code, headers, ...) where you can supply a custom Http Response status code. You can refer to the implementation of the [HttpResult](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/HttpResult.cs) object for a real-world implementation of these above interfaces. ### Further customizing the HTTP Response See the [Customize HTTP Responses](/customize-http-responses) page for more ways of customizing the HTTP Response. # Design RESTful Services Source: https://docs.servicestack.net/design-rest-services ServiceStack encourages a message-based design so each Service should have its own distinct message (aka Request DTO) where it's able to use explicit properties to define what each Service accepts. Something to keep in mind is how you define and design your Services in ServiceStack are de-coupled in how you expose them which can be exposed under any custom Route. ### Use a logical / hierarchical Url structure We recommend adopting a logical hierarchically structured URL that represents the identifier of a resource, i.e. the parent path categorizes your resource and gives it meaningful context. So if you needed to design an API for System that maintained **Events** and their **Reviews** it could adopt the following url structure: ``` /events # all events /events/1 # event #1 /events/1/reviews # event #1 reviews ``` Where each of the above resource identifiers can be invoked using any HTTP **Verb** which represents the action to take on them, e.g: ``` GET /events # View all Events POST /events # Create a new Event PUT /events/{Id} # Update an existing Event DELETE /events/{Id} # Delete an existing Event ``` ### Implementing RESTful Routes For their implementation ServiceStack encourages a message-based design that groups all related operations based on **Response type** and **Call Context**. For an Events and Reviews system it could look something like: ```csharp [Route("/events", "GET")] [Route("/events/category/{Category}", "GET")] // Optional GET example public class SearchEvents : IReturn> { //resultset filter examples, e.g. ?Category=Tech&Query=servicestack public string Category { get; set; } public string Query { get; set; } } [Route("/events", "POST")] public class CreateEvent : IReturn { public string Name { get; set; } public DateTime StartDate { get; set; } } [Route("/events/{Id}", "GET")] [Route("/events/code/{EventCode}", "GET")] // Alternative Id public class GetEvent : IReturn { public int Id { get; set; } public string EventCode { get; set; } // Alternative to fetch Events } [Route("/events/{Id}", "PUT")] public class UpdateEvent : IReturnVoid { public int Id { get; set; } public string Name { get; set; } public DateTime StartDate { get; set; } } ``` Event Reviews would follow a similar pattern: ```csharp [Route("/events/{EventId}/reviews", "GET")] public class GetEventReviews : IReturn> { public int EventId { get; set; } } [Route("/events/{EventId}/reviews/{Id}", "GET")] public class GetEventReview : IReturn { public int EventId { get; set; } public int Id { get; set; } } [Route("/events/{EventId}/reviews", "POST")] public class CreateEventReview : IReturn { public int EventId { get; set; } public string Comments { get; set; } } ``` The above REST Service examples returns naked Types and collections which [ServiceStack has a great story for](/api-design#structured-error-handling), however our personal preference is to design more coarse-grained and versionable [Message-based APIs](/design-message-based-apis) where we'd use an explicit Response DTO for each Service, e.g: ```csharp [Route("/events/{EventId}/reviews", "GET")] public class GetEventReviews : IReturn { public int EventId { get; set; } } public class GetEventReviewsResponse { public List Results { get; set; } } [Route("/events/{EventId}/reviews/{Id}", "GET")] public class GetEventReview : IReturn { public int EventId { get; set; } public int Id { get; set; } } public class GetEventReviewResponse { public EventReview Result { get; set; } public ResponseStatus ResponseStatus { get; set; } // inject structured errors if any } [Route("/events/{EventId}/reviews", "POST")] public class CreateEventReview : IReturn { public int EventId { get; set; } public string Comments { get; set; } } public class CreateEventReviewResponse { public EventReview Result { get; set; } public ResponseStatus ResponseStatus { get; set; } } ``` ### Notes The implementation of each Services then becomes straight-forward based on these messages, which (depending on code-base size) we'd recommend organizing in 2 **EventsService** and **EventReviewsService** classes. Although `UpdateEvent` and `CreateEvent` are seperate Services here, if the use-case permits they can instead be handled by a single idempotent `StoreEvent` Service. ## [Physical Project Structure](/physical-project-structure) Ideally the root-level **AppHost** project should be kept lightweight and implementation-free. Although for small projects or prototypes with only a few services it's ok for everything to be in a single project and to simply grow your architecture when and as needed. For medium-to-large projects we recommend the physical structure below which for the purposes of this example we'll assume our Application is called **Events**. The order of the projects also show its dependencies, e.g. the top-level `Events` project references **all** sub projects whilst the last `Events.ServiceModel` project references **none**: ``` /Events AppHost.cs // ServiceStack Web or Self Host Project /Events.ServiceInterface // Service implementations (akin to MVC Controllers) EventsService.cs EventsReviewsService.cs /Events.Logic // For large projects: extract C# logic, data models, etc IGoogleCalendarGateway // E.g of a external dependency this project could use /Events.ServiceModel // Service Request/Response DTOs and DTO types Events.cs // SearchEvents, CreateEvent, GetEvent DTOs EventReviews.cs // GetEventReviews, CreateEventReview Types/ Event.cs // Event type EventReview.cs // EventReview type ``` With the `Events.ServiceModel` DTO's kept in their own separate implementation and dependency-free dll, you're freely able to share this dll in any .NET client project as-is - which you can use with any of the generic [C# Service Clients](/csharp-server-events-client) to provide an end-to-end typed API without any code-gen. ## More Info - This recommended project structure is embedded in all [ServiceStackVS VS.NET Templates](/templates/). - The [Simple Customer REST Example](/why-servicestack#simple-customer-database-rest-services-example) is a small self-contained, real-world example of creating a simple REST Service utilizing an RDBMS. # Design Message-based APIs Source: https://docs.servicestack.net/design-message-based-apis To give you a flavor of the differences you should think about when designing message-based services in ServiceStack we'll look at some examples to contrast WCF/WebApi vs ServiceStack's approach: ## WCF vs ServiceStack API Design WCF encourages you to think of web services as normal C# method calls, e.g: ```csharp public interface IWcfCustomerService { Customer GetCustomerById(int id); List GetCustomerByIds(int[] id); Customer GetCustomerByUserName(string userName); List GetCustomerByUserNames(string[] userNames); Customer GetCustomerByEmail(string email); List GetCustomerByEmails(string[] emails); } ``` This is what the same Service contract would look like in ServiceStack: ```csharp public class Customers : IReturn> { public int[] Ids { get; set; } public string[] UserNames { get; set; } public string[] Emails { get; set; } } ``` The important concept to keep in mind is that the entire query (aka Request) is captured in the Request Message (i.e. Request DTO) and not in the server method signatures. The obvious immediate benefit of adopting a message-based design is that any combination of the above RPC calls can be fulfilled in 1 remote message, by a single service implementation which improves cacheability and simplifies maintenance and testing with the reduced API surface area. ## WebApi vs ServiceStack API Design Likewise WebApi promotes a similar C#-like RPC Api that WCF does: ```csharp public class ProductsController : ApiController { public IEnumerable 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 Product GetProductByName(string categoryName) { var product = products.FirstOrDefault((p) => p.Name == categoryName); if (product == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } return product; } public IEnumerable GetProductsByCategory(string category) { return products.Where(p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase)); } public IEnumerable GetProductsByPriceGreaterThan(decimal price) { return products.Where((p) => p.Price > price); } } ``` ### ServiceStack Message-Based API Design Whilst ServiceStack encourages you to retain a Message-based Design: ```csharp public class SearchProducts : IReturn> { public string Category { get; set; } public decimal? PriceGreaterThan { get; set; } } public class GetProduct : IReturn { public int? Id { get; set; } public string Name { get; set; } } public class ProductsService : Service { public object Get(SearchProducts request) { var ret = products.AsQueryable(); if (request.Category != null) ret = ret.Where(x => x.Category == request.Category); if (request.PriceGreaterThan.HasValue) ret = ret.Where(x => x.Price > request.PriceGreaterThan.Value); return ret.ToList(); } public Product Get(GetProduct request) { var product = request.Id.HasValue ? products.FirstOrDefault(x => x.Id == request.Id.Value) : products.FirstOrDefault(x => x.Name == request.Name); if (product == null) throw new HttpError(HttpStatusCode.NotFound, "Product does not exist"); return product; } } ``` Again capturing the essence of the Request in the Request DTO. The message-based design is also able to condense **5 separate RPC** WebAPI Services into **2 message-based** ServiceStack Services. ## Group by Call Semantics and Response Types It's grouped into 2 different services in this example based on **Call Semantics** and **Response Types**: Every property in each Request DTO has the same semantics that is for `SearchProducts` each property acts like a Filter (e.g. an AND) whilst in `GetProduct` it acts like a combinator (e.g. an OR). The Services also return `List` and `Product` return types which will require different handling in the call-sites of Typed APIs. In WCF / WebAPI (and other RPC services frameworks) whenever you have a client-specific requirement you would add a new Server signature on the controller that matches that request. In ServiceStack's message-based approach however you're instead encouraged to think about where this feature intuitively fits and whether you're able to enhance existing services. You should also be thinking about how you can support the client-specific requirement in a **generic way** so that the same service could benefit other future potential use-cases. ### Separate One and Many Services We can use the above context as a guide to design new Services. If we needed to design a Bookings System that needed an API to return **All Bookings** and a **Single Booking** we'd use a separate Services as they'd have different Response Types, e.g. `GetBooking` returns 1 booking whilst `GetBookings` returns many. ### Distinguish Service Operations vs Types There should be a clean split between your Operations (aka Request DTOs) which is unique per service and is used to capture the Services' request, and the DTO types they return. Request DTOs are usually actions so they're verbs, whilst DTO types are entities/data-containers so they're nouns. ### Returning naked collections ServiceStack can return naked collections that [don't require a ResponseStatus](/error-handling#error-response-types) property since if it doesn't exist the generic `ErrorResponse` DTO will be thrown and serialized on the client instead which frees you from having your Responses contain `ResponseStatus` property. ### Returning coarse-grained Response DTOs However since they offer better versionability that can later be extended to return more results without breaking existing clients we prefer specifying explicit Response DTOs for each Service, although this is entirely optional. So our preferred message-based would look similar to: ```csharp // Operations [Route("/bookings/{Id}")] public class GetBooking : IReturn { public int Id { get; set; } } public class GetBookingResponse { public Booking Result { get; set; } public ResponseStatus ResponseStatus { get; set; } // inject structured errors } [Route("/bookings/search")] public class SeachBookings : IReturn { public DateTime BookedAfter { get; set; } } public class SeachBookingsResponse { public List Results { get; set; } public ResponseStatus ResponseStatus { get; set; } // inject structured errors } // Types public class Booking { public int Id { get; set; } public int ShiftId { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public int Limit { get; set; } } ``` When they're not ambiguous we'll typiclly leave out specifying the **Verb** in `[Route]` definitions for **GET** Requests as its unnecessary. ### Using AutoQuery Where possible we'll also use [AutoQuery for Search Services](/autoquery/rdbms) which require dramatically less effort whilst offering a lot more functionality out-of-the-box. E.g. The Search Bookings Service with AutoQuery could adopt the same Customer Route and properties: ```csharp [Route("/bookings/search")] public class SeachBookings : QueryDb { public DateTime BookedAfter { get; set; } } ``` But no implementation is needed as AutoQuery automatically creates the optimal implementation. AutoQuery also supports [Implicit Conventions](/autoquery/rdbms#implicit-conventions) where you're able to filter by any of `Booking` table columns without any additional code or effort. ### Keep a consistent Nomenclature You should reserve the word **Get** on services which query on unique or Primary Keys fields, i.e. when a supplied value matches a field (e.g. Id) it only **Gets** 1 result. For "Search Services" that acts like a filter and returns multiple matching results which falls within a desired range we recommend using prefixing Services with the **Search** or **Find** verbs to signal the behavior of the Service. ### Self-describing Service Contracts Also try to be descriptive with each of your field names, these properties are part of your **public API** and should be self-describing as to what it does. E.g. By just looking at the Service Contract (e.g. Request DTO) we'd have no idea what a plain **Date** property means, as it could mean either **BookedAfter**, **BookedBefore** or **BookedOn** if it only returned bookings made on that Day. The benefit of this is now the call-sites of your [Typed .NET clients](/csharp-client) become easier to read: ```csharp Product product = client.Get(new GetProduct { Id = 1 }); var response = client.Get(new SearchBookings { BookedAfter = DateTime.Today }); ``` ## Service implementation [Filter Attributes](/filter-attributes) can be applied on either the **class** or **method** level, so when you need to secure all Operations within a given Service you can just annotate the top-level Service class with the `[Authenticate]`, e.g: ```csharp [Authenticate] public class BookingsService : Service { public object Get(GetBooking request) => ...; public object Get(SearchBookings request) => ...; } ``` ## Error Handling and Validation For info on how to add validation you either have the option to just [throw C# exceptions](/error-handling#throwing-c-exceptions) and apply your own customizations to them, in addition you also have the option to use the built-in [Declarative Validator](/declarative-validation) attributes on your Request DTO: ```csharp [ValidateIsAuthenticated] public class CreateBooking : IPost, IReturn { [ValidateNotNull] public DateTime? StartDate { get; set; } [ValidateGreatorThan(0)] public int ShiftId { get; set; } [ValidateGreatorThan(0)] public int Limit { get; set; } } ``` Or for more control you can use custom [Fluent Validation](/validation) validators. Validators are no-touch and invasive free meaning you can add them using a layered approach and maintain them without modifying the service implementation or DTO classes. Since they require an extra class We'd only use them on operations with side-effects e.g. **POST** or **PUT**, as **GET** requests tend to have minimal validation so throwing C# Exceptions typically requires less boilerplate. Here's an example of a validator you could have when creating a Booking: ```csharp public class CreateBookingValidator : AbstractValidator { public CreateBookingValidator() { RuleFor(r => r.StartDate).NotEmpty(); RuleFor(r => r.ShiftId).NotEmpty().GreaterThan(0); RuleFor(r => r.Limit).NotEmpty().GreaterThan(0); } } ``` Depending on the use-case instead of having separate `CreateBooking` and `UpdateBooking` DTOs you could re-use the same `StoreBooking` Request DTO to handle both operations. # Modular Startup Source: https://docs.servicestack.net/modular-startup ::: info For more information on the earlier Modular Startup in ServiceStack **v5.x** see our [Legacy Modular Startup](/modular-startup-legacy) docs ::: Taking advantage of C# 9 top level statements and .NET 6 [WebApplication Hosting Model](https://gist.github.com/davidfowl/0e0372c3c1d895c3ce195ba983b1e03d), ServiceStack templates by utilize both these features to simplify configuring your AppHost in a modular way. `Program.cs` becomes a script-like file since C# 9 top level statements are generating application entry point implicitly. ```csharp var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); app.UseHttpsRedirection(); } app.UseServiceStack(new AppHost()) app.Run(); ``` The application `AppHost` hooks into startup using `HostingStartup` assembly attribute. In ServiceStack templates, this uses the file name prefix of `Configure.*.cs` to help identify these startup modules. All ServiceStack's features are loaded using .NET's `HostingStartup`, including ServiceStack's `AppHost` itself that's now being configured in [Configure.AppHost.cs](https://github.com/NetCoreTemplates/web/blob/master/MyApp/Configure.AppHost.cs), e.g: ```csharp [assembly: HostingStartup(typeof(MyApp.AppHost))] namespace MyApp; public class AppHost() : AppHostBase("MyApp"), IHostingStartup { public void Configure(IWebHostBuilder builder) => builder .ConfigureServices(services => { // Configure ASP.NET Core IOC Dependencies }); public override void Configure() { // Configure ServiceStack, Run custom logic after ASP.NET Core Startup SetConfig(new HostConfig { }); } } ``` The use of Modular Startup does not change the AppHost declaration, but enables the modular grouping of configuration concerns. Different features are encapsulated together allowing them to be more easily updated or replaced, e.g. each feature could be temporarily disabled by commenting out its assembly HostingStartup's attribute: ```csharp //[assembly: HostingStartup(typeof(MyApp.AppHost))] ``` ## Module composition using `mix` This has enabled ServiceStack Apps to be easily composed with the features developers need in mind. Either at project creation with servicestack.net/start page or after a project's creation where features can easily be added and removed using the command-line [mix tool](/mix-tool) where you can view all available mix gists that can be added to projects with: :::sh x mix ::: .NET 6's idiom is incorporated into the [mix gist config files](https://gist.github.com/gistlyn/9b32b03f207a191099137429051ebde8) to adopt its `HostingStartup` which is better able to load modular Startup configuration without assembly scanning. This is a standard ASP .NET Core feature that we can use to configure Mongo DB in any ASP .NET Core App with: :::sh x mix mongodb ::: Which adds the `mongodb` gist file contents to your ASP .NET Core Host project: ```csharp using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; [assembly: HostingStartup(typeof(MyApp.ConfigureMongoDb))] namespace MyApp; public class ConfigureMongoDb : IHostingStartup { public void Configure(IWebHostBuilder builder) => builder .ConfigureServices((context, services) => { var mongoClient = new MongoClient(); IMongoDatabase mongoDatabase = mongoClient.GetDatabase("MyApp"); services.AddSingleton(mongoDatabase); }); } ``` As it's not a ServiceStack feature it can be used to configure ASP .NET Core Apps with any feature, e.g. we could also easily configure [Marten](https://martendb.io) in an ASP .NET Core App with: :::sh x mix marten ::: The benefit of this approach is entire modules of features can be configured in a single command, e.g. An empty ServiceStack App can be configured with MongoDB, ServiceStack Auth and a MongoDB Auth Repository with a single command: :::sh x mix auth auth-mongodb mongodb ::: Likewise, you can replace MongoDB with a completely different PostgreSQL RDBMS implementation by running: :::sh x mix auth auth-db postgres ::: ### Services and App Customizations Modular Startup configurations are flexible enough to encapsulate customizing ASP.NET Core's IOC and the built `WebApplication` by registering a `IStartupFilter` which is required by the Open API v3 Modular Configuration: :::sh x mix openapi3 ::: ```csharp [assembly: HostingStartup(typeof(MyApp.ConfigureOpenApi))] namespace MyApp; public class ConfigureOpenApi : IHostingStartup { public void Configure(IWebHostBuilder builder) => builder .ConfigureServices((context, services) => { if (context.HostingEnvironment.IsDevelopment()) { services.AddEndpointsApiExplorer(); services.AddSwaggerGen(); services.AddServiceStackSwagger(); services.AddBasicAuth(); //services.AddJwtAuth(); services.AddTransient(); } }); public class StartupFilter : IStartupFilter { public Action Configure(Action next) => app => { app.UseSwagger(); app.UseSwaggerUI(); next(app); }; } } ``` ### ConfigureAppHost Looking deeper, we can see where we're plugins are able to configure ServiceStack via the `.ConfigureAppHost()` extension method to execute custom logic on `AppHost` Startup: ```csharp [assembly: HostingStartup(typeof(MyApp.ConfigureAutoQuery))] namespace MyApp; public class ConfigureAutoQuery : IHostingStartup { public void Configure(IWebHostBuilder builder) => builder .ConfigureServices(services => { // Enable Audit History services.AddSingleton(c => new OrmLiteCrudEvents(c.GetRequiredService())); // For TodosService services.AddPlugin(new AutoQueryDataFeature()); // For Bookings https://docs.servicestack.net/autoquery-crud-bookings services.AddPlugin(new AutoQueryFeature { MaxLimit = 1000, //IncludeTotal = true, }); }) .ConfigureAppHost(appHost => { appHost.Resolve().InitSchema(); }); } ``` ### Customize AppHost at different Startup Lifecycles By default, any AppHost configuration is called before `AppHost.Configure()` is run, but to cater for all plugins, AppHost configurations can be registered at different stages within the AppHost's initialization: ```csharp public void Configure(IWebHostBuilder builder) => builder .ConfigureAppHost( beforeConfigure: appHost => /* fired before AppHost.Configure() */, afterConfigure: appHost => /* fired after AppHost.Configure() */, afterPluginsLoaded: appHost => /* fired after plugins are loaded */, afterAppHostInit: appHost => /* fired after AppHost has initialized */); ``` ### Removing Features The benefits of adopting a modular approach to AppHost configuration is the same as general organizational code structure which results in better decoupling and cohesion where it's easier to determine all the dependencies of a feature, easier to update, less chance of unintended side effects, easier to share standard configuration amongst multiple projects and easier to remove the feature entirely, either temporarily if needing to isolate & debug a runtime issue by: ```csharp // [assembly: HostingStartup(typeof(MyApp.ConfigureAuth))] ``` Or easier to permanently replace or remove features by either directly deleting the isolated `*.cs` source files or by undoing mixing in the feature using `mix -delete`, e.g: :::sh x mix -delete auth auth-db postgres ::: Which works similar to package managers where it removes all files contained within each mix gist. ::: info Please see the [Mix HowTo](https://gist.github.com/gistlyn/9b32b03f207a191099137429051ebde8#file-mix_howto-md) to find out how you can contribute your own gist mix features ::: ## Migrating to HostingStartup As we'll be using the new `HostingStartup` model going forward we recommend migrating your existing configuration to use them. To help with this you can refer to the [mix diff](https://github.com/ServiceStack/mix/commit/b56746622aa1879e3e6a8cbf835e634f05db30db) showing how each of the existing mix configurations were converted to the new model. As a concrete example, lets take a look at the steps used to migrate our Chinook example application [from NET5 using the previous `Startup : ModularStartup`, to .NET 6 `HostingStartup`](https://github.com/NetCoreApps/Chinook/commit/2758af9deae9c3aa910a27134f95167f7ec6e541). ### Step 1 Migrate your existing `ConfigureServices` and `Configure(IApplicationBuilder)` from `Startup : ModularStartup` to the top-level host builder in `Program.cs`. Eg ```csharp var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. // You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); app.UseHttpsRedirection(); } app.Run(); ``` ### Step 2 Move your `AppHost` class to a new `Configure.AppHost.cs` file. ### Step 3 Implement `IHostingStartup` on your AppHost with automatic initialization. Eg: ```csharp public void Configure(IWebHostBuilder builder) { builder.ConfigureServices(services => { // Configure ASP.NET Core IOC Dependencies }); } ``` ### Step 4 Declare `assembly: HostingStartup` for your `AppHost` in the same `Configure.AppHost.cs`. Eg: ```csharp [assembly: HostingStartup(typeof(Chinook.AppHost))] ``` ### Step 5 Migrate each existing modular startup class that implements `IConfgiureServices` and/or `IConfigureApp` to use `IHostingStartup`. Eg: ```csharp // net5.0 modular startup using ServiceStack; namespace Chinook; public class ConfigureAutoQuery : IConfigureAppHost { public void Configure(IAppHost appHost) { appHost.Plugins.Add(new AutoQueryFeature { MaxLimit = 1000, IncludeTotal = true }); } } ``` ```csharp // net8.0 modular startup using IHostingStartup using Microsoft.AspNetCore.Hosting; using ServiceStack; [assembly: HostingStartup(typeof(Chinook.ConfigureAutoQuery))] namespace Chinook; public class ConfigureAutoQuery : IHostingStartup { public void Configure(IWebHostBuilder builder) => builder .ConfigureServices(services => { services.AddPlugin(new AutoQueryFeature { MaxLimit = 1000, IncludeTotal = true }); }); } ``` > Remembering also that infrastructure like your `Dockerfile` or host will likely need the runtimes/SDKs updated as well. # ServiceStack's .NET Core Utility Belt Source: https://docs.servicestack.net/dotnet-tool Our `x` and `app` dotnet tools are a versatile invaluable companion for all ServiceStack developers where it's jam packed with functionality to power a number of exciting scenarios where it serves as a [Sharp App](https://sharpscript.net/docs/sharp-apps) delivery platform where they can be run as a .NET Core Windows Desktop App with `app` or as a cross-platform Web App launcher using `web` and we've already how it's now a [`#Script` runner](https://sharpscript.net/docs/sharp-scripts) with `x run` and into a [Live `#Script` playground](https://sharpscript.net/docs/sharp-scripts#live-script-with-web-watch) with `x watch`. These tools contains all the functionality ServiceStack Developers or API consumers need that can be used [Create ServiceStack projects](/templates/dotnet-new), run [Gist Desktop Apps](https://sharpscript.net/sharp-apps/gist-desktop-apps) or generate typed endpoints for consuming ServiceStack Services by either [Add/Update ServiceStack References](/add-servicestack-reference) or by generating [gRPC client proxies](/grpc#grpc-clients). ## Install To access available features, install with: :::sh dotnet tool install --global x ::: ### Update Or if you had a previous version installed, update with: :::sh dotnet tool update -g x ::: ::: info Both `x` and `app` have equivalent base functionality, whilst `app` has superset [Windows-only Desktop features](/netcore-windows-desktop) ::: ::: info To update and download Add ServiceStack Reference dtos without .NET see [npx get-dtos](/npx-get-dtos) ::: ## Usage Then run `x` without any arguments to view Usage: :::sh x ::: ```txt Usage: x new List available Project Templates x new