JsonApiClient returns nullable Responses


Why does the API client (IJsonServiceClient) return a nullable response?
The GetAsync Method should return either the response or an exception but not null.
What do i miss here?

The client interfaces have existed since the dawn of ServiceStack, which have many implementors, long before #nullable was added to C#. This interface doesn’t change the behavior of the concrete JsonApiClient that implements.

Is there a reason why you’re using IJsonServiceClient instead of the concrete JsonApiClient?

We use the Interface for decoupeling reasons, to avoid working directly with the Implementation. The concrete Implementation which gets injected is the JsonApiClient. But even if i use the concrete Implementation directly, the IDE still suggests that the response could be nullable.


My Question here is, wouldn’t it make sense to annotate the function, so nullable response is not possible? Either a response is given or an exception is thrown, a nullable response is not an option in cases where the Request has a IReturn<TResponse> defined.
Or Is there a way how i can generate the dto’s with #nullable enable?

The JsonApiClient is already annotated with #nullable enable and all the APIs on the concrete JsonApiClient don’t return nullable responses:

Which is what I’m seeing:

Not sure why your IDE is reporting it differently. Does your ServiceModel.csproj have nullable enabled?

In the meantime I’ve just added #nullable enable to all client interfaces (and all types in top-level ServiceStack.Interfaces project) in this commit. With this change even the IServiceClient interfaces report non nullable responses:

This change is available from v8.8.1+ which is now available in pre-release packages


FYI as JsonApiClient uses HttpClient you don’t want to be using it with using var or calling Dispose() on it manually. It’s instead recommended to use the ASP .NET Core’s IHttpClientFactory Registration, e.g:

builder.Services.AddJsonApiClient(builder.Configuration["BaseUrl"]);

Which just registers JsonApiClient as a Typed Client:

services.AddHttpClient<JsonApiClient>(client => client.BaseAddress = new Uri(baseUrl));

Where you’ll be able to inject JsonApiClient as a dependency into your C# client Apps.

 var result = await jsonClient.GetAsync(new GetCantonRequest
            {
                CantonId = cantonId
            });

The problem is that the request GetCantonRequest comes from the generated dto file and even though we enable nullable in the csproj. Rider still thinks it could return nullable if we do not define the type parameter explicitly. The issue is only resolved when we add the #nullable enable to the generated dto file. So my question is, is there a way to generate the dto’s with #nullable enable set?

I don’t see how nullable reference types on DTOs are going to have an effect on the return signature of an instance type.

The screenshots above are from Rider using DTOs in the ServiceModel.csproj with only <Nullable>enable</Nullable> (i.e. without #nullable enable on any file).

The header comments should remain at the top of the generated DTOs fails so they’re recognized by tools that update them. You can generate code below the using declarations with:

CSharpGenerator.InsertCodeFilter = (type, code) => "#nullable enable\n";

I’ve just tried this in Rider and it appears that it still has an effect of enabling nullable reference type checks.

This solutions works. Thank you.
Now we have one last issue. We have a server which runs on .Net v4.8. We fetch dto’s from this server with AddNullableAnnotations config set to true in the dto file. The dto’s generated gives us properties which have reference types marked as null even though they cannot be null from business logic perspective. How can we mark these properties, so that servicestack dto generation does not add nullable annotation to these?

Code on Server (.Net 4.8)

public class GetMacroregionCoordinateResponse
    {
        public MasterDataCoordinateModel Entity { get; set; }
    }

dto’s generated

[GeneratedCode("AddServiceStackReference", "8.72")]
    public partial class GetMacroregionCoordinateResponse
    {
        public virtual MasterDataCoordinateModel? Entity { get; set; }
    }

We do not want MasterDataCoordinateModel marked as nullable in the dto.

The default behavior should be to not generate DTOs with nullable reference types. You would need to opt into generating DTOs will nullable reference types by uncommenting AddNullableAnnotations:

/* Options:
Date: 2025-06-04 16:51:08
Version: 8.81
....

AddNullableAnnotations: True

If your server DTOs does not have #nullable enable enabled and you would still like to generate DTOs with nullable notations you can mark that a Reference Type is required by using the [Required] attribute, e.g:

public class GetMacroregionCoordinateResponse
{
    [Required]
    public MasterDataCoordinateModel Entity { get; set; }
}
1 Like

Wouldn’t it make sense to add required to the property in the generated dto, when the Attribute [Required] is set on the Server side for example her the result should look like this:

public required MasterDataCoordinateModel Entity { get; set; }

Currently i have solved this with the PropertyTypeFilter

CSharpGenerator.PropertyTypeFilter = (generator, type, property) => $"{(property.IsRequired ?? false ? "required " : string.Empty)}{generator.GetPropertyType(property)}";

But maybe this would make sense to support in the CSharpGenerator directly.

If you can use the required modifier, you can enable nullable annotations. The [Required] attribute is when that’s not available.

Let’s say i have a .Net Framework v4.8 API, which defines it’s dto like this:

public class GetMacroregionCoordinateResponse
{
    [Required]
    public MasterDataCoordinateModel Entity { get; set; }
}

and i have a .Net Core v8 Client which uses the API and wants to generate the dto’s with nullable annotations enabled. The generated dto looks like this:

  #nullable enable

  [GeneratedCode("AddServiceStackReference", "8.60")]
  public partial class GetMacroregionCoordinateResponse
  {
      [Required]
      public virtual MasterDataCoordinateModel Entity { get; set; }
  }

This will result in this Error:

Error CS8618 : Non-nullable property 'Entity' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

That’s why it would be nice to have the ability to set the required on the property. Currently i’ve solve the issue with this line:

CSharpGenerator.PropertyTypeFilter = (generator, type, property) => $"{(property.IsRequired ?? false ? "required " : string.Empty)}{generator.GetPropertyType(property)}";

It isn’t a compiler error by default, you would have to have reporting warnings as errors configured, which I wouldn’t for serializable types or generated code you don’t control.

1 Like