我想知道在创建工作项时是否可以创建新的链接任务。
任何人都可以提示如何做到这一点吗?
答案 0 :(得分:4)
我已经阅读了之前用于此场景的一些旧代码。每当新错误设置为已批准时,以下代码都会创建链接任务。
代码过滤到特定的团队项目并使用特定帐户进行连接。您需要在插件运行之前输入这些内容。然后,您可以修改此代码以创建所需的任务。
有关服务器插件的一般介绍以及如何将以下代码转换为正常运行的插件,请参阅Extending Team Foundation
using Microsoft.TeamFoundation.Framework.Server;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.WorkItemTracking.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Client;
using System.Net;
using System.Collections;
namespace TfsExtension.CreateTaskForBug
{
public class CreateTaskForBugEventHandler : ISubscriber
{
const string projectName = "<Enter your project name here>";
public string Name
{
get
{
return "CreateTaskForBugEventHandler";
}
}
public SubscriberPriority Priority
{
get
{
return SubscriberPriority.Normal;
}
}
public EventNotificationStatus ProcessEvent(
TeamFoundationRequestContext requestContext,
NotificationType notificationType,
object notificationEventArgs,
out int statusCode,
out string statusMessage,
out ExceptionPropertyCollection properties)
{
statusCode = 0;
properties = null;
statusMessage = String.Empty;
try
{
ProcessNotification(notificationType, notificationEventArgs, requestContext);
}
catch (Exception exception)
{
TeamFoundationApplicationCore.LogException("Error processing event", exception);
}
return EventNotificationStatus.ActionPermitted;
}
private static void ProcessNotification(NotificationType notificationType, object notificationEventArgs, TeamFoundationRequestContext requestContext)
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
var ev = notificationEventArgs as WorkItemChangedEvent;
if (ev.PortfolioProject == projectName)
{
string workItemType = (from field in ev.CoreFields.StringFields
where field.Name == "Work Item Type"
select field.NewValue).Single();
if (workItemType == "Bug")
{
ProcessBug(ev, requestContext);
}
}
}
}
private static void ProcessBug(WorkItemChangedEvent ev, TeamFoundationRequestContext requestContext)
{
var stateChange = (from field in ev.ChangedFields.StringFields
where field.Name == "State" && field.NewValue == "Approved"
select field).SingleOrDefault();
if (stateChange != null)
{
AddChildTaskToBug(ev, requestContext);
}
}
private static void AddChildTaskToBug(WorkItemChangedEvent ev, TeamFoundationRequestContext requestContext)
{
WorkItemStore wiStore = GetWorkItemStore(requestContext);
WorkItem witem = wiStore.GetWorkItem(ev.CoreFields.IntegerFields[0].NewValue);
Project teamProject = witem.Project;
int bugID = witem.Id;
string bugTitle = witem.Fields["System.Title"].Value.ToString();
string bugAssignedTo = witem.Fields["System.AssignedTo"].Value.ToString();
string bugAreaPath = witem.Fields["System.AreaPath"].Value.ToString();
string bugIterationPath = witem.Fields["System.IterationPath"].Value.ToString();
string bugChangedBy = witem.Fields["System.ChangedBy"].OriginalValue.ToString();
string bugTeamProject = witem.Project.Name;
string childTaskTitle = "Resolve bug " + bugID + " - " + bugTitle;
if (CreateResolutionTask(wiStore, bugID, childTaskTitle))
{
witem = CreateWorkItem(wiStore, teamProject, bugID, bugTitle, bugAssignedTo, bugAreaPath, bugIterationPath);
if (IsValid(witem))
{
witem.Save();
LinkParentAndChild(wiStore, witem, bugID);
}
}
}
private static bool IsValid(WorkItem witem)
{
ArrayList validationErrors = witem.Validate();
return validationErrors.Count == 0;
}
private static void LinkParentAndChild(WorkItemStore wiStore, WorkItem witem, int bugID)
{
var linkType = wiStore.WorkItemLinkTypes[CoreLinkTypeReferenceNames.Hierarchy];
var parentWorkItem = wiStore.GetWorkItem(bugID);
int taskID = witem.Id;
var childWorkItem = wiStore.GetWorkItem(taskID);
parentWorkItem.Links.Add(new WorkItemLink(linkType.ForwardEnd, childWorkItem.Id));
parentWorkItem.Save();
}
private static WorkItem CreateWorkItem(WorkItemStore wiStore, Project teamProject, int bugID, string bugTitle, string bugAssignedTo, string bugAreaPath, string bugIterationPath)
{
WorkItemTypeCollection workItemTypes = wiStore.Projects[teamProject.Name].WorkItemTypes;
WorkItemType wiType = workItemTypes["Task"];
WorkItem witem = new WorkItem(wiType);
witem.Fields["System.Title"].Value = "Resolve bug " + bugID + " - " + bugTitle;
witem.Fields["System.AssignedTo"].Value = bugAssignedTo;
witem.Fields["System.AreaPath"].Value = bugAreaPath;
witem.Fields["System.IterationPath"].Value = bugIterationPath;
witem.Fields["Microsoft.VSTS.Common.Activity"].Value = "Bug Resolution";
return witem;
}
private static bool CreateResolutionTask(WorkItemStore wiStore, int bugID, string childTaskTitle)
{
WorkItem parentBug = wiStore.GetWorkItem(bugID);
WorkItemLinkCollection links = parentBug.WorkItemLinks;
foreach (WorkItemLink wil in links)
{
if (wil.LinkTypeEnd.Name == "Child")
{
WorkItem childTask = wiStore.GetWorkItem(wil.TargetId);
if ((childTask.Title == childTaskTitle) && (childTask.State != "Closed"))
{
return false;
}
}
}
return true;
}
private static Uri GetTFSUri(TeamFoundationRequestContext requestContext)
{
var locationService = requestContext.GetService<TeamFoundationLocationService>();
return new Uri(locationService.GetServerAccessMapping(requestContext).AccessPoint + "/" + requestContext.ServiceHost.Name);
}
private static WorkItemStore GetWorkItemStore(TeamFoundationRequestContext requestContext)
{
NetworkCredential netCred = new NetworkCredential(
"<username>",
"<password>");
WindowsCredential windowsCred = new WindowsCredential(netCred);
var credentials = new TfsClientCredentials(windowsCred);
credentials.AllowInteractive = true;
var tpc = new TfsTeamProjectCollection(
GetTFSUri(requestContext),
credentials);
tpc.Authenticate();
return tpc.GetService<WorkItemStore>();
}
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(WorkItemChangedEvent) };
}
}
}