How to read event data information from VSTS web hooks - c#

We are currently developing a service that integrates service now and VSTS. When an incident created in servicenow, based on the category selected the integration creates a work item in the VSTS. This part we were able to accomplish. Now we need to send updates from VSTS workitems, if any, to servicenow incident. We have created a service hook that captures the work item event details when an update happens to work item.
Now,the problem that I am having is, how can I create an event listener that listens to the web hook and reads that information. Is an example available on how to create the event listener from web hooks?

I implemented something similar with github webhooks. I´ve used an asp.net web api in azure because in .netcore it´s still prerelease. You can look for it githubwebhookrepo
There is also a nuget package for vsts. I think it should be pretty much the same.
nuget
You will get a context with a payload json in it and there should be your event type.
public class GitHubWebHookHandler : WebHookHandler
{
public GitHubWebHookHandler()
{
this.Receiver = GitHubWebHookReceiver.ReceiverName;
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
JObject entry = context.GetDataOrDefault<JObject>();
return Task.FromResult(true);
}
}
Payload info: https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=vsts

Related

Adding middleware or alike in Azure functions v2

I need to add correlationId to my logging context and I did it on my MVC project by adding CorrelationId nuget to the project and setting up its middleware, but I could not do the same in Azure functions.
I have loaded the ICorrelationContextAccessor using Dependency injection and then set my correlationId like this:
[FunctionName("func1")]
public async Task Run([ServiceBusTrigger("mytopic", "MySubscription", Connection = "ServiceBusConnectionString")]Message message)
{
_correlationContextAccessor.CorrelationContext = _correlationContextFactory.Create(message.CorrelationId, "X-Correlation-ID");
_logger.LogInformation($"C# ServiceBus topic trigger function processed message: {message.MessageId}, {Encoding.UTF8.GetString(message.Body)}");
It works fine and I see my correlationId in the log line below and in my services in the function. The only part that I am missing is that I have logs regarding the start and finish of the function that still has no correlationId, which kind of make sense becaue when the function wants to log that it has received the message the correlationId is not set.
The short version is that you can't effect the logging code that runs before your function using the built in bindings.
You won't be able to change that first "C# Timer trigger function processed message" as the message hasn't been read at that point-- it would be the same as trying to get the correlation ID set in your MVC project before reading the incoming HTTP request.
You could add logging as soon as the message is first received by creating a custom binding. I would encourage you to consider carefully whether or not it is worth building and maintaining a custom binding to get your logging setup a few lines sooner.

How can I listen for the end of a build using VSTS WebApi?

I'm building as part of a larger process that analyzes the results of the build once it has completed. I used to work with XAML builds via C# code, and I had the following code:
QueuedBuild.Connect();
QueuedBuild.PollingCompleted += PrivateServerBuildRequest.BuildCompleted;
(QueuedBuild was IQueuedBuild type),
With new WebApi builds, do I have an event that let me know that the build has completed?
I found BuildCompletedEvent in Microsoft.TeamFoundation.Build.WebApi.Events but I didn't manage to find the way to use it.
Is there any equivalent to PollingCompleted event in WebApi builds? Something that'll fire once all build results are available?
One of the possible alternatives with the new REST API is to use Service Hooks. In particular, you might want to pay attention to the generic Web Hook, whcih can basically instruct VSTS to POST some JSON payload (once a certain event occurs) to some endpoint.
The endpoint can be anything: your custom home-made service hosted on-prem, OR an Azure Function, for instance. This article can give you an idea how to trigger an Azure Function in response to a VSTS event.
The 'Build Completed' event is in the list of available events.
So, to sum it all up, I would try the following in your case:
Create an Azure Function to accept the build info payload and process it accordingly
Subscribe to Build Completed event with the Web Hook and make sure the Azure Function URL is used as the endpoint

Azure Notification Hubs Register Device Error 404

This is the first time I'm using Azure Notification Hubs and I'm having some trouble getting it working properly with my application.
The part I'm stuck on (at the moment) is registering my device with the notification hub. I'm using the backend method to do the registration ... that is, I'm creating an Installation object and using the CreateOrUpdateInstallationAsync method to register the device via my Web API. I'm only testing it at this stage so I'm hitting my API endpoint with dummy data via Postman.
When I step through my code, I'm getting the following error when I execute CreateOrUpdateInstallationAsync ...
The remote server returned an error: (404) Not Found. Entity does not
exist.TrackingId:203cba37-007d-4dcb-ae25-ced33fa012aa_G1,TimeStamp:2/4/2018
10:24:02 PM
I've tested that I am connecting to the Notification Hub correctly by calling GetAllRegistrationsAsync. This returns an empty list (expected) and no error ... so I have my endpoints set up correctly. I'm wondering if there is a problem with my dummy data? For the installation Id, I've just created a random GUID (Guid.NewGuid). The Device ID and Push Notification Handle are random numbers and letters. And I'm testing this for the Android platform (NotificationPlatform.Gcm).
Has anyone seen this error before and know what it means? Am I able to just use random data for testing purposes (I'm only interested in registering devices at this stage) or do I need legitimate data (real device id's, etc)?
Thanks in advance.
The CreateOrUpdateInstallationAsync method would essentially invoke the REST API Create or Overwrite an Installation. When you register with a notification hub from your custom backend using the Installation, the core code would look like as follows:
NotificationHubClient hubclient = NotificationHubClient.CreateClientFromConnectionString(listenConnString, hubName);
await hubclient.CreateOrUpdateInstallationAsync(installation);
Note: You could install the Microsoft.Azure.NotificationHubs package for back end operations.
For a simpler way, I just created a console application and test this operation as follows:
Note: I just created a new Azure Notification Hub and did not set any notification settings. And I set a GUID as the InstallationId and a random string as the PushChannel, the rest operation could work as expected.
And I could retrieve the previous added registration as follows:
Has anyone seen this error before and know what it means? Am I able to just use random data for testing purposes (I'm only interested in registering devices at this stage) or do I need legitimate data (real device id's, etc)?
The operation could work on my side, I would recommend you debug your application and leverage fiddler to capture the network traces to narrow this issue. Moreover, you could follow Registration management for more details about registering devices with azure notification hubs.
Ok, it turns out that I had the wrong value for Hub Name when instantiating the NotificationHub object using NotificationHubClient.CreateClientFromConnectionString. I was using the namespace, instead of the hub name (visible on the Overview tab in the Azure Portal).

How to enable WebApi DelegatingHandler via web.config

In order to log the JSON of each WebApi request/response I have created a custom DelegatingHandler and added this to the MessageHandlers collection in WebApiConfig.cs and it works great.
In future though, I'd like to be able to enable this handler on other WebApi applications via web.config without having to actually modify WebApiConfig.cs.
By way of clarification, what I'm trying to achieve is analogous to what was possible in WCF where you could create a completely separate dll, drop it into the bin folder of a WCF service and add it into the WCF pipeline solely by editing the web.config file without having to modify the source of the service at all.
Is this possible in WebApi or can a custom DelegatingHandler only be added via code at runtime?
Modify the handler to check the config and perform its function if enabled otherwise just let the request pass through. if being used for logging make sure it is added early in the pipeline. Look into using middle-ware if possible.
public class LoggingHandler : DelegatingHandler {
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
var appSetting = ConfigurationManager.AppSettings["LoggingHandlerEnabled"];
var enabled = true;
bool.TryParse(appSetting, out enabled);
if(enabled) {
//...Extract and log request
LogRequest(request);
}
// Execute the request and get the response
var response = await base.SendAsync(request, cancellationToken);
if(enabled) {
//...Extract details from response for logging
LogResponse(response);
}
return response;
}
private void LogRequest(HttpRequestMessage request) {
//... code removed for brevity
}
private void LogResponse(HttpResponseMessage response) {
//... code removed for brevity
}
}
With that in place then there would be no further need to modify any more code to enable/disable the handler. Update the config file and the handler will respect the setting.
After a bit of research I am answering my own question. It seems like this is not possible without having to modify the source of the target application. It might be possible to dynamically load or inject such a handler at startup if some thought was given during the writing of the application and knew to look for it. Another possible solution would be to create the logging handler as a nuget package and when the nuget package is installed into the target application the installer would add the dll and also create a WebActivator hook that added the handler to the MessagingHandlers collection in PostApplicationStartMethod. This might be the approach that involves that least amount of manual code change, but would still require recompilation and re-deployment of the target app.
Tracing in ASP.NET Web API 2
From the Tools menu, select Library Package Manager, then Package Manage Console.
In the Package Manager Console window, type the following commands.
Install-Package Microsoft.AspNet.WebApi.Tracing
Update-Package Microsoft.AspNet.WebApi.WebHost
The first command installs the latest Web API tracing package. It also updates the core Web API packages. The second command updates the WebApi.WebHost package to the latest version.
Open the file WebApiConfig.cs in the App_Start folder. Add the following code to the Register method.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableSystemDiagnosticsTracing();
// Other configuration code not shown.
}
}
This code adds the SystemDiagnosticsTraceWriter class to the Web API pipeline. The SystemDiagnosticsTraceWriter class writes traces to System.Diagnostics.Trace.
To see the traces, run the application in the debugger. In the browser, navigate to /api/values.
The trace statements are written to the Output window in Visual Studio. (From the View menu, select Output).

Azure Cloud Service - Monitoring a deployment

Is there an event raised the moment a website is published and updated?
I've tried Application_End in global.asax but that event does not seem to be raised.
I suggest to use both Kudu and Microsoft ASP.NET WebHooks preview.
Kudu is the engine behind git deployments, WebJobs, and various other features in Azure Web Sites (Kudu source is on GitHub)
With Kudu, Azure Web Sites have a support for web hooks. There is an event "PostDeployment" that will be invoked whenever a deployment is complete with the result of that deployment.
Microsoft ASP.NET WebHooks preview provides a common model for receiving and processing WebHooks from any number of WebHook providers includign support for Kudu (Azure Web App Deployment).
So you may use Kudu WebHooks to get notified when an update has been deployed. (But that will require using Git Deploy instead of other ways to publish your web site).
Here is the way to do it :
First Install the Microsoft.AspNet.WebHooks.Receivers.Azure Nuget package.
The, Add these two lines to the WebApiConfig.Register method:
config.InitializeReceiveKuduWebHooks();
config.InitializeReceiveAzureAlertWebHooks();
Then Add a handler :
public class KuduWebHookHandler : WebHookHandler
{
public KuduWebHookHandler()
{
Receiver = "kudu";
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
// Convert to POCO type
KuduNotification notification = context.GetDataOrDefault<KuduNotification>();
// Get the notification message
string message = notification.Message;
// Get the notification author
string author = notification.Author;
return Task.FromResult(true);
}
}
Then configure a secret that can validates that the WebHook requests indeed come from Kudu.
Use high-entropy values such as a SHA256 hash or similar, which you can get from http://www.freeformatter.com/hmac-generator.html. Also, set them through the Azure Portal instead of hard-coding them in the Web.config file
Also, set them through the Azure Portal instead of hard-coding them in the Web.config file.
There is a more complete Post on the subject here (http://blogs.msdn.com/b/webdev/archive/2015/10/04/receive-webhooks-from-azure-alerts-and-kudu-azure-web-app-deployment.aspx)
Hope this helps
Best regards
Stéphane
I figured it out. In the Application_Start event I bind
RoleEnvironment.Stopping += RoleEnvironmentStopping;
private void RoleEnvironmentStopping(object sender, RoleEnvironmentStoppingEventArgs e)
{
// do something ...
}

Categories