Create your first WebService

ServiceStack APIs start from a different place than most frameworks. Instead of writing a method that returns JSON, you describe what the message is - and the routes, the docs, the validation, the API Explorer and the native clients are all generated from that one description.

This walkthrough creates a working API from scratch, then shows exactly what each file does and what you got for free.

That's it - you now have a running .NET 10 API. The template's home page is already calling it with typed DTOs!

How it works

The important detail is what isn't in your Service: no HttpContext, no serialization, no routing code, no manual model binding. Your Service accepts a message and returns a message, which is what lets ServiceStack expose it over HTTP, MQs, gRPC or in-process without you changing a line.

The code

What that one DTO gave you

TIP

Change the return format on any API by adding ?format=json, ?format=csv or ?format=jsonl - or by sending the matching Accept header. See Formats for the full list.

The solution structure

Every ServiceStack template scaffolds the same four projects. The layout isn't ceremony - it's what makes your API contract shareable and your logic testable:

Read more in Physical Project Structure.

Call your API from anywhere

Your App publishes enough metadata to generate a native, typed client for any supported language - so there's no SDK project to write, version or document. Pick a language to see the two commands:

Re-run the generate command whenever your API changes. New fields show up in the generated DTOs, and removed or renamed members become compile errors in the consuming App instead of runtime surprises.

From a web page, with no build step

The web template's home page uses your App's built-in JavaScript DTOs from /types/mjs with the @servicestack/client library, loaded from an importmap:

<script type="importmap">
{
  "imports": {
    "@servicestack/client":"https://unpkg.com/@servicestack/client/dist/servicestack-client.mjs"
  }
}
</script>

Which lets you reference the package name in your source instead of its physical location:

<input type="text" id="txtName">
<div id="result"></div>

<script type="module">
import { JsonServiceClient, $1, on } from '@servicestack/client'
import { Hello } from '/types/mjs'

const client = new JsonServiceClient()
on('#txtName', {
    async keyup(el) {
        const api = await client.api(new Hello({ name:el.target.value }))
        $1('#result').innerHTML = api.response.result
    }
})
</script>

Enable static analysis and intelli-sense

For IDE intelli-sense during development, save the annotated Typed DTOs to disk:

npm run dtos

Then reference the local file to enable static analysis when calling your typed APIs:

import { Hello } from '/js/dtos.mjs'
client.api(new Hello({ name }))

To also get type-checking for @servicestack/client, install the dependency-free library as a dev dependency:

npm install -D @servicestack/client

Only its TypeScript definitions are used by the IDE, so you get a rich typed authoring experience with no bundler and no additional build time:

From a component framework

The same JsonServiceClient works in every JavaScript App, from SPAs to React Native to Node.js servers, e.g. with TypeScript & Vue Single-File Components:

<template>
  <div v-if="api.error" class="ml-2 text-red-500">{‎{ error.message }‎}</div>
  <div v-else class="ml-3 mt-2 text-2xl">{‎{ api.loading ? 'Loading...' : api.response.result }‎}</div>
</template>

<script setup lang="ts">
import { JsonServiceClient } from "@servicestack/client"
import { Hello } from "@/dtos"

const props = defineProps<{ name: string }>()
const client = new JsonServiceClient()

const api = client.api(new Hello({ name: props.name }))
</script>

Compare the same API call across the major front-end frameworks:

Native Mobile and Desktop Apps use the same approach - see Add ServiceStack Reference for Swift, Java, Kotlin, Dart and .NET clients.

Where to go next

The web template is deliberately empty. When you want a template that comes with an opinionated front-end, auth, a database and deployment already wired up, start from one of the full project templates instead:

C# Project Templates Overview

For Blazor WASM and Server see our Blazor projects & Tailwind components, and the rich Vue 3 Tailwind Components library that all Vue templates are pre-configured with.

Other ways to create a project

If you don't have the x dotnet tool installed, the quickest way to create a ServiceStack App is to download your preferred template from:

Empty Projects

There are a few different ways you can create empty ServiceStack projects ordered by their level of emptiness.

To write a minimal .NET 10 Web App to your current directory, mix in the init gist files to your current directory:

npx add-in init

To create an empty Single Project Template solution use the empty template:

npx create-net empty ProjectName

To create an empty 4 Project solution that adopts ServiceStack's recommended project structure, use the web template:

npx create-net web ProjectName

INFO

You can omit the ProjectName in all above examples to use the Directory Name as the Project Name

Empty F# Template

Like C# init there's also init-fsharp gist to create an empty F# Web App:

npx add-in init-fsharp

Empty VB .NET Template

And init-vb to create an empty VB .NET Web App:

npx add-in init-vb