Quick Start
If you are new to Smithy, the official Smithy quickstart is a good place to learn the IDL before continuing.
Prerequisites
Section titled “Prerequisites”Basic builds require only the .NET SDK. NSmithy bundles the Smithy CLI (including a JRE) inside the NuGet package, so no separate Java or Smithy CLI installation is required.
If you enable SmithyGenerateDocs (Sphinx HTML docs), Python 3.11+ must also
be on your PATH.
Optionally install CSharpier for formatted generated code. NSmithy runs it automatically after codegen when it is available, and skips it otherwise.
Install the NSmithy project templates (one-time):
dotnet new install NSmithy.Templates1. Create the Contracts Project
Section titled “1. Create the Contracts Project”The contracts project owns the Smithy model and distributes it to the server and client.
mkdir HelloWorld && cd HelloWorlddotnet new sln -n HelloWorlddotnet new nsmithy-contracts -n HelloWorld.Contractsdotnet sln add HelloWorld.ContractsThis generates:
HelloWorld.Contracts/ HelloWorld.Contracts.csproj model/ service.smithy ← starter restJson1 HelloService model2. Create the Server
Section titled “2. Create the Server”dotnet new nsmithy-server -n HelloWorld.Server --contracts HelloWorld.Contracts --with-docsdotnet sln add HelloWorld.ServerThe --contracts flag adds a ProjectReference to the contracts project.
--with-docs enables the Smithy docs and OpenAPI endpoints. Build and run:
dotnet run --project HelloWorld.ServerThe server listens on http://localhost:5000. Test it:
curl http://localhost:5000/hello/world# {"message":"Hello, world!"}With --with-docs, two documentation UIs are also available:
/docs— Smithy-generated reference docs for your model/openapi— interactive Scalar UI backed by a generatedopenapi.json
See Endpoint Documentation for details.
3. Create the Client
Section titled “3. Create the Client”dotnet new nsmithy-client -n HelloWorld.Clientdotnet sln add HelloWorld.ClientThe client template defaults to a Maven contracts reference for production use:
it ships a smithy-build.json that pulls the contracts model from a Maven JAR.
For local development, switch to the sibling contracts project instead. Delete
the client’s smithy-build.json — when no smithy-build.json exists at the
project root, NSmithy synthesizes one from the contracts ProjectReference:
rm HelloWorld.Client/smithy-build.jsonThen add a ProjectReference to HelloWorld.Client/HelloWorld.Client.csproj:
<ItemGroup> <ProjectReference Include="../HelloWorld.Contracts/HelloWorld.Contracts.csproj" /></ItemGroup>Then run the client with the server still running:
dotnet run --project HelloWorld.Client# Hello, world!When you’re ready to distribute, see Distributing Contracts to publish the contracts JAR and switch back to a Maven reference.
Walking Through the Code
Section titled “Walking Through the Code”The Model
Section titled “The Model”Open HelloWorld.Contracts/model/service.smithy. The template generates a
minimal restJson1 service with a single operation:
@restJson1service HelloService { version: "2006-03-01" operations: [SayHello]}
@readonly@http(method: "GET", uri: "/hello/{name}")operation SayHello { input := { @required @httpLabel name: String } output := { @required message: String }}@restJson1 is the protocol; it controls serialization and HTTP binding
behavior. @http binds the operation to a route. @httpLabel maps name to
the {name} path segment. All generated code derives from this model; change
the model and rebuild to regenerate it.
Generated Types
Section titled “Generated Types”Running dotnet build invokes the Smithy CLI and generates C# types under
obj/. For the model above you get:
public sealed record SayHelloInput(string Name);public sealed record SayHelloOutput(string Message);And a handler interface the server must implement:
public interface IHelloServiceHandler{ Task<SayHelloOutput> SayHelloAsync( SayHelloInput input, CancellationToken ct = default);}The Server Handler
Section titled “The Server Handler”The generated server uses ASP.NET Core minimal API.
Program.cs registers your handler and maps the routes:
builder.Services.AddHelloServiceHandler<HelloHandler>();
app.MapHelloServiceHttp();HelloHandler (also generated as a starter) returns a greeting:
internal sealed class HelloHandler : IHelloServiceHandler{ public Task<SayHelloOutput> SayHelloAsync( SayHelloInput input, CancellationToken cancellationToken = default ) => Task.FromResult(new SayHelloOutput($"Hello, {input.Name}!"));}Replace the body with your real logic. The compiler enforces that every operation in the model has an implementation — add an operation to the model and the build breaks until you handle it.
The Generated Client
Section titled “The Generated Client”HelloWorld.Client/Program.cs uses the generated typed client:
var client = new HelloServiceClient(new Uri(endpoint));
var response = await client.SayHelloAsync(new SayHelloInput("world"));Console.WriteLine(response.Message);The client and server share the same generated input/output types from the contracts project.
Template Options
Section titled “Template Options”All three templates accept --protocol:
| Value | Protocol |
|---|---|
restJson1 | aws.protocols#restJson1 (default) |
simpleRestJson | alloy#simpleRestJson |
rpcv2Cbor | smithy.protocols#rpcv2Cbor |
grpc | alloy.proto#grpc (experimental) |
Additional options:
dotnet new nsmithy-server --helpdotnet new nsmithy-contracts --helpdotnet new nsmithy-client --helpExample Repository
Section titled “Example Repository”For a more complete example with multiple operations, error types, and a working client/server setup, see nsmithy-minimal.