Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump gson from 2.8.5 to 2.8.9 in /samples/Java/Basic/SimpleSend #493

Open
wants to merge 88 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
9c355e9
draft
serkantkaraca Jun 27, 2019
037168f
Adding control plane + data plane EH sample
serkantkaraca Jun 28, 2019
37cf05a
SDK ref fixes for EH RBAC sample
serkantkaraca Jun 28, 2019
2dba515
Merge branch 'master' of https://github.com/Azure/azure-event-hubs in…
serkantkaraca Jul 1, 2019
118133b
Updates for 3.0.0 RBAC release
JamesBirdsall Jul 1, 2019
27c213b
Adding RBAC custom role sample
serkantkaraca Jul 2, 2019
51587c8
Remove unintented files
serkantkaraca Jul 2, 2019
10ec29a
Reverting unintended changes
serkantkaraca Jul 2, 2019
c030b6d
readme changes
serkantkaraca Jul 2, 2019
1306652
minor changes
serkantkaraca Jul 2, 2019
eda4dbd
Refactoring token acquisition
serkantkaraca Jul 2, 2019
4a87ed4
Update readme.md
serkantkaraca Jul 2, 2019
3337741
Update readme.md
serkantkaraca Jul 2, 2019
d47a55f
Merge pull request #446 from Azure/serkar.AddCustomRbacEhSample
serkantkaraca Jul 2, 2019
8caf262
Adding sender sample for rbac
ShubhaVijayasarathy Jul 3, 2019
edb6409
Merge pull request #445 from Azure/RBACupdates
ShubhaVijayasarathy Jul 17, 2019
9940943
Merge branch 'master' of https://github.com/Azure/azure-event-hubs in…
serkantkaraca Jul 18, 2019
23d3eaa
Moving Managed Identity sample to .NET Standard SDK
serkantkaraca Jul 18, 2019
566ef0c
Remove unintended SampleSender changes
serkantkaraca Jul 18, 2019
12583b9
Revert "Updates for Java client 3.0.0 RBAC release" (#448)
ShubhaVijayasarathy Jul 22, 2019
f335055
Merge pull request #449 from Azure/MsiSampleChanges
serkantkaraca Jul 22, 2019
ff85c7c
Move EH SDK to 4.0.0
serkantkaraca Jul 22, 2019
582fc0b
Merge pull request #451 from Azure/FixRbcSample2
serkantkaraca Jul 22, 2019
bb7a402
Remove CxCache dependency in ReliableSender sample
serkantkaraca Jul 22, 2019
526c56c
-
serkantkaraca Jul 22, 2019
a5895c7
Merge pull request #452 from Azure/RemoveCxCacheReferences
serkantkaraca Jul 22, 2019
225db71
Reorging the folder structure
ShubhaVijayasarathy Jul 22, 2019
d548f8f
adding samples to Messaging.SErviceBus
ShubhaVijayasarathy Jul 22, 2019
a35a76f
Update App.config
serkantkaraca Jul 24, 2019
5cb25d3
Moving SFProcessor sample into SDK folder
serkantkaraca Jul 25, 2019
a9876ef
Merge pull request #453 from Azure/reorg_samples
serkantkaraca Jul 25, 2019
d096ca2
Update Java samples for 3.0.0 client (#455)
JamesBirdsall Aug 29, 2019
12b87e6
Consolidate all Java RBAC sample work (#456)
JamesBirdsall Aug 29, 2019
cbc412e
updated to use the 5.0.0 SDK (#459)
spelluru Oct 23, 2019
790471f
Update samples for client 3.0.2 (#457)
JamesBirdsall Oct 23, 2019
8cf2471
updated samples used by tutorials to use the new package
spelluru Oct 30, 2019
17f6ceb
updated Anomaly Detector and Wind Turbine Data Generator samples for …
spelluru Nov 5, 2019
a4354c1
updated Anomaly Detector and WindTurbineDataGenerator samples for Pre…
spelluru Dec 5, 2019
2be764e
updated for Preview 6
spelluru Dec 6, 2019
78ec550
updated based on feedback from Serkant and Jesse
spelluru Jan 9, 2020
000b20a
minor update to UI - fully qualified name
spelluru Jan 9, 2020
40fa580
added using statements
spelluru Jan 9, 2020
284fd90
Merge pull request #463 from spelluru/newpackagesamples1029
serkantkaraca Jan 13, 2020
f4f50e8
fixed the receive code
spelluru Jan 15, 2020
f65204b
Merge pull request #464 from spelluru/fixmsi0115
spelluru Jan 16, 2020
72fc2bb
Updated samples to use the latest .NET package
spelluru Jan 30, 2020
1b66691
Merge pull request #466 from spelluru/ehubsamples0130
spelluru Feb 12, 2020
3527fe9
Add async send sample (#468)
JamesBirdsall Apr 22, 2020
7ed366d
updated the readme to point to new samples. Cleaned up too.
spelluru Apr 30, 2020
5a42971
Merge pull request #469 from spelluru/sdklinks0430
spelluru May 6, 2020
5a16c14
Updated to use Functions runtime version 3 (latest)
spelluru Jun 9, 2020
5acf9e8
removed publish profile
spelluru Jun 9, 2020
3af21a2
Merge pull request #471 from spelluru/egridintegrationsample0608
spelluru Jun 9, 2020
e9e01dd
updated to use Azure.Messaging.EventHubs 5.2 - latest stable version
spelluru Dec 8, 2020
d6bf8b1
Merge pull request #472 from spelluru/ehubegridintegration1207
serkantkaraca Dec 8, 2020
da5dd91
modified readmes to point to Track 2 content; moved files to right fo…
Mar 17, 2021
aa20765
addressed review feedback
Mar 23, 2021
8576c5e
Simplify readme for RBAC
ramya-rao-a Apr 2, 2021
719324b
Re-order steps for custom role sample for clarity
ramya-rao-a Apr 2, 2021
de8fe23
Consolidate intro and note, use quick start links
ramya-rao-a Apr 2, 2021
ca68875
Merge pull request #475 from ramya-rao-a/lily-patch
lilyjma Apr 5, 2021
f471963
Merge pull request #474 from Azure/lily-patch
lilyjma Apr 6, 2021
97caf51
moved samples to approach directories
Apr 7, 2021
1362353
Remove duplicate sample for EventHubsCaptureEventGridDemo
ramya-rao-a Apr 9, 2021
6d8fc54
Merge pull request #477 from ramya-rao-a/remove-dupe
spelluru Apr 12, 2021
10df2c2
Merge pull request #476 from Azure/lily-patch2
spelluru Apr 12, 2021
809eb4c
Clean up of the EventHubsCaptureEventGridDemo sample in the azure-eve…
zedy-wj Apr 15, 2021
71ed5ea
Add pointers to new packages in readme files at the root and for .Net…
ramya-rao-a Apr 16, 2021
d961416
Updating to use EventHubsCaptureAvroBlobUri to create the BlobClient …
zedy-wj Apr 19, 2021
4cadf09
Updating the Reference
zedy-wj Apr 21, 2021
bffa22a
Merge pull request #479 from zedy-wj/CleanupEventhub
spelluru Apr 23, 2021
5c333eb
Sample using Event Hub Log4j Appender (#482)
sagar027 Sep 2, 2021
15b99a5
Update readme with pointers to newer samples (#481)
ramya-rao-a Sep 22, 2021
3cb13d5
Fix incorrect redirection (#467)
madushajg Sep 22, 2021
0b193ff
fix code comment (#485)
v-thpra Mar 7, 2022
df61522
Addition of Schema to Schema groups via Powershell
Saglodha Apr 7, 2022
af22936
Add schema to schema groups via Bash
Saglodha Apr 7, 2022
ab93acf
Added PS variables
Saglodha Apr 28, 2022
d910592
Merge pull request #488 from Saglodha/master
serkantkaraca Apr 29, 2022
f8c2795
Updating the sample to use latest packages
spelluru May 6, 2022
fe3a7bc
ARM template
spelluru May 6, 2022
6c396fc
Delete samples/e2e/EventHubsCaptureEventGridDemo/DWDumper directory
spelluru May 6, 2022
2570003
Delete samples/e2e/EventHubsCaptureEventGridDemo/media directory
spelluru May 6, 2022
2f0f8d7
Delete samples/e2e/EventHubsCaptureEventGridDemo/scripts directory
spelluru May 6, 2022
3702362
Merge pull request #1 from spelluru/spelluru-patch-1
spelluru May 6, 2022
34706f7
Duplicate of Data.cs
spelluru May 6, 2022
5723a0c
Merge pull request #490 from spelluru/master
spelluru May 13, 2022
a90fb33
Bump gson from 2.8.5 to 2.8.9 in /samples/Java/Basic/SimpleSend
dependabot[bot] May 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 38 additions & 15 deletions readme.md
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
<img src="event-hubs.png" alt="Microsoft Azure Event Hubs" width="100"/>
</p>

<h1 align="center">Microsoft Azure Event Hubs
<h1 align="center">Azure Event Hubs samples
<p align="center">
<a href="#star-our-repo">
<img src="https://img.shields.io/github/stars/azure/azure-event-hubs.svg?style=social&label=Stars"
@@ -12,23 +12,46 @@
alt="follow on Twitter"></a>
</p></h1>

We're happy to host our client SDKs and integrations on GitHub as free, open-source projects. We currently support:
This repository contains samples for Azure Event Hubs.

* [Event Hubs for Apache Kafka](https://github.com/Azure/azure-event-hubs-for-kafka)
* [.NET](https://github.com/azure/azure-event-hubs-dotnet)
* [Java](https://github.com/azure/azure-event-hubs-java)
* [C](https://github.com/azure/azure-event-hubs-c)
* [Node.js](https://github.com/azure/azure-event-hubs-node)
* [Python](https://github.com/azure/azure-event-hubs-python)
* [Go](https://github.com/azure/azure-event-hubs-go)
* [Apache Spark connector](https://github.com/Azure/azure-event-hubs-spark)
## Client SDK samples

If you have any feedback, questions, or comments, go to the respective repo and file an issue. **Your involvement is welcome and encouraged!**
> **Note:** This repository holds samples for the legacy libraries for Azure Event Hubs for .NET and Java developers. We highly recommend you to upgrade to the newer packages.

.NET legacy packages

- Microsoft.Azure.EventHubs (**legacy**)
- Microsoft.Azure.EventHubs.Processor (**legacy**)
- WindowsAzure.ServiceBus (**legacy**)

Java legacy packages

- com.microsoft.azure:azure-eventhubs (**legacy**)
- com.microsoft.azure:azure-eventhubs-eph (**legacy**)

Samples for **latest** .NET packages for Azure Event Hubs

## What is Event Hubs?
- [Azure.Messaging.EventHubs](https://docs.microsoft.com/samples/azure/azure-sdk-for-net/azuremessagingeventhubs-samples/)
- [Azure.Messaging.EventHubs.Processor](https://docs.microsoft.com/samples/azure/azure-sdk-for-net/azuremessagingeventhubsprocessor-samples/)

Samples for **latest** Java packages for Azure Event Hubs

- [com.azure:azure-messaging-eventhubs](https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/eventhubs/azure-messaging-eventhubs/src/samples)
- [com.azure:azure-messaging-eventhubs-checkpointstore-blob](https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/eventhubs/azure-messaging-eventhubs-checkpointstore-blob/src/samples)

You can find samples for other languages and frameworks in the following repositories:
- [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/eventhub/event-hubs/samples)
- [Python](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/eventhub/azure-eventhub/samples)
- [C](https://github.com/azure/azure-event-hubs-c)
- [Go](https://github.com/azure/azure-event-hubs-go)
- [Apache Spark connector](https://github.com/Azure/azure-event-hubs-spark)
- [Event Hubs for Apache Kafka](https://github.com/Azure/azure-event-hubs-for-kafka)

If you have any feedback, questions, or comments, go to the respective repo and file an issue. **Your involvement is welcome and encouraged!**

Azure Event Hubs is a hyper-scale data ingestion service, fully-managed by Microsoft, that enables you to collect, store and process trillions of events from websites, apps, IoT devices, and any stream of data. To learn more, please visit our [marketing page](https://azure.microsoft.com/services/event-hubs/).
## Management SDK samples
This repository also contains [management samples](https://github.com/Azure/azure-event-hubs/tree/master/samples/Management) that use the .NET management SDK, PowerShell, and CLI.

## Azure Event Hubs for Apache Kafka

Event Hubs now provides a Kafka endpoint that can be used by your existing Kafka-based applications as an alternative to running your own Kafka cluster. To learn more, check out the new [Azure Event Hubs for Apache Kafka](https://github.com/Azure/azure-event-hubs-for-kafka) repo!
## See also
To learn about Event Hubs, see our [Event Hubs documentation](https://docs.microsoft.com/en-us/azure/event-hubs/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
using System;
using System.Text;
using System.Threading.Tasks;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Producer;
using System.Collections.Generic;
using System.IO;

public class Program
{
private const string EventHubNamespaceConnectionString = "<EVENT HUBS NAMESPACE CONNECTION STRING>";
private const string EventHubName = "<EVENT HUB NAME>";
private const string TransactionsDumpFile = "mocktransactions.csv";

private static EventHubProducerClient producerClient;

static async Task Main()
{
// create an Event Hubs Producer client using the namespace connection string and the event hub name
producerClient = new EventHubProducerClient(EventHubNamespaceConnectionString, EventHubName);

// send messages to the event hub
await SendMessagesToEventHubAsync(1000);

await producerClient.CloseAsync();

Console.WriteLine("Press [enter] to exit.");
Console.ReadLine();
}

// Creates an Event Hub client and sends messages to the event hub.
private static async Task SendMessagesToEventHubAsync(int numMessagesToSend)
{
var eg = new EventGenerator();

IEnumerable<Transaction> transactions = eg.GenerateEvents(numMessagesToSend);

if (File.Exists(TransactionsDumpFile))
{
// exceptions not handled for brevity
File.Delete(TransactionsDumpFile);
}

await File.AppendAllTextAsync(
TransactionsDumpFile,
$"CreditCardId,Timestamp,Location,Amount,Type{Environment.NewLine}");

int numSuccessfulMessages = 0;
try
{
// create a batch using the producer client
using (EventDataBatch eventBatch = await producerClient.CreateBatchAsync())
{
foreach (var t in transactions)
{
// we don't send the transaction type as part of the message.
// that is up to the downstream analytics to figure out!
// we just pretty print them here so they can easily be compared with the downstream
// analytics results.
var message = t.Data.ToJson();

if (t.Type == TransactionType.Suspect)
{
var fc = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;

Console.WriteLine($"Suspect transaction: {message}");

Console.ForegroundColor = fc; // reset to original
}
else
{
Console.WriteLine($"Regular transaction: {message}");
}

var line = $"{t.Data.CreditCardId},{t.Data.Timestamp.ToString("o")},{t.Data.Location},{t.Data.Amount},{t.Type}{Environment.NewLine}";

File.AppendAllText(TransactionsDumpFile, line);

// add the message to the batch
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(message)));
numSuccessfulMessages++;
}
// send the batch of messages to the event hub using the producer object
await producerClient.SendAsync(eventBatch);
await Task.Delay(10);
}
}
catch (Exception ex)
{
Console.WriteLine($"{Environment.NewLine}Exception: {ex.Message}");
}
Console.WriteLine();
Console.WriteLine($"{numSuccessfulMessages} messages sent successfully.");
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

# Visualize data anomalies in real-time events sent to Azure Event Hubs
In this sample, you run an application that creates and sends credit card transactions to an event hub. Then you read the stream of data in real-time with Azure Stream Analytics, which separates the valid transactions from the invalid transactions, and then use Power BI to visually identify the transactions that are tagged as invalid.

For detailed information and steps for using this sample, see [this article](https://docs.microsoft.com/azure/event-hubs/event-hubs-tutorial-visualize-anomalies).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="ManagedIdentityWebApp.Global" Language="C#" %>
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
using System.Web.Security;
using System.Web.SessionState;

namespace EventHubsMSIDemoWebApp
namespace ManagedIdentityWebApp
{
public class Global : System.Web.HttpApplication
{

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHubsMSIDemoWebApp", "EventHubsMSIDemoWebApp\EventHubsMSIDemoWebApp.csproj", "{476F98B4-05BF-42B6-B0B4-E50CD5B71635}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedIdentityWebApp", "ManagedIdentityWebApp.csproj", "{476F98B4-05BF-42B6-B0B4-E50CD5B71635}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EventHubsMSIDemoWebApp")]
[assembly: AssemblyTitle("ManagedIdentityWebApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EventHubsMSIDemoWebApp")]
[assembly: AssemblyProduct("ManagedIdentityWebApp")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<%@ Page Async="true" Language="C#" AutoEventWireup="true" CodeBehind="SendReceive.aspx.cs" Inherits="ManagedIdentityWebApp.SendReceive" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>EventHubs Managed Identity Demo</title>
<link rel="stylesheet" href="StyleSheet.css" />
</head>
<body>
<form id="form1" runat="server">
<div style="white-space: pre">
<div>
<label>Event Hubs Namespace - Fully qualified</label><asp:TextBox ID="txtNamespace" runat="server" Text="" Width="500px" />
</div>
<div>
<label>Event Hub Name</label><asp:TextBox ID="txtEventHub" runat="server" Text=""/>
</div>
<div>
<label>Data to Send</label> <asp:TextBox ID="txtData" runat="server" TextMode="MultiLine" Width="500px"/>
</div>
<div>
<asp:Button ID="btnSend" runat="server" Text="Send" OnClick="btnSend_Click" /> <asp:Button ID="btnReceive" runat="server" Text="Receive" OnClick="btnReceive_Click" />
</div>
<div>
<asp:TextBox ID="txtOutput" runat="server" Enabled="false" TextMode="MultiLine" Width="800px" Height="200px" />
<asp:HiddenField ID="hiddenStartingOffset" runat="server" />
</div>
</div>
</form>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


// Always add app to IAM roles
// Don't use on deployment slots but only on root
namespace ManagedIdentityWebApp
{
using System;
using System.Text;
using System.Threading;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Producer;
using Azure.Messaging.EventHubs.Consumer;
using Azure.Identity;
using System.Threading.Tasks;

public partial class SendReceive : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected async void btnSend_Click(object sender, EventArgs e)
{
await using (EventHubProducerClient producerClient = new EventHubProducerClient(txtNamespace.Text, txtEventHub.Text, new DefaultAzureCredential()))
{
// create a batch
using (EventDataBatch eventBatch = await producerClient.CreateBatchAsync())
{

// add events to the batch. only one in this case.
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(txtData.Text)));

// send the batch to the event hub
await producerClient.SendAsync(eventBatch);
}

txtOutput.Text = $"{DateTime.Now} - SENT{Environment.NewLine}{txtOutput.Text}";
}
}
protected async void btnReceive_Click(object sender, EventArgs e)
{
await using (var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, txtNamespace.Text, txtEventHub.Text, new DefaultAzureCredential()))
{
int eventsRead = 0;
try
{
using CancellationTokenSource cancellationSource = new CancellationTokenSource();
cancellationSource.CancelAfter(TimeSpan.FromSeconds(5));

await foreach (PartitionEvent partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token))
{
txtOutput.Text = $"Event Read: { Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray()) }{ Environment.NewLine}" + txtOutput.Text;
eventsRead++;
}
}
catch (TaskCanceledException ex)
{
txtOutput.Text = $"Number of events read: {eventsRead}{ Environment.NewLine}" + txtOutput.Text;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
label {
width: 100px;
width: 540px;
display: inline-block;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.7.2" />
</system.Web>
-->
<system.web>
<compilation debug="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.6.1" />
<customErrors mode="Off" />
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.4.0" newVersion="5.2.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.Services.AppAuthentication" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.1.0" newVersion="1.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.7.1.0" newVersion="4.7.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.ProtectedData" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Azure.Core" version="1.0.1" targetFramework="net472" />
<package id="Azure.Identity" version="1.1.0" targetFramework="net472" />
<package id="Azure.Messaging.EventHubs" version="5.0.1" targetFramework="net472" />
<package id="Microsoft.Azure.Amqp" version="2.4.3" targetFramework="net472" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net472" />
<package id="Microsoft.Identity.Client" version="4.7.1" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="System.Buffers" version="4.5.0" targetFramework="net472" />
<package id="System.Diagnostics.DiagnosticSource" version="4.7.0" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
<package id="System.Net.WebSockets" version="4.3.0" targetFramework="net472" />
<package id="System.Net.WebSockets.Client" version="4.3.2" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.0-preview5.19224.8" targetFramework="net472" />
<package id="System.Reflection.TypeExtensions" version="4.7.0" targetFramework="net472" />
<package id="System.Runtime" version="4.3.1" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.0" targetFramework="net472" />
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.ProtectedData" version="4.7.0" targetFramework="net472" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
<package id="System.Text.Encodings.Web" version="4.7.0" targetFramework="net472" />
<package id="System.Text.Json" version="4.7.0" targetFramework="net472" />
<package id="System.Threading.Channels" version="4.7.0" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.6.0-preview.18571.3" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Producer", "Producer\Producer.csproj", "{8A768654-3ABD-4D6B-BDB3-C59CFC05C50A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A768654-3ABD-4D6B-BDB3-C59CFC05C50A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A768654-3ABD-4D6B-BDB3-C59CFC05C50A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A768654-3ABD-4D6B-BDB3-C59CFC05C50A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A768654-3ABD-4D6B-BDB3-C59CFC05C50A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {73BDBF55-C72D-4F8D-999B-E8E068E3B5A4}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
using System;
using System.Collections.Generic;

internal sealed class EventGenerator
{
// i.e. 1 in every 20 transactions is an anomaly
private const int AnomalyFactor = 20;

private const int MaxAmount = 1000;

private const int MaxDays = 30;

private readonly Random random = new Random((int)DateTimeOffset.UtcNow.Ticks);

private readonly DateTimeOffset startTime = new DateTimeOffset(DateTime.Now);

private readonly List<string> knownCreditCards = new List<string>
{
"FC6018B3-B934-4FFF-B6A9-904C4B3082C7",
"71B3B20F-0BD1-4C1D-BA33-3264D904581C",
"B3B19755-C6E5-4E4A-B423-1B31DCCEB137",
"1AF29CA0-FBF2-48B6-9D0B-88FF331FADC1",
"039AA17C-2C5C-4A4F-B019-D416D0E4F5E6",
};

private readonly List<string> knownLocations = new List<string>
{
"Seattle",
"San Francisco",
"New York",
"Kahului",
"Miami",
};

public IEnumerable<Transaction> GenerateEvents(int count)
{
int counter = 0;

var timestamp = startTime;

while (counter < count)
{
foreach (var t in NewMockPurchases(timestamp))
{
yield return t;
counter++;
}

timestamp += TimeSpan.FromMinutes(10);
}
}

/// <summary>
/// Returns a new mock transaction. In some cases where there is an anomaly, then it returns
/// 2 transactions. one regular and one anomaly. They differ in amounts, locations and timestamps, but have
/// the same credit card Id.
/// At the consumer side, since the timestamps are close together but the locations are different, these
/// 2 transactions are flagged as anomalous.
/// </summary>
/// <returns></returns>
private IEnumerable<Transaction> NewMockPurchases(DateTimeOffset timestamp)
{
var maxIndex = Math.Min(knownCreditCards.Count, knownLocations.Count);

var index = random.Next(0, maxIndex);
var cc = knownCreditCards[index];
var location = knownLocations[index];

bool isAnomaly = (random.Next(0, AnomalyFactor) % AnomalyFactor) == 0;

var purchases = new List<Transaction>();

var regularTransaction = new Transaction
{
Data = new TransactionData
{
Amount = random.Next(1, MaxAmount),
Location = location,
CreditCardId = cc,
Timestamp = timestamp,
},
Type = TransactionType.Regular,
};

purchases.Add(regularTransaction);

if (isAnomaly)
{
// change the location to something else
// now the transaction on a credit card is happening from a different location which is an anomaly!

string newLocation = null;

do
{
var newIndex = random.Next(0, knownLocations.Count);
newLocation = knownLocations[newIndex];

// while loop is - if by chance the "random" new location is the same as the original location

} while (string.Equals(newLocation, location, StringComparison.OrdinalIgnoreCase));

var suspectTransaction = new Transaction
{
Data = new TransactionData
{
Amount = random.Next(1, MaxAmount),
Location = newLocation,
CreditCardId = cc,
Timestamp = timestamp + TimeSpan.FromSeconds(2), // suspect transaction time range is close to a regular transaction
},
Type = TransactionType.Suspect,
};

purchases.Add(suspectTransaction);
}

return purchases;
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public static class JsonHelper
{
private static readonly JsonSerializerSettings publicSerializationSettings = CreatePublicSerializationSettings();

/// <summary>
/// Converts an object to its Json representation.
/// </summary>
public static string ToJson<T>(this T value)
{
string json = JsonConvert.SerializeObject(value, typeof(T), publicSerializationSettings);
return json;
}

/// <remarks>
/// Converts a Json string to an object.
/// </remarks>
public static T FromJson<T>(this string value)
{
T @object = JsonConvert.DeserializeObject<T>(value, publicSerializationSettings);

return @object;
}

private static JsonSerializerSettings CreatePublicSerializationSettings()
{
var settings = new JsonSerializerSettings();

settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

return settings;
}
}
}

Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.EventHubs" Version="1.1.0" />
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.0.0-preview.4" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>

Original file line number Diff line number Diff line change
@@ -6,15 +6,15 @@ namespace Producer
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Azure.Messaging.EventHubs;
using System.Collections.Generic;
using System.IO;

public class Program
{
private const string EventHubConnectionString = "Event Hubs connection string";
private const string EventHubConnectionString = "<EVENT HUBS NAMESPACE CONNECTION STRING>";

private const string EventHubName = "Event Hub name";
private const string EventHubName = "<EVENT HUB NAME>";

private const string TransactionsDumpFile = "mocktransactions.csv";

@@ -27,16 +27,10 @@ public static int Main(string[] args)

private static async Task<int> MainAsync(string[] args)
{
// Creates an EventHubsConnectionStringBuilder object from a the connection string, and sets the EntityPath.
// Typically the connection string should have the Entity Path in it, but for the sake of this simple scenario
// we are using the connection string from the namespace.
var connectionStringBuilder = new EventHubsConnectionStringBuilder(EventHubConnectionString)
{
EntityPath = EventHubName,
};

eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());
// create an Event Hubs client using the namespace connection string and the event hub name
eventHubClient = new EventHubClient(EventHubConnectionString, EventHubName);

// send messages to the event hub
await SendMessagesToEventHubAsync(1000);

await eventHubClient.CloseAsync();
@@ -64,6 +58,9 @@ private static async Task SendMessagesToEventHubAsync(int numMessagesToSend)
TransactionsDumpFile,
$"CreditCardId,Timestamp,Location,Amount,Type{Environment.NewLine}");

// create a producer object that you can use to produce or send messages to the event hub
EventHubProducer producer = eventHubClient.CreateProducer();

foreach (var t in transactions)
{
try
@@ -93,7 +90,9 @@ private static async Task SendMessagesToEventHubAsync(int numMessagesToSend)
File.AppendAllText(TransactionsDumpFile, line);

var ed = new EventData(Encoding.UTF8.GetBytes(message));
await eventHubClient.SendAsync(ed);

// send the message to the event hub using the producer object
await producer.SendAsync(ed);
}
catch (Exception ex)
{
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
internal sealed class Transaction
{
public TransactionData Data { get; set; }

public TransactionType Type { get; set; }
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
using System;

internal sealed class TransactionData
{
public string CreditCardId { get; set; } // like a credit card no. just simpler to use a Guid for our sample than a 16 digit no!

public int Amount { get; set; } // simplified to int instead of double for now

public string Location { get; set; }

public DateTimeOffset Timestamp { get; set; }
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Producer
{
/// <summary>
/// A mechanism to identify the mock transactions that are generated on the client side.
/// This is not used downstream. But is used more for an easy (or visual) comparison of
/// anomalous data that the downstream analytics produces.
/// </summary>
internal enum TransactionType
{
Regular,
Suspect,
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="tenantId" value="" />
<add key="clientId" value="" />
<add key="replyUrl" value="" />
<add key="eventHubNamespaceFQDN" value="" />
<add key="eventHubName" value="" />
<add key="thumbPrint" value="" />
<add key="clientSecret" value="" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.19.6.14301" newVersion="3.19.6.14301" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.1.1.3" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.4.0.0" newVersion="5.4.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.1" newVersion="4.0.3.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Serialization.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Original file line number Diff line number Diff line change
@@ -93,7 +93,8 @@ static async Task ClientAssertionCertScenarioAsync()

var authResult = await app.AcquireTokenForClient(new string[] { $"{audience}/.default" }).ExecuteAsync();
return authResult.AccessToken;
});
},
$"https://login.microsoftonline.com/{TenantId}");

var ehClient = EventHubClient.CreateWithTokenProvider(new Uri($"sb://{EventHubNamespace}/"), EventHubName, tp);
await SendReceiveAsync(ehClient);
@@ -111,17 +112,13 @@ static async Task ClientCredentialsScenarioAsync()

var authResult = await app.AcquireTokenForClient(new string[] { $"{audience}/.default" }).ExecuteAsync();
return authResult.AccessToken;
});
},
$"https://login.microsoftonline.com/{TenantId}");

var ehClient = EventHubClient.CreateWithTokenProvider(new Uri($"sb://{EventHubNamespace}/"), EventHubName, tp);
await SendReceiveAsync(ehClient);
}

static Task ControlPlaneAndDataPlaneMixedScenarioAsync()
{
return Task.FromResult(0);
}

static X509Certificate2 GetCertificate()
{
List<StoreLocation> locations = new List<StoreLocation>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Role based access sample with Microsoft.Azure.EventHubs SDK

See [Authorize access to Event Hubs resources using Azure Active Directory](https://docs.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory) for information on Role based access (RBAC).

**Note**: This sample shows different ways to authenticate using Azure Active Directory with the legacy Event Hubs library `Microsoft.Azure.EventHubs`.
For the current version of the library `Azure.Messaging.EventHubs`, please see the [sample that makes use of credentials from Azure.Identity](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md).
Original file line number Diff line number Diff line change
@@ -40,34 +40,34 @@
<Reference Include="Microsoft.Azure.Amqp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.Amqp.2.4.2\lib\net45\Microsoft.Azure.Amqp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.EventHubs, Version=3.0.0.0, Culture=neutral, PublicKeyToken=7e34167dcc6d6d8c, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.EventHubs.3.0.0-dev.20190618.1\lib\net461\Microsoft.Azure.EventHubs.dll</HintPath>
<Reference Include="Microsoft.Azure.EventHubs, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7e34167dcc6d6d8c, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.EventHubs.4.0.0\lib\net461\Microsoft.Azure.EventHubs.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Services.AppAuthentication, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.Azure.Services.AppAuthentication.1.2.0\lib\net461\Microsoft.Azure.Services.AppAuthentication.dll</HintPath>
<HintPath>packages\Microsoft.Azure.Services.AppAuthentication.1.2.0\lib\net461\Microsoft.Azure.Services.AppAuthentication.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Identity.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Identity.Client.4.0.0\lib\net45\Microsoft.Identity.Client.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.4.11002, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.19.4.11002, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.IdentityModel.JsonWebTokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.IdentityModel.JsonWebTokens.5.5.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
<HintPath>packages\Microsoft.IdentityModel.JsonWebTokens.5.5.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.IdentityModel.Logging, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.IdentityModel.Logging.5.5.0\lib\net461\Microsoft.IdentityModel.Logging.dll</HintPath>
<HintPath>packages\Microsoft.IdentityModel.Logging.5.5.0\lib\net461\Microsoft.IdentityModel.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\Microsoft.IdentityModel.Tokens.5.5.0\lib\net461\Microsoft.IdentityModel.Tokens.dll</HintPath>
<HintPath>packages\Microsoft.IdentityModel.Tokens.5.5.0\lib\net461\Microsoft.IdentityModel.Tokens.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@@ -85,30 +85,30 @@
<Reference Include="System.Data" />
<Reference Include="System.IdentityModel" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.IdentityModel.Tokens.Jwt.5.5.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll</HintPath>
<HintPath>packages\System.IdentityModel.Tokens.Jwt.5.5.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.WebSockets, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.Net.WebSockets.4.3.0\lib\net46\System.Net.WebSockets.dll</HintPath>
<HintPath>packages\System.Net.WebSockets.4.3.0\lib\net46\System.Net.WebSockets.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.WebSockets.Client, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.Net.WebSockets.Client.4.3.2\lib\net46\System.Net.WebSockets.Client.dll</HintPath>
<HintPath>packages\System.Net.WebSockets.Client.4.3.2\lib\net46\System.Net.WebSockets.Client.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reflection.TypeExtensions, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Runtime.Serialization.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.Runtime.Serialization.Primitives.4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll</HintPath>
<HintPath>packages\System.Runtime.Serialization.Primitives.4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -118,7 +118,7 @@
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\CxCache\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" />
@@ -136,14 +136,15 @@
<None Include="nuget.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Azure.Services.AppAuthentication.1.0.3\build\Microsoft.Azure.Services.AppAuthentication.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Azure.Services.AppAuthentication.1.0.3\build\Microsoft.Azure.Services.AppAuthentication.targets'))" />
</Target>
<Import Project="packages\Microsoft.Azure.Services.AppAuthentication.1.0.3\build\Microsoft.Azure.Services.AppAuthentication.targets" Condition="Exists('packages\Microsoft.Azure.Services.AppAuthentication.1.0.3\build\Microsoft.Azure.Services.AppAuthentication.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.Amqp" version="2.4.2" targetFramework="net462" />
<package id="Microsoft.Azure.EventHubs" version="3.0.0-dev.20190618.1" targetFramework="net462" />
<package id="Microsoft.Azure.EventHubs" version="4.0.0" targetFramework="net462" />
<package id="Microsoft.Azure.Services.AppAuthentication" version="1.2.0" targetFramework="net462" />
<package id="Microsoft.Identity.Client" version="4.0.0" targetFramework="net462" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.19.4" targetFramework="net462" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>CustomRole</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>CustomRole</PackageId>
<RuntimeFrameworkVersion>2.1.0</RuntimeFrameworkVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.EventHubs" Version="4.0.0" />
<PackageReference Include="Microsoft.Azure.EventHubs.Processor" Version="4.0.0" />
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="9.4.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomRole", "CustomRole.csproj", "{679DFCC5-76BD-4725-A51E-AFBB01565401}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Debug|Any CPU.Build.0 = Debug|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Release|Any CPU.ActiveCfg = Release|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4190FE18-2881-43ED-9A45-6AECB8D3314A}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace CustomRole
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Microsoft.Azure.EventHubs.Processor;
using Microsoft.Identity.Client;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;

public class Program
{
private const string Authority = "Authority of tenant";
private const string ClientId = "AAD app id";
private const string ClientSecret = "AAD app secret";
private const string EventHubNamespace = "FQDN of Event Hubs namespace";
private const string EventHubName = "Event hub name";
private const string StorageAccountName = "Storage account name";
private const string StorageContainerName = "Storage account container name";

static IConfidentialClientApplication tokenClient;

public static async Task Main(string[] args)
{
// Use the same identity client for both Event Hubs and Storage
tokenClient = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithAuthority(Authority)
.WithClientSecret(ClientSecret)
.Build();

// Create Storage client with access token provider
var tokenAndFrequency = await TokenRenewerAsync(tokenClient, CancellationToken.None);
var tokenCredential = new TokenCredential(tokenAndFrequency.Token,
TokenRenewerAsync,
tokenClient,
tokenAndFrequency.Frequency.Value);
var storageCredentials = new StorageCredentials(tokenCredential);
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(storageCredentials, StorageAccountName, string.Empty, true);

// Create Event Hubs access token provider and processor host
TokenProvider tp = TokenProvider.CreateAzureActiveDirectoryTokenProvider(
new AzureActiveDirectoryTokenProvider.AuthenticationCallback(GetAccessTokenAsync), Authority, tokenClient);
var eventProcessorHost = new EventProcessorHost(
new Uri(EventHubNamespace),
EventHubName,
PartitionReceiver.DefaultConsumerGroupName,
tp,
cloudStorageAccount,
StorageContainerName);

// Registers the Event Processor Host and starts receiving messages
Console.WriteLine("Registering EventProcessor...");
await eventProcessorHost.RegisterEventProcessorAsync<SimpleEventProcessor>();

Console.WriteLine("Receiving. Press enter key to stop worker.");
Console.ReadLine();

// Disposes of the Event Processor Host
await eventProcessorHost.UnregisterEventProcessorAsync();
}

private static async Task<NewTokenAndFrequency> TokenRenewerAsync(Object state, CancellationToken cancellationToken)
{
var authResult = await AcquireTokenAsync("https://storage.azure.com/");

// Renew the token 5 minutes before it expires.
var next = (authResult.ExpiresOn - DateTimeOffset.UtcNow) - TimeSpan.FromMinutes(5);
if (next.Ticks < 0)
{
next = default(TimeSpan);
Console.WriteLine("Renewing token...");
}

// Return the new token and the next refresh time.
return new NewTokenAndFrequency(authResult.AccessToken, next);
}

static async Task<string> GetAccessTokenAsync(string audience, string authority, object state)
{
var authResult = await AcquireTokenAsync(audience);

return authResult.AccessToken;
}

static async Task<AuthenticationResult> AcquireTokenAsync(string audience)
{
return await tokenClient
.AcquireTokenForClient(new string[] { $"{audience}/.default" }).ExecuteAsync();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CustomRole")]
[assembly: AssemblyTrademark("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("679dfcc5-76bd-4725-a51e-afbb01565401")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace CustomRole
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Microsoft.Azure.EventHubs.Processor;

public class SimpleEventProcessor : IEventProcessor
{
public Task CloseAsync(PartitionContext context, CloseReason reason)
{
Console.WriteLine($"Processor Shutting Down. Partition '{context.PartitionId}', Reason: '{reason}'.");
return Task.CompletedTask;
}

public Task OpenAsync(PartitionContext context)
{
Console.WriteLine($"SimpleEventProcessor initialized. Partition: '{context.PartitionId}'");
return Task.CompletedTask;
}

public Task ProcessErrorAsync(PartitionContext context, Exception error)
{
Console.WriteLine($"Error on Partition: {context.PartitionId}, Error: {error.Message}");
return Task.CompletedTask;
}

public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
foreach (var eventData in messages)
{
var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}', Partition Key: '{eventData.SystemProperties.PartitionKey}'");
}

return context.CheckpointAsync();
}
}
}
56 changes: 56 additions & 0 deletions samples/DotNet/Microsoft.Azure.EventHubs/Rbac/CustomRole/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Receive events with the Event Processor Host in .NET Standard with a custom role which grants Listen claim for Event Hubs and blob claims for Storage accounts.

**Note:** The sample in this folder uses the legacy Event Hubs library `Microsoft.Azure.EventHubs`. We strongly recommend you to use the current library `Azure.Messaging.EventHubs`. This file has instructions for both.

## Prerequisites

- [Microsoft Visual Studio 2015 or 2017](http://www.visualstudio.com).
- [.NET Core SDK](http://www.microsoft.com/net/core).
- An [Azure subscription](https://azure.microsoft.com/free/).

## Set up for custom role

1. [Create an Event Hubs namespace and an Event Hub](https://docs.microsoft.com/azure/event-hubs/event-hubs-create).
2. Create a Storage account to host a blob container, needed to store checkpoints and information required for balance load among partitions.
3. [Create a new custom role](https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles) with the definition below.
4. [Create a new AAD (Azure Active Directory) application](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal).
5. Assign AAD application to both Event Hubs namespace and Storage account with the custom role you just created.

```
{
"Name": "Custom role for RBAC sample",
"Id": "8ddab47f-cf99-4b04-8fc3-1d2d857fb931",
"Description": "Test role",
"IsCustom": true,
"Actions": [
"Microsoft.Storage/*"
],
"NotActions": [],
"DataActions": [
"Microsoft.EventHub/namespaces/messages/receive/action",
"Microsoft.Storage/*"
],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/your-subscription-id"
]
}
```

## Run the sample for legacy library Microsoft.Azure.EventHubs

After following the [set up steps](#set-up-for-custom-role), to run the sample in this folder to receive events, which uses the legacy library, follow these steps:

1. Clone or download this GitHub repo.
2. Run [Sender application](https://github.com/Azure/azure-event-hubs/tree/serkar.AddCustomRbacEhSample/samples/DotNet/Microsoft.Azure.EventHubs/SampleSender) to send some number of events to your Event Hub instance.
3. Run the CustomRole sample to receive those events back.

## Run the sample for current library Azure.Messaging.EventHubs

After following the [set up steps](#set-up-for-custom-role), to the run the sample to receive events using the current library, follow these steps:

1. Follow the sample in [Publish events using Azure.Messaging.EventHubs](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md) to send some number of events to your Event Hub instance.
2. Follow the sample in [Processing events with identity-based authorization using Azure.Messaging.EventHubs.Processor](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample05_IdentityAndSharedAccessCredentials.md#processing-events-with-identity-based-authorization) to receive the events. To make use of the custom role, set the below environment variables that will be picked up by the `DefaultAzureCredential` used in the sample.
- AZURE_TENANT_ID
- AZURE_CLIENT_ID
- AZURE_CLIENT_SECRET
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="ManagedIdentityWebApp.Global" Language="C#" %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

namespace ManagedIdentityWebApp
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{476F98B4-05BF-42B6-B0B4-E50CD5B71635}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ManagedIdentityWebApp</RootNamespace>
<AssemblyName>ManagedIdentityWebApp</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Azure.Amqp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.Amqp.2.4.3\lib\net45\Microsoft.Azure.Amqp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.EventHubs, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7e34167dcc6d6d8c, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.EventHubs.4.0.0\lib\net461\Microsoft.Azure.EventHubs.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Azure.Services.AppAuthentication, Version=1.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Azure.Services.AppAuthentication.1.2.1\lib\net472\Microsoft.Azure.Services.AppAuthentication.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.4.11002, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.19.4.11002, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.JsonWebTokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.JsonWebTokens.5.5.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Logging, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Logging.5.5.0\lib\net461\Microsoft.IdentityModel.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Tokens.5.5.0\lib\net461\Microsoft.IdentityModel.Tokens.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.3.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\System.IdentityModel.Tokens.Jwt.5.5.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference>
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.WebSockets, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.WebSockets.4.0.0\lib\net46\System.Net.WebSockets.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.WebSockets.Client, Version=4.0.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.WebSockets.Client.4.0.2\lib\net46\System.Net.WebSockets.Client.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Runtime.Serialization.Primitives, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.Serialization.Primitives.4.1.1\lib\net46\System.Runtime.Serialization.Primitives.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Properties\PublishProfiles\ManagedIdentityWebApp20190718022551 - Web Deploy.pubxml" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<Content Include="SendReceive.aspx" />
<Content Include="Global.asax" />
<Content Include="StyleSheet.css" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Include="SendReceive.aspx.cs">
<DependentUpon>SendReceive.aspx</DependentUpon>
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="SendReceive.aspx.designer.cs">
<DependentUpon>SendReceive.aspx</DependentUpon>
</Compile>
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Models\" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>56779</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:56779/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedIdentityWebApp", "ManagedIdentityWebApp.csproj", "{476F98B4-05BF-42B6-B0B4-E50CD5B71635}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{476F98B4-05BF-42B6-B0B4-E50CD5B71635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{476F98B4-05BF-42B6-B0B4-E50CD5B71635}.Debug|Any CPU.Build.0 = Debug|Any CPU
{476F98B4-05BF-42B6-B0B4-E50CD5B71635}.Release|Any CPU.ActiveCfg = Release|Any CPU
{476F98B4-05BF-42B6-B0B4-E50CD5B71635}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AE17B842-5FBE-4C43-B583-5441703DBCE9}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ManagedIdentityWebApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ManagedIdentityWebApp")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("476f98b4-05bf-42b6-b0b4-e50cd5b71635")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Managed Service Identity sample #

**Note:** This sample uses the legacy Event Hubs library `Microsoft.Azure.EventHubs`. We strongly encourage you to use the current library `Azure.Messaging.EventHubs`. See the [corresponding sample](https://github.com/Azure/azure-event-hubs/tree/master/samples/DotNet/Azure.Messaging.EventHubs/ManagedIdentityWebApp) that uses the current library.

For more information on Managed Service Identity (MSI) and how to run this sample follow this [link](https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-managed-service-identity).

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SendReceive.aspx.cs" Inherits="ManagedIdentityWebApp.SendReceive" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>EventHubs Managed Identity Demo</title>
<link rel="stylesheet" href="StyleSheet.css" />
</head>
<body>
<form id="form1" runat="server">
<div style="white-space: pre">
<div>
<label>Event Hubs Namespace</label><asp:TextBox ID="txtNamespace" runat="server" Text="" />
</div>
<div>
<label>Event Hub Name</label><asp:TextBox ID="txtEventHub" runat="server" Text=""/>
</div>
<div>
<label>Partition count</label><asp:TextBox ID="txtPartitions" runat="server" Text="2"/>
</div>
<div>
<label>Data to Send</label> <asp:TextBox ID="txtData" runat="server" TextMode="MultiLine" Width="500px"/>
</div>
<div>
<asp:Button ID="btnSend" runat="server" Text="Send" OnClick="btnSend_Click" /> <asp:Button ID="btnReceive" runat="server" Text="Receive" OnClick="btnReceive_Click" />
</div>
<div>
<asp:TextBox ID="txtOutput" runat="server" Enabled="false" TextMode="MultiLine" Width="800px" Height="200px" />
<asp:HiddenField ID="hiddenStartingOffset" runat="server" />
</div>
</div>
</form>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;

// Always add app to IAM roles
// Don't use on deployment slots but only on root
namespace ManagedIdentityWebApp
{
public partial class SendReceive : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void btnSend_Click(object sender, EventArgs e)
{
EventHubClient ehClient = EventHubClient.CreateWithManagedIdentity(new Uri($"sb://{txtNamespace.Text}.servicebus.windows.net/"), txtEventHub.Text);
ehClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(txtData.Text))).GetAwaiter().GetResult();
txtOutput.Text = $"{DateTime.Now} - SENT{Environment.NewLine}" + txtOutput.Text;
ehClient.Close();
}

protected void btnReceive_Click(object sender, EventArgs e)
{
EventHubClient ehClient = EventHubClient.CreateWithManagedIdentity(new Uri($"sb://{txtNamespace.Text}.servicebus.windows.net/"), txtEventHub.Text);
int partitions = int.Parse(txtPartitions.Text);
string[] lastOffsets = new string[partitions];

if (!string.IsNullOrEmpty(hiddenStartingOffset.Value))
{
lastOffsets = hiddenStartingOffset.Value.Split(',');
}

var totalReceived = 0;

Parallel.ForEach(Enumerable.Range(0, int.Parse(txtPartitions.Text)), partitionId =>
{
var receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, $"{partitionId}", lastOffsets[partitionId] == null ? EventPosition.FromStart() : EventPosition.FromOffset(lastOffsets[partitionId]));
var messages = receiver.ReceiveAsync(int.MaxValue, TimeSpan.FromSeconds(15)).GetAwaiter().GetResult();

if (messages != null)
{
foreach (var message in messages)
{
txtOutput.Text = $"{DateTime.Now} - RECEIVED PartitionId: {partitionId} Seq#:{message.SystemProperties.SequenceNumber} data:{Encoding.UTF8.GetString(message.Body.Array)}{Environment.NewLine}" + txtOutput.Text;
lastOffsets[partitionId] = message.SystemProperties.Offset;
}

Interlocked.Add(ref totalReceived, messages.Count());
}

receiver.Close();
});

txtOutput.Text = $"{DateTime.Now} - RECEIVED TOTAL = {totalReceived}{Environment.NewLine}" + txtOutput.Text;

if (totalReceived > 0)
{
hiddenStartingOffset.Value = string.Join(",", lastOffsets);
}

ehClient.Close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
label {
width: 200px;
display: inline-block;
}

text {
width: 300px;
display: block;
}

input[type="submit"] {
width: 75px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>

<!-- For more information on using web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>

<!-- For more information on using web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>
Loading