Skip to content

Commit

Permalink
Prevent using graphtype as model (#3316)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 committed Sep 16, 2022
1 parent ca2c139 commit c458360
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 16 deletions.
14 changes: 14 additions & 0 deletions docs2/site/docs/migrations/migration7.md
Expand Up @@ -555,3 +555,17 @@ services.AddGraphQL(b => b
// other calls
);
```

### 14. Graph types cannot be used as data models

From version 7.1 on, graph types cannot be used as data models. This is because the graph types are
designed to be used as schema definitions, and not as a data model. The following classes
will now throw an exception if a graph type is used as a data model:

- `ObjectGraphType<TSourceType>`
- `InputObjectGraphType<TSourceType>`
- `AutoRegisteringObjectGraphType<TSourceType>`
- `AutoRegisteringInputObjectGraphType<TSourceType>`

If it is necessary to do so, you can derive from the `ObjectGraphType` or `InputObjectGraphType` classes
instead of the generic version.
19 changes: 11 additions & 8 deletions src/GraphQL.Tests/Bugs/BubbleUpTheNullToNextNullable.cs
Expand Up @@ -268,21 +268,26 @@ public BubbleNullSchema()
var query = new ObjectGraphType();

query.Field<NonNullGraphType<DataGraphType>>("nonNullableDataGraph")
.Resolve(c => new DataGraphType { Data = c.Source as Data }
.Resolve(c => new DataModel { Data = c.Source as Data }
);

query.Field<DataGraphType>("nullableDataGraph")
.Resolve(c => new DataGraphType { Data = c.Source as Data }
.Resolve(c => new DataModel { Data = c.Source as Data }
);

query.Field<NonNullGraphType<ListGraphType<NonNullGraphType<DataGraphType>>>>("nonNullableListOfNonNullableDataGraph")
.Resolve(_ => new[] { new DataGraphType() });
.Resolve(_ => new[] { new DataModel() });

Query = query;
}
}

public class DataGraphType : ObjectGraphType<DataGraphType>
public class DataModel
{
public Data Data { get; set; }
}

public class DataGraphType : ObjectGraphType<DataModel>
{
public DataGraphType()
{
Expand All @@ -307,13 +312,11 @@ public DataGraphType()
.Resolve(_ => throw new Exception("test"));

Field<NonNullGraphType<DataGraphType>>("nonNullableNest")
.Resolve(c => new DataGraphType { Data = c.Source.Data.NonNullableNest });
.Resolve(c => new DataModel { Data = c.Source.Data.NonNullableNest });

Field<DataGraphType>("nullableNest")
.Resolve(c => new DataGraphType { Data = c.Source.Data.NullableNest });
.Resolve(c => new DataModel { Data = c.Source.Data.NullableNest });
}

public Data Data { get; set; }
}

public class Data
Expand Down
14 changes: 14 additions & 0 deletions src/GraphQL.Tests/Types/ComplexGraphTypeTests.cs
Expand Up @@ -552,4 +552,18 @@ public void create_fieldbuilder_with_inferred_graph_type()
type.Field<IEnumerable<string>>("field13").Resolve(_ => Array.Empty<string>());
type.Fields.Find("field13").ShouldNotBeNull().Type.ShouldBe(typeof(NonNullGraphType<ListGraphType<GraphQLClrOutputTypeReference<string>>>));
}

[Fact]
public void cannot_use_graphtype_as_model()
{
Should.Throw<InvalidOperationException>(() => new Graph2())
.Message.ShouldBe("Cannot use graph type 'Graph1' as a model for graph type 'Graph2'. Please use a model rather than a graph type for TSourceType.");
Should.Throw<InvalidOperationException>(() => new Graph4())
.Message.ShouldBe("Cannot use graph type 'Graph3' as a model for graph type 'Graph4'. Please use a model rather than a graph type for TSourceType.");
}

private class Graph1 : ObjectGraphType { }
private class Graph2 : ObjectGraphType<Graph1> { }
private class Graph3 : InputObjectGraphType { }
private class Graph4 : InputObjectGraphType<Graph3> { }
}
17 changes: 9 additions & 8 deletions src/GraphQL.Tests/Types/NonNullGraphTypeTests.cs
Expand Up @@ -94,34 +94,35 @@ public NullableSchema()
var query = new ObjectGraphType();

query.Field<NullableSchemaType>("nullable")
.Resolve(c => new NullableSchemaType { Data = c.Source as ExampleContext });
.Resolve(c => new DataModel { Data = c.Source as ExampleContext });
query.Field<NonNullableSchemaType>("nonNullable")
.Resolve(c => new NonNullableSchemaType { Data = c.Source as ExampleContext });
.Resolve(c => new DataModel { Data = c.Source as ExampleContext });

Query = query;
}
}

public class NullableSchemaType : ObjectGraphType<NullableSchemaType>
public class DataModel
{
public ExampleContext Data { get; set; }
}

public class NullableSchemaType : ObjectGraphType<DataModel>
{
public NullableSchemaType()
{
Field<IntGraphType>("a").Resolve(_ => _.Source.Data.A);
Field<BooleanGraphType>("b").Resolve(_ => _.Source.Data.B);
Field<StringGraphType>("c").Resolve(_ => _.Source.Data.C);
}

public ExampleContext Data { get; set; }
}

public class NonNullableSchemaType : ObjectGraphType<NonNullableSchemaType>
public class NonNullableSchemaType : ObjectGraphType<DataModel>
{
public NonNullableSchemaType()
{
Field<NonNullGraphType<IntGraphType>>("a").Resolve(_ => _.Source.Data.A);
Field<NonNullGraphType<BooleanGraphType>>("b").Resolve(_ => _.Source.Data.B);
Field<NonNullGraphType<StringGraphType>>("c").Resolve(_ => _.Source.Data.C);
}

public ExampleContext Data { get; set; }
}
3 changes: 3 additions & 0 deletions src/GraphQL/Types/Composite/ComplexGraphType.cs
Expand Up @@ -17,6 +17,9 @@ public abstract class ComplexGraphType<TSourceType> : GraphType, IComplexGraphTy
/// <inheritdoc/>
protected ComplexGraphType()
{
if (typeof(IGraphType).IsAssignableFrom(typeof(TSourceType)) && GetType() != typeof(Introspection.__Type))
throw new InvalidOperationException($"Cannot use graph type '{typeof(TSourceType).Name}' as a model for graph type '{GetType().Name}'. Please use a model rather than a graph type for {nameof(TSourceType)}.");

Description ??= typeof(TSourceType).Description();
DeprecationReason ??= typeof(TSourceType).ObsoleteMessage();
}
Expand Down

0 comments on commit c458360

Please sign in to comment.