Skip to content

Commit 2a0bbe9

Browse files
EG API updates (Azure#18274)
* EG API updates * webjob tests * Use optional serializer param in GetData<T> methods; revert culture in SAS
1 parent 12a86ca commit 2a0bbe9

18 files changed

+478
-439
lines changed

sdk/eventgrid/Azure.Messaging.EventGrid/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ Publishing events to Event Grid is performed using the `EventGridPublisherClient
9696
List<EventGridEvent> eventsList = new List<EventGridEvent>
9797
{
9898
new EventGridEvent(
99-
"This is the event data",
10099
"ExampleEventSubject",
101100
"Example.EventType",
102-
"1.0")
101+
"1.0",
102+
"This is the event data")
103103
};
104104

105105
// Send the events
@@ -138,10 +138,10 @@ To publish events to any topic in an Event Domain, push the events to the domain
138138
List<EventGridEvent> eventsList = new List<EventGridEvent>
139139
{
140140
new EventGridEvent(
141-
"This is the event data",
142141
"ExampleEventSubject",
143142
"Example.EventType",
144-
"1.0")
143+
"1.0",
144+
"This is the event data")
145145
{
146146
Topic = "MyTopic"
147147
}
@@ -185,7 +185,7 @@ foreach (CloudEvent cloudEvent in cloudEvents)
185185
TestPayload testPayload = await cloudEvent.GetDataAsync<TestPayload>(myCustomSerializer);
186186
Console.WriteLine(testPayload.Name);
187187
break;
188-
case SystemEventMappings.StorageBlobDeletedEventName:
188+
case SystemEventNames.StorageBlobDeleted:
189189
// Example for deserializing system events using GetData<T>
190190
StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData<StorageBlobDeletedEventData>();
191191
Console.WriteLine(blobDeleted.BlobType);

sdk/eventgrid/Azure.Messaging.EventGrid/api/Azure.Messaging.EventGrid.netstandard2.0.cs

Lines changed: 113 additions & 109 deletions
Large diffs are not rendered by default.

sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample1_PublishEventsToTopic.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ Note on `EventGridEvent`: each `EventGridEvent` has a set of required, non-nulla
3838
List<EventGridEvent> eventsList = new List<EventGridEvent>
3939
{
4040
new EventGridEvent(
41-
"This is the event data",
4241
"ExampleEventSubject",
4342
"Example.EventType",
44-
"1.0")
43+
"1.0",
44+
"This is the event data")
4545
};
4646

4747
// Send the events

sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample2_PublishEventsToDomain.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ To publish events to any topic in an Event Domain, push the events to the domain
2828
List<EventGridEvent> eventsList = new List<EventGridEvent>
2929
{
3030
new EventGridEvent(
31-
"This is the event data",
3231
"ExampleEventSubject",
3332
"Example.EventType",
34-
"1.0")
33+
"1.0",
34+
"This is the event data")
3535
{
3636
Topic = "MyTopic"
3737
}

sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample3_ParseAndDeserializeEvents.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ foreach (CloudEvent cloudEvent in cloudEvents)
4343
TestPayload testPayload = await cloudEvent.GetDataAsync<TestPayload>(myCustomSerializer);
4444
Console.WriteLine(testPayload.Name);
4545
break;
46-
case SystemEventMappings.StorageBlobDeletedEventName:
46+
case SystemEventNames.StorageBlobDeleted:
4747
// Example for deserializing system events using GetData<T>
4848
StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData<StorageBlobDeletedEventData>();
4949
Console.WriteLine(blobDeleted.BlobType);

sdk/eventgrid/Azure.Messaging.EventGrid/src/Azure.Messaging.EventGrid.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@
2929
<Compile Include="$(AzureCoreSharedSources)Argument.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
3030
<Compile Include="$(AzureCoreSharedSources)AzureResourceProviderNamespaceAttribute.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
3131
</ItemGroup>
32+
<ItemGroup>
33+
<ProjectReference Include="..\..\..\core\Azure.Core\src\Azure.Core.csproj" />
34+
</ItemGroup>
3235

3336
</Project>

sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/CloudEvent.cs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,51 +167,42 @@ public static CloudEvent[] Parse(string requestContent)
167167
/// Deserializes the event payload into a specified event type using the provided <see cref="ObjectSerializer"/>.
168168
/// </summary>
169169
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
170-
/// <param name="serializer"> Custom serializer used to deserialize the payload. </param>
170+
/// <param name="serializer"> A custom serializer used to deserialize the payload. If not provided, the
171+
/// <see cref="JsonObjectSerializer"/> will be used.</param>
171172
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
172173
/// <exception cref="InvalidOperationException"> Event was not created from CloudEvent.Parse() method. </exception>
173174
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
174175
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
175-
public async Task<T> GetDataAsync<T>(ObjectSerializer serializer, CancellationToken cancellationToken = default)
176+
public async Task<T> GetDataAsync<T>(ObjectSerializer serializer = default, CancellationToken cancellationToken = default)
176177
{
177-
if (Data != null)
178+
if (Data != null && serializer != null)
178179
{
179180
throw new InvalidOperationException("Cannot pass in a custom deserializer if event was not created from CloudEvent.Parse(), " +
180181
"as event data should already be deserialized and the custom deserializer will not be used.");
181182
}
182-
return await GetDataInternal<T>(serializer, true, cancellationToken).ConfigureAwait(false);
183+
return await GetDataInternal<T>(serializer ?? s_jsonSerializer, true, cancellationToken).ConfigureAwait(false);
183184
}
184185

185186
/// <summary>
186187
/// Deserializes the event payload into a specified event type using the provided <see cref="ObjectSerializer"/>.
187188
/// </summary>
188189
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
189-
/// <param name="serializer"> Custom serializer used to deserialize the payload. </param>
190+
/// <param name="serializer"> A custom serializer used to deserialize the payload. If not provided, the
191+
/// <see cref="JsonObjectSerializer"/> will be used.</param>
190192
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
191193
/// <exception cref="InvalidOperationException"> Event was not created from CloudEvent.Parse() method. </exception>
192194
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
193195
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
194-
public T GetData<T>(ObjectSerializer serializer, CancellationToken cancellationToken = default)
196+
public T GetData<T>(ObjectSerializer serializer = default, CancellationToken cancellationToken = default)
195197
{
196-
if (Data != null)
198+
if (Data != null && serializer != null)
197199
{
198200
throw new InvalidOperationException("Cannot pass in a custom deserializer if event was not created from CloudEvent.Parse(), " +
199201
"as event data should already be deserialized and the custom deserializer will not be used.");
200202
}
201-
return GetDataInternal<T>(serializer, false, cancellationToken).EnsureCompleted();
203+
return GetDataInternal<T>(serializer ?? s_jsonSerializer, false, cancellationToken).EnsureCompleted();
202204
}
203205

204-
/// <summary>
205-
/// Deserializes the event payload into a specified event type using the provided <see cref="JsonObjectSerializer"/>.
206-
/// </summary>
207-
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
208-
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
209-
/// <exception cref="InvalidOperationException"> Event was not created from CloudEvent.Parse() method. </exception>
210-
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
211-
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
212-
public T GetData<T>(CancellationToken cancellationToken = default)
213-
=> GetDataInternal<T>(s_jsonSerializer, false, cancellationToken).EnsureCompleted();
214-
215206
private async Task<T> GetDataInternal<T>(ObjectSerializer serializer, bool async, CancellationToken cancellationToken = default)
216207
{
217208
Argument.AssertNotNull(serializer, nameof(serializer));

sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEvent.cs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System;
55
using System.Collections.Generic;
66
using System.IO;
7-
using System.Text;
87
using System.Text.Json;
98
using System.Threading;
109
using System.Threading.Tasks;
@@ -20,12 +19,12 @@ public class EventGridEvent
2019
{
2120
/// <summary> Initializes a new instance of <see cref="EventGridEvent"/>. </summary>
2221
/// <param name="subject"> A resource path relative to the topic path. </param>
23-
/// <param name="data"> Event data specific to the event type. </param>
2422
/// <param name="eventType"> The type of the event that occurred. For example, "Contoso.Items.ItemReceived". </param>
2523
/// <param name="dataVersion"> The schema version of the data object. </param>
24+
/// <param name="data"> Event data specific to the event type. </param>
2625
/// <param name="dataSerializationType">The type to use when serializing the data.
2726
/// If not specified, <see cref="object.GetType()"/> will be used on <paramref name="data"/>.</param>
28-
public EventGridEvent(object data, string subject, string eventType, string dataVersion, Type dataSerializationType = default)
27+
public EventGridEvent(string subject, string eventType, string dataVersion, object data, Type dataSerializationType = default)
2928
{
3029
Argument.AssertNotNull(subject, nameof(subject));
3130
Argument.AssertNotNull(data, nameof(data));
@@ -134,51 +133,42 @@ public static EventGridEvent[] Parse(string requestContent)
134133
/// Deserializes the event payload into a specified event type using the provided <see cref="ObjectSerializer"/>.
135134
/// </summary>
136135
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
137-
/// <param name="serializer"> Custom serializer used to deserialize the payload. </param>
136+
/// <param name="serializer"> A custom serializer used to deserialize the payload. If not provided, the
137+
/// <see cref="JsonObjectSerializer"/> will be used.</param>
138138
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
139139
/// <exception cref="InvalidOperationException"> Event was not created from EventGridEvent.Parse() method. </exception>
140140
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
141141
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
142-
public async Task<T> GetDataAsync<T>(ObjectSerializer serializer, CancellationToken cancellationToken = default)
142+
public async Task<T> GetDataAsync<T>(ObjectSerializer serializer = default, CancellationToken cancellationToken = default)
143143
{
144-
if (Data != null)
144+
if (Data != null && serializer != null)
145145
{
146146
throw new InvalidOperationException("Cannot pass in a custom deserializer if event was not created from EventGridEvent.Parse(), " +
147147
"as event data should already be deserialized and the custom deserializer will not be used.");
148148
}
149-
return await GetDataInternal<T>(serializer, true, cancellationToken).ConfigureAwait(false);
149+
return await GetDataInternal<T>(serializer ?? s_jsonSerializer, true, cancellationToken).ConfigureAwait(false);
150150
}
151151

152152
/// <summary>
153153
/// Deserializes the event payload into a specified event type using the provided <see cref="ObjectSerializer"/>.
154154
/// </summary>
155155
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
156-
/// <param name="serializer"> Custom serializer used to deserialize the payload. </param>
156+
/// <param name="serializer"> A custom serializer used to deserialize the payload. If not provided, the
157+
/// <see cref="JsonObjectSerializer"/> will be used.</param>
157158
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
158159
/// <exception cref="InvalidOperationException"> Event was not created from EventGridEvent.Parse() method. </exception>
159160
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
160161
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
161-
public T GetData<T>(ObjectSerializer serializer, CancellationToken cancellationToken = default)
162+
public T GetData<T>(ObjectSerializer serializer = default, CancellationToken cancellationToken = default)
162163
{
163-
if (Data != null)
164+
if (Data != null && serializer != null)
164165
{
165166
throw new InvalidOperationException("Cannot pass in a custom deserializer if event was not created from EventGridEvent.Parse(), " +
166167
"as event data should already be deserialized and the custom deserializer will not be used.");
167168
}
168-
return GetDataInternal<T>(serializer, false, cancellationToken).EnsureCompleted();
169+
return GetDataInternal<T>(serializer ?? s_jsonSerializer, false, cancellationToken).EnsureCompleted();
169170
}
170171

171-
/// <summary>
172-
/// Deserializes the event payload into a specified event type using the provided <see cref="JsonObjectSerializer"/>.
173-
/// </summary>
174-
/// <typeparam name="T"> Type of event to deserialize to. </typeparam>
175-
/// <param name="cancellationToken"> The cancellation token to use during deserialization. </param>
176-
/// <exception cref="InvalidOperationException"> Event was not created from EventGridEvent.Parse() method. </exception>
177-
/// <exception cref="InvalidCastException"> Event payload cannot be cast to the specified event type. </exception>
178-
/// <returns> Deserialized payload of the event, cast to the specified type. </returns>
179-
public T GetData<T>(CancellationToken cancellationToken = default)
180-
=> GetDataInternal<T>(s_jsonSerializer, false, cancellationToken).EnsureCompleted();
181-
182172
private async Task<T> GetDataInternal<T>(ObjectSerializer serializer, bool async, CancellationToken cancellationToken = default)
183173
{
184174
Argument.AssertNotNull(serializer, nameof(serializer));

sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridPublisherClient.cs

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,7 @@ public EventGridPublisherClient(Uri endpoint, AzureKeyCredential credential)
5050
{
5151
}
5252

53-
/// <summary>Initalizes a new instance of the <see cref="EventGridPublisherClient"/> class.</summary>
54-
/// <param name="endpoint">The topic endpoint. For example, "https://TOPIC-NAME.REGION-NAME-1.eventgrid.azure.net/api/events".</param>
55-
/// <param name="credential">The Shared Access Signature credential used to authenticate with the service.This signature
56-
/// can be constructed using <see cref="BuildSharedAccessSignature"/>.</param>
57-
public EventGridPublisherClient(Uri endpoint, AzureSasCredential credential)
58-
: this(endpoint, credential, new EventGridPublisherClientOptions())
59-
{
60-
}
61-
62-
/// <summary>Initalizes a new instance of the <see cref="EventGridPublisherClient"/> class.</summary>
53+
/// <summary>Initalizes a new instance of the <see cref="EventGridPublisherClient"/> class.</summary>
6354
/// <param name="endpoint">The topic endpoint. For example, "https://TOPIC-NAME.REGION-NAME-1.eventgrid.azure.net/api/events".</param>
6455
/// <param name="credential">The key credential used to authenticate with the service.</param>
6556
/// <param name="options">The set of options to use for configuring the client.</param>
@@ -137,9 +128,9 @@ private async Task<Response> SendCloudNativeCloudEventsInternalAsync(ReadOnlyMem
137128
/// </summary>
138129
/// <param name="endpoint">The topic endpoint. For example, "https://TOPIC-NAME.REGION-NAME-1.eventgrid.azure.net/api/events".</param>
139130
/// <param name="credential">The Shared Access Signature credential used to connect to Azure. This signature
140-
/// can be constructed using <see cref="BuildSharedAccessSignature"/>.</param>
131+
/// can be constructed using the <see cref="EventGridSasBuilder"/>.</param>
141132
/// <param name="options">The set of options to use for configuring the client.</param>
142-
public EventGridPublisherClient(Uri endpoint, AzureSasCredential credential, EventGridPublisherClientOptions options)
133+
public EventGridPublisherClient(Uri endpoint, AzureSasCredential credential, EventGridPublisherClientOptions options = default)
143134
{
144135
Argument.AssertNotNull(credential, nameof(credential));
145136
options ??= new EventGridPublisherClientOptions();
@@ -372,38 +363,6 @@ private async Task<Response> PublishCustomEventsInternal(IEnumerable<object> eve
372363
}
373364
}
374365

375-
/// <summary>
376-
/// Creates a SAS token for use with the Event Grid service.
377-
/// </summary>
378-
/// <param name="endpoint">The path for the event grid topic to which you're sending events. For example, "https://TOPIC-NAME.REGION-NAME.eventgrid.azure.net/eventGrid/api/events".</param>
379-
/// <param name="expirationUtc">Time at which the SAS token becomes invalid for authentication.</param>
380-
/// <param name="key">The key credential used to generate the token.</param>
381-
/// <param name="apiVersion">The service version to use when handling requests made with the SAS token.</param>
382-
/// <returns>The generated SAS token string.</returns>
383-
public static string BuildSharedAccessSignature(Uri endpoint, DateTimeOffset expirationUtc, AzureKeyCredential key, EventGridPublisherClientOptions.ServiceVersion apiVersion = EventGridPublisherClientOptions.LatestVersion)
384-
{
385-
const char Resource = 'r';
386-
const char Expiration = 'e';
387-
const char Signature = 's';
388-
389-
var uriBuilder = new RequestUriBuilder();
390-
uriBuilder.Reset(endpoint);
391-
uriBuilder.AppendQuery("api-version", apiVersion.GetVersionString(), true);
392-
string encodedResource = HttpUtility.UrlEncode(uriBuilder.ToString());
393-
var culture = CultureInfo.CreateSpecificCulture("en-US");
394-
var encodedExpirationUtc = HttpUtility.UrlEncode(expirationUtc.ToString(culture));
395-
396-
string unsignedSas = $"{Resource}={encodedResource}&{Expiration}={encodedExpirationUtc}";
397-
using (var hmac = new HMACSHA256(Convert.FromBase64String(key.Key)))
398-
{
399-
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(unsignedSas)));
400-
string encodedSignature = HttpUtility.UrlEncode(signature);
401-
string signedSas = $"{unsignedSas}&{Signature}={encodedSignature}";
402-
403-
return signedSas;
404-
}
405-
}
406-
407366
private JsonDocument SerializeObjectToJsonDocument(object data, Type type, CancellationToken cancellationToken)
408367
{
409368
using (MemoryStream stream = new MemoryStream())

0 commit comments

Comments
 (0)