Skip to content

Commit

Permalink
Initial revision
Browse files Browse the repository at this point in the history
  • Loading branch information
dbarkol committed Aug 23, 2018
1 parent 469808a commit 7eb4318
Show file tree
Hide file tree
Showing 70 changed files with 23,781 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .vscode/launch.json
@@ -0,0 +1,46 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/viewer/bin/Debug/netcoreapp2.1/viewer.dll",
"args": [],
"cwd": "${workspaceFolder}/viewer",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
25 changes: 25 additions & 0 deletions AzureEventGridViewer.sln
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2000
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "viewer", "viewer\viewer.csproj", "{B76DCFAF-1283-4BE7-86E6-28FF41C300F0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B76DCFAF-1283-4BE7-86E6-28FF41C300F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B76DCFAF-1283-4BE7-86E6-28FF41C300F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B76DCFAF-1283-4BE7-86E6-28FF41C300F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B76DCFAF-1283-4BE7-86E6-28FF41C300F0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9E98DBE-C8B1-4612-A197-DD257FEF3709}
EndGlobalSection
EndGlobal
Binary file added viewer/.vscode/._tasks.json
Binary file not shown.
46 changes: 46 additions & 0 deletions viewer/.vscode/launch.json
@@ -0,0 +1,46 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/netcoreapp2.1/viewer.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
15 changes: 15 additions & 0 deletions viewer/.vscode/tasks.json
@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/viewer.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
43 changes: 43 additions & 0 deletions viewer/Controllers/HomeController.cs
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using viewer.Models;

namespace viewer.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult About()
{
ViewData["Message"] = "Your application description page.";

return View();
}

public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";

return View();
}

public IActionResult Privacy()
{
return View();
}

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
164 changes: 164 additions & 0 deletions viewer/Controllers/UpdatesController.cs
@@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using System.Net;
using System.Text;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.Mvc;
using viewer.Hubs;
using viewer.Models;

namespace viewer.Controllers
{
[Route("api/[controller]")]
public class UpdatesController : Controller
{
#region Data Members

private bool EventTypeSubcriptionValidation
=> HttpContext.Request.Headers["aeg-event-type"].FirstOrDefault() ==
"SubscriptionValidation";

private bool EventTypeNotification
=> HttpContext.Request.Headers["aeg-event-type"].FirstOrDefault() ==
"Notification";

private readonly IHubContext<GridEventsHub> _hubContext;

#endregion

#region Constructors

public UpdatesController(IHubContext<GridEventsHub> gridEventsHubContext)
{
this._hubContext = gridEventsHubContext;
}

#endregion

#region Public Methods

[HttpPost]
public async Task<IActionResult> Post()
{
using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
{
var jsonContent = await reader.ReadToEndAsync();

// Check the event type.
// Return the validation code if it's
// a subscription validation request.
if (EventTypeSubcriptionValidation)
{
return await HandleValidation(jsonContent);
}
else if (EventTypeNotification)
{
// Check to see if this is passed in using
// the CloudEvents schema
if (IsCloudEvent(jsonContent))
{
return await HandleCloudEvent(jsonContent);
}

return await HandleGridEvents(jsonContent);
}

return BadRequest();
}
}

#endregion

#region Private Methods

private async Task<JsonResult> HandleValidation(string jsonContent)
{
var gridEvent =
JsonConvert.DeserializeObject<List<GridEvent<Dictionary<string, string>>>>(jsonContent)
.First();

await this._hubContext.Clients.All.SendAsync(
"gridupdate",
gridEvent.Id,
gridEvent.EventType,
gridEvent.Subject,
gridEvent.EventTime.ToLongTimeString(),
jsonContent.ToString());

// Retrieve the validation code and echo back.
var validationCode = gridEvent.Data["validationCode"];
return new JsonResult(new
{
validationResponse = validationCode
});
}

private async Task<IActionResult> HandleGridEvents(string jsonContent)
{
var events = JArray.Parse(jsonContent);
foreach (var e in events)
{
// Invoke a method on the clients for
// an event grid notiification.
var details = JsonConvert.DeserializeObject<GridEvent<dynamic>>(e.ToString());
await this._hubContext.Clients.All.SendAsync(
"gridupdate",
details.Id,
details.EventType,
details.Subject,
details.EventTime.ToLongTimeString(),
e.ToString());
}

return Ok();
}

private async Task<IActionResult> HandleCloudEvent(string jsonContent)
{
var details = JsonConvert.DeserializeObject<CloudEvent<dynamic>>(jsonContent);

// CloudEvents schema and mapping to
// Event Grid: https://docs.microsoft.com/en-us/azure/event-grid/cloudevents-schema
await this._hubContext.Clients.All.SendAsync(
"gridupdate",
details.EventId,
details.EventType,
details.Source,
details.EventTime,
jsonContent
);

return Ok();
}

private static bool IsCloudEvent(string jsonContent)
{
// Cloud events are sent one at a time, while Grid events
// are sent in an array. As a result, the JObject.Parse will
// fail for Grid events.
try
{
// Attempt to read one JSON object.
var eventData = JObject.Parse(jsonContent);

// Check for the cloud events version property.
var version = eventData["cloudEventsVersion"].Value<string>();
if (!string.IsNullOrEmpty(version)) return true;
}
catch (Exception e)
{
Console.WriteLine(e);
}

return false;
}

#endregion
}
}
11 changes: 11 additions & 0 deletions viewer/Hubs/GridEventsHub.cs
@@ -0,0 +1,11 @@
using Microsoft.AspNetCore.SignalR;

namespace viewer.Hubs
{
public class GridEventsHub: Hub
{
public GridEventsHub()
{
}
}
}
29 changes: 29 additions & 0 deletions viewer/Models/CloudEvent.cs
@@ -0,0 +1,29 @@

using Newtonsoft.Json;

namespace viewer.Models
{
public class CloudEvent<T> where T : class
{
[JsonProperty("eventID")]
public string EventId { get; set; }

[JsonProperty("cloudEventsVersion")]
public string CloudEventVersion { get; set; }

[JsonProperty("eventType")]
public string EventType { get; set; }

[JsonProperty("eventTypeVersion")]
public string EventTypeVersion { get; set; }

[JsonProperty("source")]
public string Source { get; set; }

[JsonProperty("eventTime")]
public string EventTime { get; set; }

[JsonProperty("data")]
public T Data { get; set; }
}
}

0 comments on commit 7eb4318

Please sign in to comment.