Muitas vezes quando trabalhamos com Work Items no TFS realizamos tarefas repetitivas como criar as tarefas para uma determinada atividade. Veja o cenário abaixo:
Perceba que nesse cenário para cada User Story temos a repetição de várias Tasks, para automatizar a criação dessas Tasks vamos codificar um componente que vai ser executado depois do evento save de um Work Item do tipo User Story e vamos criar automaticamente os Work Items do tipo Task
Criando o Projeto
Crie um projeto do tipo Class Library e adicione as seguintes referências
c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\
Microsoft.TeamFoundation.dll
Microsoft.TeamFoundation.Client.dll
Microsoft.TeamFoundation.Common.dll
Microsoft.TeamFoundation.WorkItemTracking.Client.dll
C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\bin\
Microsoft.TeamFoundation.Framework.Server.dll
Microsoft.TeamFoundation.WorkItemTracking.Server.Dataaccesslayer.dll
Agora adicione uma nova classe chamada WorkItemChangedEventHandler.cs
[sourcecode language=”csharp”]
public class WorkItemChangedEventHandler : ISubscriber
{
public string Name
{
get { return "WorkItemChangedEventHandler"; }
}
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;
return EventNotificationStatus.ActionPermitted;
}
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(WorkItemChangedEvent) };
}
}
[/sourcecode]
Veja que nossa classe está implementando uma interface ISubscriber que possui um método ProcessEvent que será invocado quando um Work Item for criado
Veja abaixo a implementação do método ProcessEvent
[sourcecode language=”csharp”]
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
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent;
// código do work item
int workItemId = ev.CoreFields.IntegerFields[0].NewValue;
if (ev.ChangeType == ChangeTypes.New)
{
if((ev.CoreFields.StringFields[0].Name.Equals("Work Item Type")) && (ev.CoreFields.StringFields[0].NewValue.Equals("User Story")))
{
// responsável pelo WI
string assignTo = string.Empty;
if (!String.IsNullOrEmpty(ev.CoreFields.StringFields[5].NewValue))
assignTo = ev.CoreFields.StringFields[5].NewValue;
// Recupera o projeto especifico
WorkItemStore workItemStore = GetWorkItemStore(requestContext);
Project teamProject = workItemStore.Projects[ev.PortfolioProject];
// cria o tipo de work item
WorkItemType tipoWI = teamProject.WorkItemTypes["Task"];
// cria a relação do work item
WorkItemLinkTypeEnd linkTypeEnd = workItemStore.WorkItemLinkTypes.LinkTypeEnds["Parent"];
// criar os work item do tipo Task
Create(tipoWI, workItemId, linkTypeEnd, "Levantamento de Requisitos", assignTo, "Realizar Levantamento de Requisitos");
Create(tipoWI, workItemId, linkTypeEnd, "Desenvolvimento", assignTo, "Realizar a codificação");
Create(tipoWI, workItemId, linkTypeEnd, "Testes", assignTo, "Executar os testes");
Create(tipoWI, workItemId, linkTypeEnd, "Publicação", assignTo, "Fazer a publicação nos ambientes");
EventLog.WriteEntry("WorkItemChangedEventHandler", "WorkItem created [" + ev.WorkItemTitle + "]");
}
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("WorkItemChangedEventHandler", "Erro: " + ex.Message);
}
return EventNotificationStatus.ActionPermitted;
}
[/sourcecode]
Deploy do Projeto
Para que o TFS possa chamar esse componente temos que colocar a DLL no seguinte diretório C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\bin\Plugins
TestandoVisual Studio
Agora vamos criar um novo Work Item do tipo Use Story e perceba que as Tasks ja foram criadas automáticamente
Testando Portal do Projeto
Essa solução também funciona quando criamos uma User Story pelo portal do projeto
Download do Projeto
Segue abaixo o código completo para download
Deixe seu comentário, opinião, critica
Aquele abraço!
Olá Leando, tudo bom?! Você comentou que o método ProcessEvent será invocado quando um Work Item for criado. O método é invocado também quando o Status de um Work Item é alterado?
Parece que eu li em algum lugar que esse plugin é acionado de tempo em tempo.
Até mais e obrigado.
Gustavo,
Na verdade eu me expressei mal, o que me referia é que o método ProcessEvent será invocado quando o WI sofrer alguma alteração (New, Update)
Por esse motivo eu verifico se o ChangeType = New para criar os WI do tipo task
att,
Leandro Prado
Entendi.
Brigadão pelo esclarecimento. Isso vai me ajudar, pois eu vou criar uma integração com o CRM. Quando algum usuário criar um “problema” no CRM eu vou criar um Work Item no TFS.
Vou precisar desse plugin para quando algum Work Item sofrer alguma modificação, como por exemplo, uma alteração de status eu atualizar no CRM.
Até mais Leandro.
Leandro, boa noite.
Sempre que eu coloco a dll no meu servidor, ele para de responder completamente.
Consegue dar alguma dica? O erro está abaixo, ele aparece no eventviewer do server
TF53010: The following error has occurred in a Team Foundation component or extension:
Date (UTC): 16/08/2012 22:18:55
Machine: TFS
Application Domain: /LM/W3SVC/8080/ROOT/tfs-1-129896291340132576
Assembly: Microsoft.TeamFoundation.Framework.Server, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a; v2.0.50727
Service Host:
Process Details:
Process Name: w3wp
Process Id: 3592
Thread Id: 1692
Account name: TFS\Administrator
Detailed Message: The request could not be processed because the application is not configured correctly. No service host is available for the request.
Web Request Details
Url: http://tfs:8080/tfs/TeamFoundation/Administration/v3.0/CatalogService.asmx [method: POST]
User Agent: Team Foundation (devenv.exe, 10.0.30319.1)
Headers: Connection=Keep-Alive&Content-Length=375&Content-Type=application%2fsoap%2bxml%3b+charset%3dutf-8&Accept-Encoding=gzip&Accept-Language=pt-BR&Expect=100-continue&Host=tfs%3a8080&User-Agent=Team+Foundation+(devenv.exe%2c+10.0.30319.1)&X-TFS-Version=1.0.0.0&X-TFS-Session=2b8b9f36-1a62-4c74-a5bd-9865c9747392&TF-Instance=2b8b9f36-1a62-4c74-a5bd-9865c9747392&SOAPAction=http%3a%2f%2fmicrosoft.com%2fwebservices%2fQueryNodes
Path: /tfs/TeamFoundation/Administration/v3.0/CatalogService.asmx
Local Request: False
Host Address: fe80::f8f1:a4b1:ee7a:1eb6%10
User: TFS\Administrator [authentication type: ]
Junior,
Seu componente foi criado em qual versão do .NET Framework? Caso seja a versão 4.0 tente mudar para a versão 3.5
att,
Leandro Prado
Oi Leandro, valeu pela resposta.
Estou compilando com a versão 3.5 mesmo, o projeto é exatamente o mesmo que você disponibliza para download.
Tentei debugar fazendo o attach do processo mais não chega nem a debugar. A dll cai na pasta \plugins e o TFS para de responder na hora.
Até mais.
Leandro, Descobri.
Era o arquivo class1.cs adicionado o projeto que estava bugando tudo. Foi só retirar ele e vualá 🙂
obrigado
hehehehe!!!!
flw!!!
Hi Leandro,
Thanks for the code example.
I’m Testing your code, but the event is not fired !
I copied the dll in in
~:\Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins\ folder
at the tfs-server
I googled a lot but cannot find the answer. I’ll hope you have one for me.
I’ve created an event source in the application log
“eventcreate /l Application /t Information /so WorkItemChangedEventHandler /id 1 /d “Test message”
When I add the following line to your code :
after the first if of the method “ProcessEvent”
EventLog.WriteEntry(“WorkItemChangedEventHandler”, “WorkItem changed”);
there is no event written. So in my opnion the event is not fired.
Can you help me?
Thanks in advance
Hi Wijnand
In your method EventNotificationStatus add a message to event viewer to verify if the method is called, excute the deploy again!
Regards,
Leandro Prado
Leandro,
Boa tarde.
Excelente post, eu tenho uma duvida, na aba de Status na parte de state eu gostaria de saber se a possibilidade de inserir mais itens? se tiver como devo proceder.
Obrigado
Rodrigo,
Nesse caso você terá que customizar o process template, você deverá abrir o arquivo do Work Item que você quer adicionar o novo Status e fazer suas transições.
att,
Leandro Prado
Leandro, boa tarde.
Fiz tudo certo, mas aparentemente o evento não está disparando de jeito nenhum!
Está com .NET 3.5, criei um Source WorkItemChangedEventHandler para registrar no log eventos e nada..
Tem alguma ideia?
Desde já agradeço.
Acabei descobrindo a solução.
Meu TFS é 2012, então o meu projeto tinha que estar no .NET 4.0.
Além disso, as DLLs referênciadas do TFS tem de estar na versão v11. Caso esteja alguma delas com v10, o evento não dispara e nem gera exception, te deixando sem rumo.
exatamente Eduardo…
como esse post é antigo, foi criado usando o TFS 2010, mas no 2012 é exatamente o que vc fez, .net 4 e versão 11 das DLLs
att,
Leandro Prado
Sou inciante nesse assunto,mas tenho a necessidade de automatizar uma edição de work item,como devo proceder?