Skip to content

Exposing types

When working with a traditional REST API, the shape of the data we can query is defined by the different endpoints' responses, often defined through DTOs that aim to expose only what is relevant for that specific endpoint and hide any domain details that should not be leaked.

Object types

While it is possible to define our GraphQL by using DTOs and certain mapping libraries, we highly encourage using the type system to customize our objects instead. What in the REST world would be done as follows:

C#
public class User
{
    public string UserName { get; set;}

    public string EmailAddress { get; set; }

    public string Password { get; set;}
}

public record UserDto
{
    public string UserName { get; set;}

    public string EmailAddress { get; set; }
}

Can be achieved by defining a GraphQL user type

C#
1
2
3
4
5
6
7
public class UserType : ObjectType<User>
{
    protected override void Configure(IObjectTypeDescriptor<User> descriptor)
    {
        descriptor.Ignore(user => user.Password)
    }
}

Object types can then be registered with the module options

C#
public class MyApplicationModule : SuiteModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        builder.DependsOn<GraphQLModule, GraphQLModuleOptions>(opts =>
        {
            opts.AddType<User, UserType>();
        })
    }
}

Interface types

The GraphQL module also allows to declare types as interface types. In this case you do not need to define a custom type and can reference the domain type directly.

C#
public class Vehicle
{
    public virtual int Wheels { get; set; }
}


public class Car : Vehicle
{
    public override int Wheels { get; set; } = 4;
}

public class MyApplicationModule : SuiteModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        builder.DependsOn<GraphQLModule, GraphQLModuleOptions>(opts =>
        {
            opts.AddInterfaceType<Vehicle>();
            opts.AddType<Car>();
        })
    }
}

Note

The AddType<TEntity>() overload registers a default ObjectType<TEntity> type. This is usually not required unless you are defining an interface type with derived types.