VB ServiceStack Reference

Add ServiceStack Reference generates your API's VB.NET DTOs from a running ServiceStack App. It gives VB.NET clients an end-to-end typed API without sharing the server's ServiceModel assembly, so client and server projects can be versioned, deployed and updated independently.

The generated source retains routes, HTTP verb markers, response types, validation metadata, inheritance, collections, enums and AutoQuery conventions. Existing desktop and line-of-business applications can consume new APIs without a hand-written HTTP or JSON layer.

Modern typed APIs for VB.NET

VB.NET uses the same current JsonApiClient and ServiceStack.Client package as C#:

Dim client = New JsonApiClient("https://api.example.com")

Dim response = client.Get(New Hello With {.Name = "World"})
Console.WriteLine(response.Result)

Both asynchronous and blocking APIs are available, fitting event-driven desktop applications, ASP.NET, batch jobs, scheduled integrations and test projects.

Add ServiceStack Reference

Use the cross-platform x tool from any IDE or build environment:

dotnet tool install --global x
x vbnet https://api.example.com
dotnet add package ServiceStack.Client

This saves the generated contract to dtos.vb. The vb alias provides a shorter command:

x vb https://api.example.com

Visual Studio users can alternatively use ServiceStackVS's Add ServiceStack Reference project context menu, which adds the generated DTOs and ServiceStack.Client package.

Update ServiceStack Reference

After the API contract changes, run this from the client solution:

x vbnet

The tool finds existing references from the BaseUrl in their generated headers and preserves uncommented customization options. You can also update one file directly with x dtos.vb. In Visual Studio, use Update ServiceStack Reference on the generated file.

Generated files should be treated as replaceable source. Put client-only behavior in separate Partial Class files.

What is generated

A Hello API is emitted with its routes, supported attributes and inferred response marker:

<Route("/hello")>
<Route("/hello/{Name}")>
Public Partial Class Hello
    Implements IReturn(Of HelloResponse)

    <Required>
    Public Overridable Property Name As String

    Public Overridable Property Title As String
End Class

Public Partial Class HelloResponse
    Public Overridable Property Result As String
End Class

The generated contract provides:

  • IReturn(Of HelloResponse) for compile-time response inference.
  • <Route> metadata for custom route selection and path substitution.
  • IGet, IPost, IPut, IPatch and IDelete markers for Send/SendAsync HTTP method inference.
  • IReturnVoid for commands which intentionally return no response body.
  • Native .NET representations for enums, arrays, List(Of T), dictionaries, inheritance, nested types and interfaces.
  • Supported descriptions and serialization attributes for IntelliSense and wire compatibility.
Generated contract Typed VB.NET result
IReturn(Of String) String
IReturn(Of Item()) Array
IReturn(Of List(Of Item)) Generic collection
IReturn(Of Dictionary(Of String, Item)) Typed dictionary
IReturn(Of QueryResponse(Of Item)) AutoQuery results, totals and metadata
IReturn(Of Byte()) Raw binary response
IReturn(Of Stream) Response stream
IReturnVoid No response body

Call generated APIs

Use an explicit HTTP method when the caller should choose it:

Dim syncResponse = client.Post(New Hello With {.Name = "World"})
Dim asyncResponse = Await client.PostAsync(
    New Hello With {.Name = "World"}, cancellationToken)

When the generated request has a verb marker, SendAsync chooses it automatically:

Public Class HelloGet
    Implements IReturn(Of HelloVerbResponse)
    Implements IGet

    Public Property Id As Integer
End Class

Dim response As HelloVerbResponse = Await client.SendAsync(
    New HelloGet With {.Id = 1}, cancellationToken)

Current JsonApiClient capabilities

JsonApiClient is the current HttpClient-based implementation for .NET 6+. It uses /api/ as the fallback route, prefers matching custom routes for explicit HTTP methods, and defaults unmarked Send requests to POST.

It can be registered with .NET's typed client factory:

builder.Services.AddJsonApiClient("https://api.example.com")

It also supports:

  • Per-call cancellation with CancellationToken.
  • Cookie, Basic, Bearer Token and automatic Refresh Token authentication.
  • Request/response filters, custom headers, URL resolvers and request compression.
  • Direct String, Byte() and Stream responses in addition to JSON DTOs.
  • Batching, one-way publishing, file uploads, multipart forms and custom HTTP methods.
  • Both synchronous and asynchronous APIs.

Configure automatic token renewal when an authenticated API returns 401:

Dim client = New JsonApiClient("https://api.example.com") With {
    .BearerToken = auth.BearerToken,
    .RefreshToken = auth.RefreshToken,
    .EnableAutoRefreshToken = True
}

The client's SessionId and Version are also copied onto generated requests implementing IHasSessionId and IHasVersion.

Handle errors as values

ApiAsync returns ApiResult(Of TResponse) so validation and API failures can remain normal application values:

Dim api = Await client.ApiAsync(
    New Hello With {.Name = form.Name}, cancellationToken)

If api.Succeeded Then
    Console.WriteLine(api.Response.Result)
Else
    Console.WriteLine($"{api.Error?.ErrorCode}: {api.ErrorMessage}")
    Console.WriteLine(api.FieldErrorMessage(NameOf(form.Name)))
End If

ApiResult(Of T) also exposes Errors, ErrorSummary, FieldError(), FieldErrorMessage() and HasFieldError() for form and validation workflows.

The lower-level client APIs throw WebServiceException for failed responses:

Try
    Dim response = Await client.PostAsync(
        New Hello With {.Name = Nothing}, cancellationToken)
Catch ex As WebServiceException
    Console.WriteLine($"{ex.StatusCode} {ex.StatusDescription}")
    Console.WriteLine($"{ex.ResponseStatus.ErrorCode}: {ex.ResponseStatus.Message}")
End Try

Batch and one-way requests

Send multiple requests of the same type in a single HTTP request:

Dim requests = {
    New Hello With {.Name = "A"},
    New Hello With {.Name = "B"},
    New Hello With {.Name = "C"}
}

Dim responses As List(Of HelloResponse) =
    Await client.SendAllAsync(requests, cancellationToken)

Use PublishAsync or PublishAllAsync for one-way commands which do not need a response DTO:

Await client.PublishAsync(
    New HelloReturnVoid With {.Id = 1}, cancellationToken)

Typed AutoQuery

Generated AutoQuery requests retain their generic query contracts:

<Route("/rockstars", "GET")>
Public Partial Class QueryRockstars
    Inherits QueryDb(Of Rockstar)
    Implements IReturn(Of QueryResponse(Of Rockstar))
End Class

Use inherited paging, ordering, projection and metadata properties with typed results:

Dim query = Await client.GetAsync(New QueryRockstars With {
    .Skip = 0,
    .Take = 25,
    .OrderBy = "Age"
}, cancellationToken)

Console.WriteLine($"Showing {query.Results.Count} of {query.Total}")

GetLazy() also provides lazy synchronous enumeration across AutoQuery pages.

Rich .NET data contracts

Generated DTOs preserve .NET primitives and compound types including nullable values, Decimal, Guid, DateTime, DateTimeOffset, TimeSpan, Byte(), arrays, List(Of T) and nested dictionaries. The same serializer handles route, query-string and request-body values, avoiding transport-specific mapping code.

File uploads

Combine a generated Request DTO with a file stream:

Using audio = File.OpenRead("recording.wav")
    Dim response As TextGenerationResponse =
        Await client.PostFileWithRequestAsync(
            New SpeechToText With {
                .RefId = "task-42",
                .Tag = "meeting"
            },
            New UploadFile("recording.wav", audio, NameOf(SpeechToText.Audio)),
            cancellationToken)
End Using

Use PostFilesWithRequestAsync for multiple streams or ApiFormAsync when multipart form failures should be returned as ApiResult(Of T).

Proxy and API gateway endpoints

The Base URL can include a path prefix, allowing the same generated DTOs to call a downstream ServiceStack API through a proxy or gateway:

Dim client = New JsonApiClient(
    "https://gateway.example.com/techstacks")

Dim response = Await client.GetAsync(
    New GetTechnology With {.Slug = "ServiceStack"}, cancellationToken)

Typed responses and structured WebServiceException errors continue to work through the proxy. This is useful for exposing multiple internal services behind one public host or applying tenant-specific routing.

Integration testing

Generated contracts make black-box API tests concise and representative of production clients:

<Test>
Public Async Function EchoesSupportedValues() As Task
    Dim client = New JsonApiClient(TestConfig.BaseUrl)
    Dim request = New EchoTypes With {
        .Int = 3,
        .Float = 1.1F,
        .String = "value"
    }

    Dim response = Await client.PostAsync(request)

    Assert.That(response.Int, [Is].EqualTo(request.Int))
    Assert.That(response.Float, [Is].EqualTo(request.Float))
    Assert.That(response.String, [Is].EqualTo(request.String))
End Function

The same pattern covers authenticated APIs, validation failures, AutoQuery and APIs exposed behind proxy path prefixes.

Use in any .NET App

Because a ServiceStack Reference is ordinary VB.NET source and ServiceStack.Client supports current .NET targets, the same contract and client patterns can be shared across ASP.NET Core, Blazor, MAUI, desktop, console, worker and test projects.

DTO customization options

The options in each generated file's header control how its VB.NET DTOs are generated. Triple-commented options are server defaults. To override one, change its ''' prefix to a single ', update the value, then run x vbnet or use Visual Studio's Update ServiceStack Reference action:

' Options:
'Date: 2026-08-27 12:00:00
'Version: 10.1.5
'Tip: To override a DTO option, remove "''" prefix before updating
'BaseUrl: https://api.example.com
'
'''GlobalNamespace: 
'''MakePartial: True
'''MakeVirtual: True
'''MakeDataContractsExtensible: False
'''AddReturnMarker: True
'''AddDescriptionAsComments: True
'''AddDataContractAttributes: False
'''AddIndexesToDataMembers: False
'''AddGeneratedCodeAttributes: False
'''AddResponseStatus: False
'''AddImplicitVersion: 
'''InitializeCollections: False
'''ExportValueTypes: False
'''IncludeTypes: 
'''ExcludeTypes: 
'''AddNamespaces: 
'''AddDefaultXmlNamespace: http://schemas.servicestack.net/types

To override an option, change its prefix from triple ''' to a single '. This convention is used because VB.NET has no block comment syntax. For example, this disables partial classes:

' Options:
'Date: 2026-08-27 12:00:00
'Version: 10.1.5
'BaseUrl: https://api.example.com
'
'MakePartial: False
'''MakeVirtual: True
'''MakeDataContractsExtensible: False
'''AddReturnMarker: True
'''AddDescriptionAsComments: True
'''AddDataContractAttributes: False
'''AddIndexesToDataMembers: False
'''AddGeneratedCodeAttributes: False
'''AddResponseStatus: False
'''AddImplicitVersion: 
'''InitializeCollections: True
'''ExportValueTypes: False
'''IncludeTypes: 
'''ExcludeTypes: 
'''AddNamespaces: 
'''AddDefaultXmlNamespace: http://schemas.servicestack.net/types

Options that do not start with a ''' are sent to the server to override any defaults set by the server.

Change Default Server Configuration

The defaults can also be overridden on the ServiceStack server by modifying the NativeTypesFeature configuration:

var nativeTypes = this.GetPlugin<NativeTypesFeature>();
nativeTypes.MetadataTypesConfig.MakeVirtual = false;

The following options control the generated source.

MakePartial

Adds the Partial modifier to generated types, letting you extend DTOs in separate source files:

Public Partial Class GetAnswers

MakeVirtual

Adds the Overridable modifier to all properties:

Public Partial Class GetAnswers
    ...
    Public Overridable Property QuestionId As Integer
End Class

MakeDataContractsExtensible

Add .NET's DataContract ExtensionDataObject to all DTOs:

Public Partial Class Hello
            ...
    Implements IExtensibleDataObject
            ...
    Public Overridable Property ExtensionData As ExtensionDataObject Implements IExtensibleDataObject.ExtensionData
End Class

AddReturnMarker

AddReturnMarker annotates Request DTOs with an IReturn(Of T) marker referencing the response type ServiceStack infers the Service returns:

Public Partial Class GetAnswers
    Implements IReturn(Of GetAnswersResponse)

The original DTO does not need a return marker. ServiceStack can infer its response from the Service return type or the %Response DTO naming convention.

AddDescriptionAsComments

Converts text from <Description> attributes into VB.NET documentation comments, providing IntelliSense in client projects:

'''<Summary>
'''Get a list of Answers for a Question
'''</Summary>
Public Class GetAnswers

AddDataContractAttributes

Decorates all DTO types with <DataContract> and properties with <DataMember>, and adds default XML namespaces for the generated VB.NET namespaces:

<Assembly: ContractNamespace("http://schemas.servicestack.net/types", ClrNamespace:="StackApis.ServiceModel.Types")>
<Assembly: ContractNamespace("http://schemas.servicestack.net/types", ClrNamespace:="StackApis.ServiceModel")>
...
<DataContract>
Partial Public Class GetAnswers
    Implements IReturn(Of GetAnswersResponse)
    <DataMember>
    Public Overridable Property QuestionId As Integer
End Class

AddIndexesToDataMembers

Populates a DataMember Order index for all properties:

<DataContract>
Public Partial Class GetAnswers
    ...
    <DataMember(Order:=1)>
    Public Overridable Property QuestionId As Integer
End Class

Requires AddDataContractAttributes=true

AddGeneratedCodeAttributes

Emits a <GeneratedCode> attribute on every generated type:

<GeneratedCode("AddServiceStackReference", "10.1.5")>
Public Partial Class GetAnswers ...

AddResponseStatus

Automatically adds a ResponseStatus property to response DTOs which do not already define one:

Public Partial Class GetAnswers
    ...
    Public Overridable Property ResponseStatus As ResponseStatus
End Class

AddImplicitVersion

Specifies the version number automatically populated in every Request DTO sent from the client:

Public Partial Class GetAnswers
    Public Overridable Property Version As Integer
    Public Sub New()
                Version = 1
    End Sub
    ...
End Class

This identifies the service-contract version used by existing clients, making it easier to implement ServiceStack's recommended versioning strategy.

InitializeCollections

Automatically initializes collections in generated DTOs:

Public Partial Class SearchQuestions
    Public Overridable Property Tags As List(Of String) = New List(Of String)
    ...
End Class

ExportValueTypes

By default custom value types are represented as strings unless they are enums. Enable ExportValueTypes to emit and reference their value type definitions instead:

' Options:
'ExportValueTypes: True

IncludeTypes

Specifies only the types you want generated:

' Options:
'IncludeTypes: GetTechnology,GetTechnologyResponse

Only generates the GetTechnology and GetTechnologyResponse DTOs:

Public Partial Class GetTechnology ...
Public Partial Class GetTechnologyResponse ...

Include Request DTO and its dependent types

You can include a Request DTO and all its dependent types with a .* suffix on the Request DTO, e.g:

' Options:
'IncludeTypes: GetTechnology.*

This includes the GetTechnology Request DTO, its GetTechnologyResponse Response DTO and all types referenced by either DTO.

Include All Types within a C# namespace

If your DTOs are grouped into different namespaces, include a complete C# namespace with the /* suffix:

' Options:
'IncludeTypes: MyApp.ServiceModel.Admin/*

This includes all DTOs within the MyApp.ServiceModel.Admin C# namespace.

ExcludeTypes

Specifies types to exclude from generation:

' Options:
'ExcludeTypes: GetTechnology,GetTechnologyResponse

Excludes the GetTechnology and GetTechnologyResponse DTOs from generation.

AddNamespaces

Include additional VB.NET namespaces, e.g:

' Options:
'AddNamespaces: System.Drawing,MyApp

Where it will generate the specified namespaces in the generated Types:

Imports System.Drawing
Imports MyApp

AddDefaultXmlNamespace

This lets you change the default DataContract XML namespace used for all namespaces:

<Assembly: ContractNamespace("http://my.types.net", ClrNamespace:="StackApis.ServiceModel.Types")>
<Assembly: ContractNamespace("http://my.types.net", ClrNamespace:="StackApis.ServiceModel")>

Requires AddDataContractAttributes=true