Laden...

[gelöst] ASP.NET Core GraphQL Typ kann nicht abgefragt werden

Erstellt von Olii vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.085 Views
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren
[gelöst] ASP.NET Core GraphQL Typ kann nicht abgefragt werden

Hallo, ich beschäftige mich immer noch mit GraphQL und asp.net core. Ich habe einige Beispiele durch Tutorials etc. nach geschrieben und mir die Doku durch gelesen und wollte nun selber mal eine API mit GraphQL schreiben. Nun scheitere ich allerdings schon an einer Sache.

Ich habe es mit einem meiner Funktionierenden Beispiele abgeglichen und kann nicht feststellen was ich denn falsch gemacht habe.

Zuerst habe ich ein Model erstellt:


public class UserAccount
    {
        public int id {get;set;}
        public string login_name {get;set;}

    }

public class GraphQLQuery
    {
        public string OperationName { get; set; }
        public string NamedQuery { get; set; }
        public string Query { get; set; }
        public JObject Variables { get; set; }
    }

Dann den Type dafür:


public class UserAccountType : ObjectGraphType<UserAccount>
    {
        public UserAccountType()
        {
            Name = "UserAccount";

            Field(x => x.id, type: typeof(IdGraphType)).Description("UserAccount id");
            Field(x => x.login_name).Description("The login name");
        }
    }

Da nach die Query Klasse die ich DataQuery genannt habe:


public class DataQuery : ObjectGraphType
    {
        public DataQuery()
        {
            Field<UserAccountType>(
                "UserAccount",
                arguments: new QueryArguments(
                    new QueryArgument<IdGraphType> { Name = "id", Description = "The ID of the Author." }),
                resolve: context =>
                {
                    UserAccount useracc = new UserAccount();
                    useracc.id = 4;
                    useracc.login_name = "Test";
                    return useracc;
                }
            );
        }
    }

Die soll auch noch gar nichts Sinnvolles zurückgeben, deswegen gibt es einfach nur einen neuen UserAccount aus.

Und zum Schluss habe ich einfach den Controller wie folgt erstellt:


public async Task<IActionResult> Post([FromBody] GraphQLQuery query)
        {
            var inputs = query.Variables.ToInputs();

            var schema = new Schema
            {
                Query = new DataQuery()
            };

            var result = await new DocumentExecuter().ExecuteAsync(_ =>
            {
                _.Schema = schema;
                _.Query = query.Query;
                _.OperationName = query.OperationName;
                _.Inputs = inputs;
            });

            if(result.Errors?.Count > 0)
            {
                return BadRequest();
            }

            return Ok(result);
        }

Wenn ich nun eine Query wie diese ausführe:


{ 
 "query":
  "{
  useraccount(id:1) {
    id
  }
 }"
}

Dann wird in der QueryClass anscheinend gar nicht der neue UserAccount erstellt und zurück gegeben. Ich weiß leider auch nicht wieso und auch noch nicht so richtig wie ich das Debuggen kann. ich versuche es seit Stunden und verstehe nicht wieso ich einen Fehler zurück bekomme.

Wenn ich die Query so formuliere, erhalte ich den selben "Fehler" (Fehler im Sinne von ich erhalte nur ein BadRequest bzw. halt kein Ergebnis)


{ 
 "query":
  "{
  useraccount {
    id
  }
 }"
}

Hat jemand vielleicht eine Idee?

16.806 Beiträge seit 2008
vor 4 Jahren

Mein Beispiel zu meinen Talks zu GraphQL ist folgendes: https://github.com/BenjaminAbt/2018-Talks-ModernApiDevelopment/tree/master/src/GraphQLApi

In GraphQL erzeugt man Entitäten nicht über Query, sondern über eine Mutation.
Querys sind reine Abfragen - keine Manipulationen. Null. Beginne nicht hier schon mit einer Standardverletzung.

Der wichtigste Punkt bei GraphQL ist das Schema (also der ObjectGraphType, Du hast es einfach nur DataQuery genannt).
Hier erkennt GraphQL welcher Query/Mutation nachher auf welche Func gemappt ist.
Das ist auch die richtige Stelle für das Debuggen.
Da gehört aber keine Logik rein. Entweder man spricht hier mit Services, oder wie ich mit einem Mediator.

So wie ich das sehe ist aber Dein Query schon völlig falsch aufgebaut.

  1. Du solltest Field<UserAccountType>("useraccount", schreiben - alles lower-case.
    Der Query ist schließlich auch lower-case. GraphQL ist per Standard case-sensitive!

  2. Dein Query beginnt nicht mit "query" sondern in Deinem Fall nur


{ 
  useraccount(id:1) {
    id
  }
}

Daher dürfte an für sich das Schema gar keinen Treffer finden und sollte einen Fehler werfen.
a) weil Case nicht passt und b) weil der Query-Aufbau nicht passt.

Siehe aber beim Author / Book Beispiel auf GitHub.
In der Readme sind auch Beispiele zur Abfrage.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Querys sind reine Abfragen - keine Manipulationen. Null. Beginne nicht hier schon mit einer Standardverletzung.

Achso okey, ich hatte das Beispiel in den Docs gesehen und habe es zum testen ebenfalls so gemacht (https://graphql-dotnet.github.io/docs/getting-started/introduction/ GraphType First Approach)

(also der ObjectGraphType, Du hast es einfach nur DataQuery genannt).

Ich habe es DataQuery genannt, da ich dachte das es vielleicht Sinn macht wenn ich in dem Schema mehr als nur auf den UserAccount gehen bzw suchen/mappen möchte. So wie es hier in den Docs beschrieben ist: https://graphql-dotnet.github.io/docs/getting-started/query-organization
Aber soweit war/bin ich noch nicht.

  1. Du solltest Field<UserAccountType>("useraccount", schreiben - alles lower-case

Ah das war schon der Fuchs. Ich habe an der falschen Stelle mit der Schreibweise hantiert. ich dachte es wäre hier nur die Bezeichnung und in der Type Klasse (UserAccountType) würde der Name eine Rolle spielen. Wenn ich in der Query alles lower case mache, dann funktioniert es, da habe ich das ganze auch mal mit dem Namen in der Type Klasse ausprobiert, ob das irgendeinen Einfluss hat, scheint allerdings nicht so. Egal wie ich es dort Schreibe es funktioniert mit der gleichen Query.

  1. Dein Query beginnt nicht mit "query" sondern in Deinem Fall nur
  
{   
  useraccount(id:1) {  
    id  
  }  
}  

Dazu hatte ich auf Stackoverflow was gefunden:
Zitat:


>

If a document contains only one query operation, and that query defines no variables and contains no directives, that operation may be represented in a short?hand form which omits the query keyword and query name.

You can omit the query keyword and the operation name. This leaves you with just a selection set, which is wrapped in a set of curly brackets.

Scheint als ob es auch nur mit "einmal" query in der Abfrage geht. Ich habe das ganze gerade probiert und trieft zu. Die Abfrage so wie ich Sie zu beginn hatte, funktioniert. Fehlerhaft war die QueryKlasse (ObjectGraphType).

Dein Git bin ich auch schon durch und habe es versucht mit anderen Beispielen zu vergleichen. Ich hatte da schon rein geschnuppert als du mir mit MediatR geholfen hast 😄

Ich Danke dir für die Hilfe Abt! Du hast es echt drauf!

16.806 Beiträge seit 2008
vor 4 Jahren

Achso okey, ich hatte das Beispiel in den Docs gesehen und habe es zum testen ebenfalls so gemacht (
>
GraphType First Approach)

Ah ok; aber hier wird nichts "erstellt". Hatte das so verstanden, dass Du hier ein" GetOrCreate() ausführen willst, was nicht gültig wäre.
Das Sample liefert ja immer einfach eine Entität zurück - egal was man anfragt.

If a document contains only one query operation, and that query defines no variables and contains no directives, that operation may be represented in a short?hand form which omits the query keyword and query name.

Das is nen Multiquery; dachte wolltest nen simplen.