Я получаю сообщение об ошибке при попытке создать новую итерацию с помощью клиентского 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
. Я знаю, что это далеко не так, но иначе я в полной растерянности.
Суть в том, что теперь это работает.
Я могу создать новую итерацию, используя Microsoft.TeamFoundation.WorkItemTracking.WebApi в Azure DevOps Services .NET SDK.
Пожалуйста, ознакомьтесь с приведенным ниже примером:
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
; Вы можете отладить свой код, чтобы проверить, почему не было задано имя узла.
@InteXX У вас была возможность проверить приведенный выше пример. Как прошло?
Спасибо, что заглянули — это в списке на завтра (вторник).
Ваш код работает. Мой нет. Что странно, поскольку мы видим, что я устанавливаю свойство Name
в конструкторе класса Iteration
. Единственная принципиальная разница между вашим кодом и моим заключается в том, что ваш создает экземпляр нового WorkItemClassificationNode
объекта в SaveNode()
методе. Мой базовый класс наследует WorkItemClassificationNode
напрямую. Эта конструкция исправно служит мне уже по крайней мере четыре года — эта новая неудача очень внезапна и неожиданна. Очевидно, что-то изменилось, я просто не знаю что, за исключением того, что это был не мой код.
Мне пришлось бы выдергивать кишки из всего приложения, если бы я принял вашу концепцию, а там тонна кода. Я в тупике. Есть ли способ проверить JSON, отправленный в API?
Я собираюсь попробовать немного реорганизовать класс. Я думаю, что могу сделать это, не нарушая остальную часть кода. Сегодня меня нет, но я поработаю над этим завтра и отправлю вам обновление.
Я все еще в этом, и я делаю хорошие успехи, но я внезапно зациклился на том, что должно быть второстепенным моментом. Я не могу добавить существующую область в существующую команду (stackoverflow.com/q/65472137). Вы можете помочь?
@InteXX. Как вы решили вышеуказанную проблему создания итерации? Не могли бы вы поделиться своим решением? Что касается добавления существующей области в команду. Вы можете проверить метод UpdateTeamFieldValuesAsync
.
К вашему сведению, я обновил свой вопрос, включив в него свое окончательное решение. Спасибо вам за вашу помощь.
Спасибо. Сегодня меня нет на рабочем месте, так что я попробую завтра и дам вам знать.