4

I have a simple enum I am trying to include in my GraphQL type and am receiving teh following error:

The GraphQL type for Field: 'Category' on parent type: 'NewsItemType' could not be derived implicitly.

------------------The GraphQL type for Field: 'Category' on parent type: 'NewsItemType' could not be derived implicitly.

---------------The type: NewsType cannot be coerced effectively to a GraphQL type Parameter name: type

my simple enum looks like:

public enum NewsType
{
    General = 0,

    Business = 1,

    Entertainment = 2,

    Sports = 3,

    Technology = 4
}

The GraphQL ObjectGraphType that it is included in:

public class NewsItemType : ObjectGraphType<NewsItemViewModel>
{
    public NewsItemType()
    {
        Field(x => x.Id).Description("Id of a news item.");
        Field(x => x.Title).Description("Title of a new item.");
        Field(x => x.Description).Description("Description of a news item.");
        Field(x => x.Author).Description("Author of a news item.");
        Field(x => x.Url).Description("URI location of the news item");
        Field(x => x.ImageUrl).Description("URI location of the image for the news item");
        Field(x => x.PublishDate).Description("Date the news item was published");
        Field(x => x.Category).Description("Category of the news item.");
    }
}

and finally, teh viewmodel that the graphql type is based on:

public class NewsItemViewModel : ViewModelBase
{
    public string Title { get; set; }

    public string Author { get; set; }

    public string Description { get; set; }

    public string Url { get; set; }

    public string ImageUrl { get; set; }

    public DateTime PublishDate { get; set; }

    public NewsType Category { get; set; }
}

What am I doing wrong here and how can I overcome it?

EDIT: my query contains the following:

        Field<ListGraphType<NewsItemType>>(
            name: "newsItems",
            arguments: new QueryArguments(
                new QueryArgument<IntGraphType>() { Name = "count" },
                new QueryArgument<IntGraphType>() { Name = "category" }),
            resolve: context =>
            {
                var count = context.GetArgument<int?>("count");
                var category = context.GetArgument<int>("category");
                var newsType = (NewsType)category;

                if (count.HasValue)
                {
                    return newsItemService.GetMostRecent(newsType, count.Value);
                }
                else
                {
                    return newsItemService.GetMostRecent(newsType);
                }
            }
        )
Community
  • 1
  • 1
GregH
  • 5,125
  • 8
  • 55
  • 109

2 Answers2

7

I had a very hard time getting this to work as well. Official documentation definitely seems to be lacking in this regard. The way I got it to work was based on something I found in this article.

For your scenario, you would create a 'GraphType' class for your enum as follows:

public class NewsEnumType : EnumerationGraphType<NewsType>
{
}

Then update your field to:

Field<NewsEnumType>(nameof(NewsItemViewModel.Category)).Description("Category of the news item.");

One other thing to mention that I ran into with EnumTypes that I wasn't expecting. If you are using an enum as a parameter, do what you did above where you ingest it as an IntGraphType and then cast it to your enum type (NewsType)category

    Field<ListGraphType<NewsItemType>>(
        name: "newsItems",
        arguments: new QueryArguments(
            new QueryArgument<IntGraphType>() { Name = "count" },
            new QueryArgument<IntGraphType>() { Name = "category" }),
        resolve: context =>
        {
            var count = context.GetArgument<int?>("count");
            var category = context.GetArgument<int>("category");
            var newsType = (NewsType)category;

            if (count.HasValue)
            {
                return newsItemService.GetMostRecent(newsType, count.Value);
            }
            else
            {
                return newsItemService.GetMostRecent(newsType);
            }
        }
    )

My enum was part of a complex object that I was passing as a parameter, more like new QueryArgument<NewsItemType>() { Name = "newsItem" },

If you are going to do that, then the category property on the object passed to the server needs to be a string. So, if the category you are passing back to the server is Business = 1, then you would need to pass category: 'Business' and NOT category: 1.

peinearydevelopment
  • 11,042
  • 5
  • 48
  • 76
  • Thanks for the answer. I ran into this too. It's disappointing, because the GraphQL .NET documentation explicitly states that the "Expression syntax" should work in this case. Maybe it's a bug? – Homr Zodyssey Jul 23 '21 at 13:55
6

Here's a quick way to do this for your case. Basically you don't use the default lambda expression Field. Instead actually write out a resolver yourself and convert the enum to the proper type. This is helping GraphQL to convert the type properly into the type you want to return.

Field<IntGraphType>("category", resolve: context => (int)context.Source.Category);

If your enum was a string, you could do the same for that as well.

Field<StringGraphType>("category", resolve: context => context.Source.Category.ToString());

There is another, more verbose way, shared in this answer where you inherit from the EnumerationGraphType<T> first and then do the same custom resolver as above.

https://stackoverflow.com/a/56051133/11842628

Hardik Goel
  • 71
  • 1
  • 3