Skip to content

About

A minimal REST example with NSmithy

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

NSmithy Minimal Example

A minimal example of NSmithy — a C# implementation of the Smithy IDL.

The service is the Weather example from the Smithy quickstart: a REST API that exposes city resources with paginated listing and per-city weather forecasts.

Projects

  • Weather.Contracts — Smithy model (model/weather.smithy). Builds the contract and generates C# types used by both the server and client.
  • Weather.Server — ASP.NET Core server with a hardcoded in-memory implementation.
  • Weather.Client — Console app that exercises the API end-to-end.

Prerequisites

Requires the .NET SDK (10.0+), the Smithy CLI (1.73.0+, on PATH) for code generation, and Python (for Smithy doc generation).

Alternatively, use pixi to drop into a dev shell that provides all three (on macOS, Linux and Windows):

pixi shell

If you'd rather not install the Smithy CLI, reference the NSmithy.SmithyCli package instead, which bundles it with its Java runtime — add this to Directory.Packages.props:

<ItemGroup>
  <GlobalPackageReference Include="NSmithy.SmithyCli" Version="1.73.0" />
</ItemGroup>

Running

just is available in the pixi shell:

just server         # start the server
just client         # run the client against http://localhost:5000
just client-debug   # same, with wire-level request/response logging

Or directly with the .NET CLI:

dotnet run --project Weather.Server
dotnet run --project Weather.Client

The client connects to http://localhost:5000 by default. Pass a different URL as an argument if needed:

just client http://localhost:8080
# or
dotnet run --project Weather.Client -- http://localhost:8080

Pass --debug to log requests, responses, and wire bytes (this is what just client-debug does):

dotnet run --project Weather.Client -- --debug

Rejecting a bad request

The server enforces the model at the boundary, so a request that violates it is answered with a structured 4xx rather than reaching the handler. Nothing in the handlers implements these checks — they are generated from the model.

CityId is declared @pattern("^[A-Za-z0-9 ]+$"), so a city ID carrying a character the pattern excludes is rejected with ValidationException, which names the member and the constraint it failed:

curl -i 'http://localhost:5000/cities/SEA%21'   # "SEA!"
HTTP/1.1 400 Bad Request
X-Amzn-Errortype: ValidationException

{"message":"1 validation error detected. Value at '/cityId' failed to satisfy
constraint: Member must satisfy regular expression pattern: ^[A-Za-z0-9 ]+$",
"fieldList":[{"path":"/cityId","message":"..."}]}

Input that cannot become modeled input at all fails earlier, during deserialization, and comes back as SerializationException — here pageSize is modeled as Integer:

curl -i 'http://localhost:5000/cities?pageSize=abc'
HTTP/1.1 400 Bad Request
X-Amzn-Errortype: SerializationException

{"message":"Value 'abc' is not a valid integer."}

An Accept header that excludes the response's media type is answered with 406:

curl -i -H 'Accept: application/xml' http://localhost:5000/cities/SEA
HTTP/1.1 406 Not Acceptable
X-Amzn-Errortype: NotAcceptableException

{"message":"Response is 'application/json', which Accept 'application/xml' excludes."}

A request that satisfies the model but names something absent still reaches the handler and returns the error the operation models — a space is inside CityId's pattern, so this is a NoSuchResource, not a validation failure:

curl -i 'http://localhost:5000/cities/%20'
HTTP/1.1 400 Bad Request
X-Amzn-Errortype: NoSuchResource

{"resourceType":"City"}

The client exercises both of these — a modeled NoSuchResource and an implicit ValidationException — as typed exceptions rather than bare status codes.

Once the server is running, the following endpoints are also available:

  • Scalar API explorer — http://localhost:5000/openapi
  • Smithy docs — http://localhost:5000/docs

About

A minimal REST example with NSmithy

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages