Мутация GraphQL.NET со списком ‹Dictionary‹ строка, строка ›› | Строка JSON

Я хочу зарегистрировать alarms в своем серверном приложении. Чтобы предотвратить передачу более 10 аргументов, я сериализую свой alarm на стороне клиента и передаю его как List<JSONString> своему серверу. Десериализуйте его, зарегистрируйте и дайте ответ зарегистрированного alarm.

Теперь моя проблема в том, что я не знаю, как передать эти параметры:

Использование мутации - DictionaryType

Словарь

"Переменная \" $ params \ "типа \" [String]! \ ", Используемая в типе ожидания позиции \" [DictionaryType]! \ "."

Использование мутации - StringGraphType

«Невозможно преобразовать значение в AST: System.Collections.Generic.Dictionary`2 [System.String, System.Object]», **

Сервер

Мутация - DictionaryType

public class Mutation : ObjectGraphType
{
    public Mutation()
    {
        Name = "Mutation";

        FieldAsync<HtStaticAlarmBaseType>(
            "registerStaticAlarms",
            "Register a list with static alarms.",
            arguments: new QueryArguments(
                new QueryArgument<NonNullGraphType<ListGraphType<DictionaryType>>> {Name = "params"}
            ),
            resolve: async context =>
            {
                List<object> parameterString = context.GetArgument<List<object>>("params");

                //TODO

                return null;
            }
        );
    }
}

Мутация - DictionaryType

public class Mutation : ObjectGraphType
{
    public Mutation()
    {
        Name = "Mutation";

        FieldAsync<HtStaticAlarmBaseType>(
            "registerStaticAlarms",
            "Register a list with static alarms.",
            arguments: new QueryArguments(
                new QueryArgument<NonNullGraphType<ListGraphType<StringGraphType>>> {Name = "params"}
            ),
            resolve: async context =>
            {
                List<object> parameterString = context.GetArgument<List<object>>("params");

                //TODO

                return null;
            }
        );
    }
}

DictionaryType

public class DictionaryType : ObjectGraphType<Dictionary<string,string>>
{
    public DictionaryType()
    {
        Name = "DictionaryType";
        Description = "Dictionary of type string, string.";
    }
}

HtStaticAlarmBaseType

public class HtStaticAlarmBaseType : ObjectGraphType<HtStaticAlarmBase>
{
    public HtStaticAlarmBaseType()
    {
        Name = "HtStaticAlarmBase";
        Description = "Base class of a static alarm.";


        // ##################################################
        // HtAlarmBase
        // ##################################################

        #region HtAlarmBase

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

        Field<StringGraphType>(
            "AlarmGroup",
            resolve: context => context.Source.AlarmGroup);

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

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

        Field<StringGraphType>(
            "Message",
            resolve: context => context.Source.Message);

        Field<StringGraphType>(
            "Station",
            resolve: context => context.Source.Station);

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

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

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

        Field<StringGraphType>(
            "Origin",
            resolve: context => context.Source.Origin);

        #endregion

        Field<IntGraphType>(
            "Number",
            resolve: context => context.Source.Number);

        Field<BooleanGraphType>(
            "Active",
            resolve: context => context.Source.Active);
    }
}

person Dominic Jonas    schedule 12.02.2018    source источник


Ответы (1)


На самом деле это мое текущее рабочее решение:

Запрос для клиента

mutation RegisterStaticAlarms($params: [HtStaticAlarmInputType])
{
    registerStaticAlarms(params: $params)
    {
        id,
        number,
        message,
        errorCode
    }
}

Мутация

public class Mutation : ObjectGraphType
{
    public Mutation()
    {
        Name = "Mutation";

        Field<ListGraphType<HtStaticAlarmType>>(
            "registerStaticAlarms",
            arguments: new QueryArguments(
                new QueryArgument<ListGraphType<HtStaticAlarmInputType>>
                {
                    Name = "params"
                }
            ),
            resolve: context =>
            {
                List<HtStaticAlarmInputTypeParams> paramses = context.GetArgument<List<HtStaticAlarmInputTypeParams>>("params");

                List<HtStaticAlarmBase> list = new List<HtStaticAlarmBase>();
                foreach (HtStaticAlarmInputTypeParams p in paramses)
                {
                    list.Add(HtAlarmManager.Create(p.Origin, (EHtAlarmClassType)Enum.Parse(typeof(EHtAlarmClassType), p.AlarmClass.ToString()), p.AlarmGroup, p.Station, (HtErrorCode)Enum.Parse(typeof(HtErrorCode), p.ErrorCode.ToString()), p.Message, p.Number));
                }

                return list;
            }
        );            
    }
}

Тип и модель

/// <summary>
/// GraphQl type of the <see cref="HtStaticAlarmBase"/>
/// </summary>
internal class HtStaticAlarmType : ObjectGraphType<HtStaticAlarmBase>
{
    public HtStaticAlarmType()
    {
        Name = "HtStaticAlarmType";
        Description = "Base class of a static alarm.";


        // ##################################################
        // HtAlarmBase
        // ##################################################

        #region HtAlarmBase

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

        Field<StringGraphType>(
            "AlarmGroup",
            resolve: context => context.Source.AlarmGroup);

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

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

        Field<StringGraphType>(
            "Message",
            resolve: context => context.Source.Message);

        Field<StringGraphType>(
            "Station",
            resolve: context => context.Source.Station);

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

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

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

        Field<StringGraphType>(
            "Origin",
            resolve: context => context.Source.Origin);

        #endregion

        Field<IntGraphType>(
            "Number",
            resolve: context => context.Source.Number);

        Field<BooleanGraphType>(
            "Active",
            resolve: context => context.Source.Active);
    }
}

/// <summary>
/// GraphQL input type of the <see cref="HtStaticAlarmBase"/>
/// </summary>
internal class HtStaticAlarmInputType : InputObjectGraphType
{
    public HtStaticAlarmInputType()
    {
        Name = "HtStaticAlarmInputType";
        Description = "Base class of a static alarm.";

        // ##################################################
        // HtAlarmBase
        // ##################################################

        #region HtAlarmBase

        Field<IntGraphType>("AlarmClass");
        Field<StringGraphType>("AlarmGroup");
        Field<IntGraphType>("ErrorCode");
        Field<StringGraphType>("Id");
        Field<StringGraphType>("Message");
        Field<StringGraphType>("Station");
        Field<DateGraphType>("TimeStampCome");
        Field<DateGraphType>("TimeStampGone");
        Field<DateGraphType>("TimeStampAcknowledge");
        Field<StringGraphType>("Origin");
        Field<StringGraphType>("IsSynced");
        Field<StringGraphType>("Pending");

        #endregion

        Field<IntGraphType>("Number");
        Field<BooleanGraphType>("Active");            
    }
}

/// <summary>
/// A lightweight class to deserialize the incoming <see cref="HtStaticAlarmInputType"/>
/// </summary>
internal class HtStaticAlarmInputTypeParams
{
    public int AlarmClass { get; set; }
    public string AlarmGroup { get; set; }
    public int ErrorCode { get; set; }
    public string Message { get; set; }
    public string Station { get; set; }
    public DateTime TimeStampCome { get; set; }
    public DateTime TimeStampGone { get; set; }
    public DateTime TimeStampAcknowledge { get; set; }
    public string Origin { get; set; }

    public int Number { get; set; }
    public bool Active { get; set; }
}

Предварительный просмотр

Предварительный просмотр

  • Также можно было бы включить properties в HtStaticAlarmInputType. Но я не хочу иметь эти накладные расходы и создал легкий класс HtStaticAlarmInputTypeParams.

  • Важно использовать CamelCasePropertyNamesContractResolver, если вы хотите использовать JSON (https://stackoverflow.com/a/36884359/6229375 ).

  • Это решение основано на https://gist.github.com/DanielRobinsonSoftware/963a2a3

person Dominic Jonas    schedule 12.02.2018