Ошибка "Значение не может быть нулевым: имя узла" при создании новой итерации

Я получаю сообщение об ошибке при попытке создать новую итерацию с помощью Client SDK:

Значение не может быть нулевым. Имя параметра: nodeName

В качестве теста я попытался создать его с помощью Postman и REST API - как было предложено здесь - и это удалось.

Я уже довольно давно пользуюсь этим, чтобы избавиться от иерархии спринтов на год. Это первое подобное появление этой ошибки - прошлогодние прогоны прошли без сбоев. Я ничего не изменил (насколько мне известно) с прошлогоднего успешного забега.

Как мы видим, свойство итерации Name устанавливается правильно. Я пробовал Overloads вместо Shadows, но это не помогло.

Как я могу устранить эту неполадку, чтобы узнать, что такое nodeName и как его заполнить с помощью Client SDK?

Вот мой код:

Module Main()
  Private Sub AddYear(Year As Integer, Client As WorkItemTrackingHttpClient)
    Dim oIterationYear As Classifications.Iteration
    Dim dFinishDate As Date
    Dim dStartDate As Date

    Console.WriteLine($"Year:{vbTab}{vbTab}{Year}")

    dFinishDate = New Date(Year, 12, 31)
    dStartDate = New Date(Year, 1, 1)

    oIterationYear = New Classifications.Iteration(Client, TeamProject, Year, dStartDate, dFinishDate)
    oIterationYear.Save()

    ...

  End Sub
End Module

Public Class Iteration
  Inherits Base

  Public Sub New(Client As WorkItemTrackingHttpClient, TeamProject As TeamProjects, Name As String, StartDate As Date, FinishDate As Date)
    Me.New(Client, TeamProject, Name, StartDate, FinishDate, Nothing)
  End Sub

  Public Sub New(Client As WorkItemTrackingHttpClient, TeamProject As TeamProjects, Name As String, StartDate As Date, FinishDate As Date, Parent As Iteration)
    MyBase.New(Client, TeamProject, Parent)

    Me.StructureType = TreeNodeStructureType.Iteration
    Me.FinishDate = FinishDate
    Me.StartDate = StartDate
    Me.Name = Name
  End Sub

  ...

End Class

Public MustInherit Class Base
  Inherits WorkItemClassificationNode

  Public Sub New(Client As WorkItemTrackingHttpClient, TeamProject As TeamProjects, Parent As Base)
    Me.ProjectName = TeamProject.ToDescription
    Me.Parent = Parent
    Me.Client = Client
  End Sub

  Public Sub Save()
    If Me.Parent.IsNothing Then
      Me.Node = Me.Client.CreateOrUpdateClassificationNodeAsync(Me, Me.ProjectName, Me.StructureType).Result <-- Error
    Else
      Me.Node = Me.Client.CreateOrUpdateClassificationNodeAsync(Me, Me.ProjectName, Me.StructureType, path:=Me.Path).Result
    End If
  End Sub

  ...

  Public Shadows Property Name As String
    Get
      If Me.Node.IsNothing Then
        Name = Me._Name
      Else
        Name = Me.Node.Name
      End If
    End Get
    Set(Value As String)
      Me._Name = Value
    End Set
  End Property
  Private _Name As String
End Class

Примечание: это вопрос, не зависящий от языка, поэтому я намеренно опустил тег VB.NET. Ответ может прийти либо на VB.NET, либо на C # - меня устраивает любой из них.

- ИЗМЕНИТЬ -

Основываясь на предложениях по дизайну, содержащихся в принятом ответе, я придумал это решение, которое работает:

Public MustInherit Class Base
  Public Sub New(Client As WorkItemTrackingHttpClient, TeamProject As TeamProjects, Parent As Base)
    Me.Node = New WorkItemClassificationNode With {
      .StructureType = StructureType,
      .Name = Name
    }

    Me.ProjectName = TeamProject.ToDescription
    Me.Parent = Parent
    Me.Client = Client
    Me.Name = Name
  End Sub

  Public Sub Save()
    If Me.Parent.IsNothing Then
      Me.Node = Me.Client.CreateOrUpdateClassificationNodeAsync(Me.Node, Me.ProjectName, Me.StructureType).Result
    Else
      Me.Node = Me.Client.CreateOrUpdateClassificationNodeAsync(Me.Node, Me.ProjectName, Me.StructureType, path:=Me.Path).Result
    End If
  End Sub

  ...

  Public Property Name As String
    Get
      Return Me.Node.Name
    End Get
    Private Set(Value As String)
      Me.Node.Name = Value
    End Set
  End Property
End Class

По сути, все, что я сделал, - это удалил наследование базового класса от WorkItemClassificationNode и во всех случаях сохранил внутреннюю ссылку на узел. Я также упростил реализацию свойства Name.

Что касается того, почему он внезапно перестал работать без каких-либо изменений в моем коде, единственное, что я могу придумать, - это удаленная возможность того, что произошло изменение в компиляторе, которое повлияло на то, как SDK оценивает ключевые слова Shadows и Overloads. Я знаю, что это долгий путь, но в остальном я полностью растерялся.

Итог, теперь он работает.


person InteXX    schedule 16.12.2020    source источник


Ответы (1)


Я могу создать новую итерацию, используя Microsoft.TeamFoundation.WorkItemTracking.WebApi в пакете SDK .NET для Azure DevOps Services.

Пожалуйста, ознакомьтесь с приведенным ниже примером:

 class Program
    {
        static void Main(string[] args)
        {
           
            Uri accountUri = new Uri("https://dev.azure.com/org/");
            string personalAccessToken = "pat";
           
            VssConnection _connection = new VssConnection(accountUri, new VssBasicCredential(string.Empty, personalAccessToken));
            WorkItemTrackingHttpClient workItemTrackingHttpClient = _connection.GetClient<WorkItemTrackingHttpClient>();

            Iteration iteration = new Iteration(workItemTrackingHttpClient,2021, "projectName");
            iteration.SaveNode();
        }
          
    }

public class Iteration
    {
        WorkItemTrackingHttpClient client;
        WorkItemClassificationNode node;
        string project;
        string path;
        public Iteration(WorkItemTrackingHttpClient client, int Year, string project, string path=null) {
            this.client = client;
            node = new WorkItemClassificationNode();
            this.project = project;
            this.path = path;
            IDictionary<string, object> DateAttr = new Dictionary<string, object>();
            DateAttr.Add("startDate", new DateTime(Year, 1, 1));
            DateAttr.Add("finishDate", new DateTime(Year, 12, 31));
            node.Attributes = DateAttr;
            node.Name = Year.ToString();
            node.StructureType = TreeNodeStructureType.Iteration;

        }

        public void SaveNode()
        {
            var res = client.CreateOrUpdateClassificationNodeAsync(node, project, TreeStructureGroup.Iterations, path).Result;
            Console.WriteLine(res.Id);
        }
    }

См. Результат ниже:

введите описание изображения здесь

Я могу воспроизвести вышеуказанную ошибку Value cannot be null. Parameter name: nodeName. Если я намеренно не установил node.Name = null; Вы можете отладить свой код, чтобы проверить, почему не было задано имя узла.

person Levi Lu-MSFT    schedule 17.12.2020
comment
Спасибо. Сегодня меня нет на рабочем месте, поэтому я попробую завтра и дам вам знать. - person InteXX; 17.12.2020
comment
@InteXX У вас была возможность проверить пример выше. Как прошло? - person Levi Lu-MSFT; 22.12.2020
comment
Спасибо, что зарегистрировались - это в списке на завтра (вторник). - person InteXX; 22.12.2020
comment
Ваш код работает. У меня нет. Это странно, поскольку мы видим, что я устанавливаю свойство Name в конструкторе класса Iteration. Единственное различие между вашим кодом и моим по идее состоит в том, что ваш код создает экземпляр нового объекта WorkItemClassificationNode в методе SaveNode(). Мой базовый класс напрямую наследует WorkItemClassificationNode. Эта конструкция хорошо служила мне по крайней мере четыре года - эта новая неудача была очень внезапной и неожиданной. Очевидно, что-то изменилось, я просто не знаю что, кроме того, что это был не мой код. - person InteXX; 23.12.2020
comment
Мне пришлось бы выдернуть кишку из всего приложения, если бы я принял вашу концепцию - а там тонна кода. Я в тупике. Есть ли способ проверить JSON, отправленный в API? - person InteXX; 23.12.2020
comment
Я попробую немного реорганизовать класс. Я думаю, что смогу сделать это, не нарушая остальной код. Сегодня меня нет, но завтра я поработаю над этим и пришлю вам обновленную информацию. - person InteXX; 23.12.2020
comment
Я все еще занимаюсь этим, и у меня хорошие успехи, но я внезапно зациклился на том, что должно быть второстепенным. Я не могу добавить существующую область к существующей команде (stackoverflow.com/q/65472137). Вы можете помочь? - person InteXX; 28.12.2020
comment
@InteXX. Как вы исправили описанную выше проблему создания итерации? Не могли бы вы поделиться своим решением? Что касается добавления существующей области в команду. Вы можете проверить метод UpdateTeamFieldValuesAsync. - person Levi Lu-MSFT; 28.12.2020
comment
К вашему сведению, я обновил свой вопрос, включив в него свое окончательное решение. Спасибо за помощь. - person InteXX; 29.12.2020