This commit is contained in:
Родитель
f10d01c4a2
Коммит
67b642a42d
|
@ -7,11 +7,11 @@ using Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters;
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker
|
namespace Microsoft.Azure.Functions.Worker
|
||||||
{
|
{
|
||||||
[AllowConverterFallback(true)]
|
|
||||||
[InputConverter(typeof(EventGridCloudEventConverter))]
|
[InputConverter(typeof(EventGridCloudEventConverter))]
|
||||||
[InputConverter(typeof(EventGridEventConverter))]
|
[InputConverter(typeof(EventGridEventConverter))]
|
||||||
[InputConverter(typeof(EventGridBinaryDataConverter))]
|
[InputConverter(typeof(EventGridBinaryDataConverter))]
|
||||||
[InputConverter(typeof(EventGridStringArrayConverter))]
|
[InputConverter(typeof(EventGridStringArrayConverter))]
|
||||||
|
[ConverterFallbackBehavior(ConverterFallbackBehavior.Default)]
|
||||||
public sealed class EventGridTriggerAttribute : TriggerBindingAttribute
|
public sealed class EventGridTriggerAttribute : TriggerBindingAttribute
|
||||||
{
|
{
|
||||||
private bool _isBatched = false;
|
private bool _isBatched = false;
|
||||||
|
|
|
@ -3,76 +3,42 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converter to bind to BinaryData or BinaryData[] parameter.
|
/// Converter to bind to <see cref="BinaryData" /> or <see cref="BinaryData[]" /> type parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SupportedConverterType(typeof(BinaryData))]
|
[SupportedTargetType(typeof(BinaryData))]
|
||||||
[SupportedConverterType(typeof(BinaryData[]))]
|
[SupportedTargetType(typeof(BinaryData[]))]
|
||||||
internal class EventGridBinaryDataConverter : IInputConverter
|
internal class EventGridBinaryDataConverter : EventGridConverterBase
|
||||||
{
|
{
|
||||||
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
|
protected override ConversionResult ConvertCore(Type targetType, string json)
|
||||||
{
|
{
|
||||||
try
|
ConversionResult result = targetType switch
|
||||||
{
|
{
|
||||||
if (context is null)
|
Type t when t == typeof(BinaryData) => ConversionResult.Success(BinaryData.FromString(json)),
|
||||||
{
|
Type t when t == typeof(BinaryData[]) => ConversionResult.Success(ConvertToBinaryDataArray(json)),
|
||||||
throw new ArgumentNullException(nameof(context));
|
_ => ConversionResult.Failed(new InvalidOperationException($"'{targetType.Name}' is not supported by this converter."))
|
||||||
}
|
};
|
||||||
|
|
||||||
if (context.Source is not string contextSource)
|
return result;
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException("Context source must be a non-null string. Current type of context source is " + context?.Source?.GetType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetType = context.TargetType;
|
|
||||||
|
|
||||||
switch (targetType)
|
|
||||||
{
|
|
||||||
case Type t when t == typeof(BinaryData):
|
|
||||||
return new(ConversionResult.Success((BinaryData.FromString(contextSource))));
|
|
||||||
case Type t when t == typeof(BinaryData[]):
|
|
||||||
return new(ConversionResult.Success(ConvertToBinaryDataArray(contextSource)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (JsonException ex)
|
|
||||||
{
|
|
||||||
string msg = String.Format(CultureInfo.CurrentCulture,
|
|
||||||
@"Binding parameters to complex objects uses JSON serialization.
|
|
||||||
1. Bind the parameter type as 'string' instead to get the raw values and avoid JSON deserialization, or
|
|
||||||
2. Change the event payload to be valid json.");
|
|
||||||
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException(msg, ex)));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(ex));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new(ConversionResult.Unhandled());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryData?[]? ConvertToBinaryDataArray(string contextSource)
|
private BinaryData[] ConvertToBinaryDataArray(string json)
|
||||||
{
|
{
|
||||||
var jsonData = JsonSerializer.Deserialize(contextSource, typeof(List<object>)) as List<object>;
|
var data = JsonSerializer.Deserialize<List<object>>(json);
|
||||||
List<BinaryData?> binaryDataList = new List<BinaryData?>();
|
var result = data.Select(item => BinaryData.FromString(item.ToString())).ToArray();
|
||||||
|
|
||||||
if (jsonData is not null)
|
if (result is null)
|
||||||
{
|
{
|
||||||
foreach (var item in jsonData)
|
throw new Exception("Unable to convert to BinaryData[].");
|
||||||
{
|
|
||||||
var binaryData = item == null? null: BinaryData.FromString(item.ToString());
|
|
||||||
binaryDataList.Add(binaryData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return binaryDataList.ToArray();
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,32 +2,29 @@
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Text.Json;
|
||||||
using Azure.Messaging;
|
using Azure.Messaging;
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converter to bind to CloudEvent or CloudEvent[] parameter.
|
/// Converter to bind to <see cref="CloudEvent" /> or <see cref="CloudEvent[]" /> type parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SupportedConverterType(typeof(CloudEvent))]
|
[SupportedTargetType(typeof(CloudEvent))]
|
||||||
[SupportedConverterType(typeof(CloudEvent[]))]
|
[SupportedTargetType(typeof(CloudEvent[]))]
|
||||||
internal class EventGridCloudEventConverter: IInputConverter
|
internal class EventGridCloudEventConverter: EventGridConverterBase
|
||||||
{
|
{
|
||||||
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
|
protected override ConversionResult ConvertCore(Type targetType, string json)
|
||||||
{
|
{
|
||||||
if (context is null)
|
var cloudEvent = JsonSerializer.Deserialize(json, targetType);
|
||||||
|
|
||||||
|
if (cloudEvent is null)
|
||||||
{
|
{
|
||||||
return new(ConversionResult.Failed(new ArgumentNullException(nameof(context))));
|
return ConversionResult.Failed(new Exception("Unable to convert to CloudEvent."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.TargetType != typeof(CloudEvent) && context.TargetType != typeof(CloudEvent[]))
|
return ConversionResult.Success(cloudEvent);
|
||||||
{
|
|
||||||
return new(ConversionResult.Unhandled());
|
|
||||||
}
|
|
||||||
|
|
||||||
return EventGridHelper.DeserializeToTargetType(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
|
|
||||||
|
namespace Microsoft.Azure.Functions.Worker
|
||||||
|
{
|
||||||
|
internal abstract class EventGridConverterBase : IInputConverter
|
||||||
|
{
|
||||||
|
public EventGridConverterBase() { }
|
||||||
|
|
||||||
|
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
|
||||||
|
{
|
||||||
|
if (context is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (context.Source is not string json)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Context source must be a non-null string");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = ConvertCore(context.TargetType, json);
|
||||||
|
return new ValueTask<ConversionResult>(result);
|
||||||
|
}
|
||||||
|
catch (JsonException ex)
|
||||||
|
{
|
||||||
|
string msg = String.Format(CultureInfo.CurrentCulture,
|
||||||
|
@"Binding parameters to complex objects uses JSON serialization.
|
||||||
|
1. Bind the parameter type as 'string' instead to get the raw values and avoid JSON deserialization, or
|
||||||
|
2. Change the queue payload to be valid json.");
|
||||||
|
|
||||||
|
return new ValueTask<ConversionResult>(ConversionResult.Failed(new InvalidOperationException(msg, ex)));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ValueTask<ConversionResult>(ConversionResult.Failed(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ConversionResult ConvertCore(Type targetType, string json);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,32 +2,29 @@
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Text.Json;
|
||||||
using Azure.Messaging.EventGrid;
|
using Azure.Messaging.EventGrid;
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converter to bind to EventGridEvent or EventGridEvent[] parameter.
|
/// Converter to bind to <see cref="EventGridEvent" /> or <see cref="EventGridEvent[]" /> type parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SupportedConverterType(typeof(EventGridEvent))]
|
[SupportedTargetType(typeof(EventGridEvent))]
|
||||||
[SupportedConverterType(typeof(EventGridEvent[]))]
|
[SupportedTargetType(typeof(EventGridEvent[]))]
|
||||||
internal class EventGridEventConverter : IInputConverter
|
internal class EventGridEventConverter : EventGridConverterBase
|
||||||
{
|
{
|
||||||
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
|
protected override ConversionResult ConvertCore(Type targetType, string json)
|
||||||
{
|
{
|
||||||
if (context is null)
|
var eventGridEvent = JsonSerializer.Deserialize(json, targetType);
|
||||||
|
|
||||||
|
if (eventGridEvent is null)
|
||||||
{
|
{
|
||||||
return new(ConversionResult.Failed(new ArgumentNullException(nameof(context))));
|
return ConversionResult.Failed(new Exception("Unable to convert to EventGridEvent."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context?.TargetType != typeof(EventGridEvent) && context?.TargetType != typeof(EventGridEvent[]))
|
return ConversionResult.Success(eventGridEvent);
|
||||||
{
|
|
||||||
return new(ConversionResult.Unhandled());
|
|
||||||
}
|
|
||||||
|
|
||||||
return EventGridHelper.DeserializeToTargetType(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
|
||||||
{
|
|
||||||
internal static class EventGridHelper
|
|
||||||
{
|
|
||||||
internal static ValueTask<ConversionResult> DeserializeToTargetType(ConverterContext context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (context.Source is not string contextSource)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException("Context source must be a non-null string. Current type of context source is " + context?.Source?.GetType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetType = context.TargetType;
|
|
||||||
var item = JsonSerializer.Deserialize(contextSource, targetType);
|
|
||||||
return new(ConversionResult.Success(item));
|
|
||||||
}
|
|
||||||
catch (JsonException ex)
|
|
||||||
{
|
|
||||||
string msg = String.Format(CultureInfo.CurrentCulture,
|
|
||||||
@"Binding parameters to complex objects uses JSON serialization.
|
|
||||||
1. Bind the parameter type as 'string' instead to get the raw values and avoid JSON deserialization, or
|
|
||||||
2. Change the event payload to be valid json.");
|
|
||||||
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException(msg, ex)));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(ex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,62 +3,29 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
|
|
||||||
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
namespace Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converter to bind to string[] parameter.
|
/// Converter to bind to <see cref="string[]" /> type parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SupportedConverterType(typeof(string[]))]
|
[SupportedTargetType(typeof(string[]))]
|
||||||
internal class EventGridStringArrayConverter : IInputConverter
|
internal class EventGridStringArrayConverter : EventGridConverterBase
|
||||||
{
|
{
|
||||||
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
|
protected override ConversionResult ConvertCore(Type targetType, string json)
|
||||||
{
|
{
|
||||||
try
|
var jsonData = JsonSerializer.Deserialize<List<object>>(json);
|
||||||
|
var result = jsonData.Select(d => d.ToString()).ToArray();
|
||||||
|
|
||||||
|
if (result is null)
|
||||||
{
|
{
|
||||||
if (context is null)
|
return ConversionResult.Failed(new Exception("Unable to convert to string[]."));
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.TargetType != typeof(string[]))
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Unhandled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.Source is not string contextSource)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException("Context source must be a non-null string. Current type of context source is " + context?.Source?.GetType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
var jsonData = JsonSerializer.Deserialize(contextSource, typeof(List<object>)) as List<object>;
|
|
||||||
List<string?> stringList = new List<string?>();
|
|
||||||
|
|
||||||
if (jsonData is not null)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Success(jsonData.Select(d => d?.ToString()).ToArray()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (JsonException ex)
|
|
||||||
{
|
|
||||||
string msg = String.Format(CultureInfo.CurrentCulture,
|
|
||||||
@"Binding parameters to complex objects uses JSON serialization.
|
|
||||||
1. Bind the parameter type as 'string' instead to get the raw values and avoid JSON deserialization, or
|
|
||||||
2. Change the event payload to be valid json.");
|
|
||||||
|
|
||||||
return new(ConversionResult.Failed(new InvalidOperationException(msg, ex)));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new(ConversionResult.Failed(ex));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(ConversionResult.Unhandled());
|
return ConversionResult.Success(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
// Default URL for triggering event grid function in the local environment.
|
||||||
|
// http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname}
|
||||||
|
|
||||||
|
using Azure.Messaging;
|
||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace SampleApp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Samples demonstrating binding to the <see cref="CloudEvent"/> type.
|
||||||
|
/// </summary>
|
||||||
|
public class CloudEventSamples
|
||||||
|
{
|
||||||
|
private readonly ILogger<CloudEventSamples> _logger;
|
||||||
|
|
||||||
|
public CloudEventSamples(ILogger<CloudEventSamples> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function demonstrates binding to a single <see cref="CloudEvent"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Function(nameof(CloudEventFunction))]
|
||||||
|
public void CloudEventFunction([EventGridTrigger] CloudEvent cloudEvent)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Event type: {type}, Event subject: {subject}", cloudEvent.Type, cloudEvent.Subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function demonstrates binding to an array of <see cref="CloudEvent"/>.
|
||||||
|
/// Note that when doing so, you must also set the <see cref="EventGridTriggerAttribute.IsBatched"/> property
|
||||||
|
/// to <value>true</value>.
|
||||||
|
/// </summary>
|
||||||
|
[Function(nameof(CloudEventBatchFunction))]
|
||||||
|
public void CloudEventBatchFunction([EventGridTrigger(IsBatched = true)] CloudEvent[] cloudEvents)
|
||||||
|
{
|
||||||
|
foreach (var cloudEvent in cloudEvents)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Event type: {type}, Event subject: {subject}", cloudEvent.Type, cloudEvent.Subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
// Default URL for triggering event grid function in the local environment.
|
||||||
|
// http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname}
|
||||||
|
|
||||||
|
using Azure.Messaging.EventGrid;
|
||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace SampleApp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Samples demonstrating binding to the <see cref="EventGridEvent"/> type.
|
||||||
|
/// </summary>
|
||||||
|
public class EventGridEventSamples
|
||||||
|
{
|
||||||
|
private readonly ILogger<EventGridEventSamples> _logger;
|
||||||
|
|
||||||
|
public EventGridEventSamples(ILogger<EventGridEventSamples> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function demonstrates binding to a single <see cref="EventGridEvent"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Function(nameof(EventGridEventFunction))]
|
||||||
|
public void EventGridEventFunction([EventGridTrigger] EventGridEvent eventGridEvent)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Event received: {event}", eventGridEvent.Data.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function demonstrates binding to an array of <see cref="EventGridEvent"/>.
|
||||||
|
/// Note that when doing so, you must also set the <see cref="EventGridTriggerAttribute.IsBatched"/> property
|
||||||
|
/// to <value>true</value>.
|
||||||
|
/// </summary>
|
||||||
|
[Function(nameof(EventGridEventBatchFunction))]
|
||||||
|
public void EventGridEventBatchFunction([EventGridTrigger(IsBatched = true)] EventGridEvent[] eventGridEvents)
|
||||||
|
{
|
||||||
|
foreach (var eventGridEvent in eventGridEvents)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Event received: {event}", eventGridEvent.Data.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,105 +0,0 @@
|
||||||
// Default URL for triggering event grid function in the local environment.
|
|
||||||
// http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname}
|
|
||||||
using System;
|
|
||||||
using Azure.Messaging;
|
|
||||||
using Azure.Messaging.EventGrid;
|
|
||||||
using Microsoft.Azure.Functions.Worker;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace WorkerBindingSamples.EventGrid
|
|
||||||
{
|
|
||||||
public class EventGridTriggerBindingSamples
|
|
||||||
{
|
|
||||||
private readonly ILogger _logger;
|
|
||||||
|
|
||||||
public EventGridTriggerBindingSamples(ILoggerFactory loggerFactory)
|
|
||||||
{
|
|
||||||
_logger = loggerFactory.CreateLogger<EventGridTriggerBindingSamples>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("MyEventFunction")]
|
|
||||||
public void MyEventFunction([EventGridTrigger] MyEvent input)
|
|
||||||
{
|
|
||||||
_logger.LogInformation(input.Data?.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("CloudEventFunction")]
|
|
||||||
public void CloudEventFunction([EventGridTrigger] CloudEvent input)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Event type: {type}, Event subject: {subject}", input.Type, input.Subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("MultipleCloudEventFunction")]
|
|
||||||
public void MultipleCloudEventFunction([EventGridTrigger(IsBatched = true)] CloudEvent[] input)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < input.Length; i++)
|
|
||||||
{
|
|
||||||
var cloudEvent = input[i];
|
|
||||||
_logger.LogInformation("Event type: {type}, Event subject: {subject}", cloudEvent.Type, cloudEvent.Subject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("EventGridEvent")]
|
|
||||||
public void EventGridEvent([EventGridTrigger] EventGridEvent input)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Event received: {event}", input.Data.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("EventGridEventArray")]
|
|
||||||
public void EventGridEventArray([EventGridTrigger(IsBatched = true)] EventGridEvent[] input)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < input.Length; i++)
|
|
||||||
{
|
|
||||||
var eventGridEvent = input[i];
|
|
||||||
_logger.LogInformation("Event received: {event}", eventGridEvent.Data.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("BinaryDataEvent")]
|
|
||||||
public void BinaryDataEvent([EventGridTrigger] BinaryData input)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Event received: {event}", input.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("BinaryDataArrayEvent")]
|
|
||||||
public void BinaryDataArrayEvent([EventGridTrigger(IsBatched = true)] BinaryData[] input)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < input.Length; i++)
|
|
||||||
{
|
|
||||||
var binaryDataEvent = input[i];
|
|
||||||
_logger.LogInformation("Event received: {event}", binaryDataEvent.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("StringArrayEvent")]
|
|
||||||
public void StringArrayEvent([EventGridTrigger(IsBatched = true)] string[] input)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < input.Length; i++)
|
|
||||||
{
|
|
||||||
var stringEventGrid = input[i];
|
|
||||||
_logger.LogInformation("Event received: {event}", stringEventGrid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Function("StringEvent")]
|
|
||||||
public void StringEvent([EventGridTrigger] string input)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Event received: {event}", input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MyEvent
|
|
||||||
{
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
public string? Topic { get; set; }
|
|
||||||
|
|
||||||
public string? Subject { get; set; }
|
|
||||||
|
|
||||||
public string? EventType { get; set; }
|
|
||||||
|
|
||||||
public DateTime EventTime { get; set; }
|
|
||||||
|
|
||||||
public object? Data { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -314,5 +314,77 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CloudEventFunction",
|
||||||
|
"scriptFile": "WorkerBindingSamples.dll",
|
||||||
|
"entryPoint": "SampleApp.CloudEventSamples.CloudEventFunction",
|
||||||
|
"language": "dotnet-isolated",
|
||||||
|
"properties": {
|
||||||
|
"IsCodeless": false
|
||||||
|
},
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "cloudEvent",
|
||||||
|
"direction": "In",
|
||||||
|
"type": "eventGridTrigger",
|
||||||
|
"cardinality": "One",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CloudEventBatchFunction",
|
||||||
|
"scriptFile": "WorkerBindingSamples.dll",
|
||||||
|
"entryPoint": "SampleApp.CloudEventSamples.CloudEventBatchFunction",
|
||||||
|
"language": "dotnet-isolated",
|
||||||
|
"properties": {
|
||||||
|
"IsCodeless": false
|
||||||
|
},
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "cloudEvents",
|
||||||
|
"direction": "In",
|
||||||
|
"type": "eventGridTrigger",
|
||||||
|
"cardinality": "Many",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EventGridEventFunction",
|
||||||
|
"scriptFile": "WorkerBindingSamples.dll",
|
||||||
|
"entryPoint": "SampleApp.EventGridEventSamples.EventGridEventFunction",
|
||||||
|
"language": "dotnet-isolated",
|
||||||
|
"properties": {
|
||||||
|
"IsCodeless": false
|
||||||
|
},
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "eventGridEvent",
|
||||||
|
"direction": "In",
|
||||||
|
"type": "eventGridTrigger",
|
||||||
|
"cardinality": "One",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EventGridEventBatchFunction",
|
||||||
|
"scriptFile": "WorkerBindingSamples.dll",
|
||||||
|
"entryPoint": "SampleApp.EventGridEventSamples.EventGridEventBatchFunction",
|
||||||
|
"language": "dotnet-isolated",
|
||||||
|
"properties": {
|
||||||
|
"IsCodeless": false
|
||||||
|
},
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "eventGridEvents",
|
||||||
|
"direction": "In",
|
||||||
|
"type": "eventGridTrigger",
|
||||||
|
"cardinality": "Many",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -20,19 +20,41 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_SourceAsObject_ReturnsUnhandled()
|
public async Task ConvertAsync_Source_IsNotAString_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(BinaryData), new object());
|
var context = new TestConverterContext(typeof(BinaryData), new object());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Equal("Context source must be a non-null string", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_UnsupportedTargetType_ReturnsFailed()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(string), "");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Success()
|
public async Task ConvertAsync_InvalidJson_ThrowsJsonException_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(BinaryData), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
var context = new TestConverterContext(typeof(BinaryData[]), @"{""invalid"" :json""}");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Contains("Binding parameters to complex objects uses JSON serialization", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_SingleBinaryData_ReturnsSuccess()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(BinaryData), EventGridTestHelper.GetEventGridJsonData());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -41,28 +63,9 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Unhandled_For_Unsupported_Type()
|
public async Task ConvertAsync_BinaryDataArray_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
var context = new TestConverterContext(typeof(BinaryData[]), EventGridTestHelper.GetEventGridJsonDataArray());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_SourceAsObject_BinaryDataCollectible_ReturnsUnhandled()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(BinaryData[]), new object());
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_BinaryDataCollectible_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(BinaryData[]), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -72,19 +75,9 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_BinaryDataCollectible_Returns_Unhandled_For_Unsupported_Type()
|
public async Task ConvertAsync_BinaryDataArray_SingleElement_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
var context = new TestConverterContext(typeof(BinaryData[]), $"[{EventGridTestHelper.GetEventGridJsonData()}]");
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_SingleElement_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(BinaryData[]), "[{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Azure.Messaging;
|
using Azure.Messaging;
|
||||||
using Azure.Messaging.EventGrid;
|
|
||||||
using Microsoft.Azure.Functions.Worker;
|
using Microsoft.Azure.Functions.Worker;
|
||||||
using Microsoft.Azure.Functions.Worker.Converters;
|
using Microsoft.Azure.Functions.Worker.Converters;
|
||||||
using Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters;
|
using Microsoft.Azure.Functions.Worker.Extensions.EventGrid.TypeConverters;
|
||||||
|
@ -21,24 +19,45 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
public EventGridCloudEventConverterTests()
|
public EventGridCloudEventConverterTests()
|
||||||
{
|
{
|
||||||
var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { }).Build();
|
var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { }).Build();
|
||||||
|
|
||||||
_eventGridConverter = new EventGridCloudEventConverter();
|
_eventGridConverter = new EventGridCloudEventConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_SourceAsObject_ReturnsFailed()
|
public async Task ConvertAsync_Source_IsNotAString_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(CloudEvent), new object());
|
var context = new TestConverterContext(typeof(CloudEvent), new object());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Equal("Context source must be a non-null string", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_UnsupportedTargetType_ReturnsFailed()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(string), "");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Success()
|
public async Task ConvertAsync_InvalidJson_ThrowsJsonException_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(CloudEvent), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
var context = new TestConverterContext(typeof(CloudEvent[]), @"{""invalid"" :json""}");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Contains("Binding parameters to complex objects uses JSON serialization", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_SingleCloudEvent_ReturnsSuccess()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(CloudEvent), EventGridTestHelper.GetEventGridJsonData());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -46,30 +65,11 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
Assert.True(conversionResult.Value is CloudEvent);
|
Assert.True(conversionResult.Value is CloudEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_Returns_Unhandled_For_Unsupported_Type()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(string), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_SourceAsObject_CloudEventCollectible_ReturnsFailed()
|
public async Task ConvertAsync_CloudEventArray_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(CloudEvent[]), new object());
|
var context = new TestConverterContext(typeof(CloudEvent[]), EventGridTestHelper.GetEventGridJsonDataArray());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_CloudEventCollectible_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(CloudEvent[]), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -79,19 +79,9 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_CloudEventCollectible_Returns_Unhandled_For_Unsupported_Type()
|
public async Task ConvertAsync_CloudEventArray_SingleElement_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
var context = new TestConverterContext(typeof(CloudEvent[]), $"[{EventGridTestHelper.GetEventGridJsonData()}]");
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_SingleElement_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(CloudEvent[]), "[{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Azure.Messaging.EventGrid;
|
using Azure.Messaging.EventGrid;
|
||||||
using Microsoft.Azure.Functions.Worker;
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
@ -25,19 +24,52 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_SourceAsObject_ReturnsUnhandled()
|
public async Task ConvertAsync_Source_IsNotAString_ReturnsUnhandled()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent), new object());
|
var context = new TestConverterContext(typeof(EventGridEvent), new object());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Equal("Context source must be a non-null string", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_UnsupportedTargetType_ReturnsFailed()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(string), "");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Success()
|
public async Task ConvertAsync_InvalidJson_ThrowsJsonException_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent), "{\"id\":\"'1\",\"topic\":\"hello\",\"subject\":\"yoursubject\",\"eventType\":\"yourEventType\",\"eventTime\":\"2018-01-23T17:02:19.6069787Z\",\"data\":\"test\",\"dataVersion\":\"test\"}");
|
var context = new TestConverterContext(typeof(EventGridEvent), @"{""invalid"" :json""}");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Contains("Binding parameters to complex objects uses JSON serialization", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_InvalidData_Throws_ReturnsFailed()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(EventGridEvent), EventGridTestHelper.GetEventGridJsonData());
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Equal("Value cannot be null. (Parameter 'EventType')", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_SingleEventGridEvent_ReturnsSuccess()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(EventGridEvent), EventGridTestHelper.GetEventGridEventJsonData());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -46,39 +78,9 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Unhandled_For_Unsupported_Type()
|
public async Task ConvertAsync_EventGridArray_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string), "{\"id\":\"'1\",\"topic\":\"hello\",\"subject\":\"yoursubject\",\"eventType\":\"yourEventType\",\"eventTime\":\"2018-01-23T17:02:19.6069787Z\",\"data\":\"test\",\"dataVersion\":\"test\"}");
|
var context = new TestConverterContext(typeof(EventGridEvent[]), EventGridTestHelper.GetEventGridEventJsonDataArray());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_Returns_Failed_Bad_Source()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync__EventGridCollectible_SourceAsObject_ReturnsUnhandled()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent[]), new object());
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync__EventGridCollectible_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent[]), "[{\"id\":\"'1\",\"topic\":\"hello\",\"subject\":\"yoursubject\",\"eventType\":\"yourEventType\",\"eventTime\":\"2018-01-23T17:02:19.6069787Z\",\"data\":\"test\",\"dataVersion\":\"test\"},{\"id\":\"'1\",\"topic\":\"hello\",\"subject\":\"yoursubject\",\"eventType\":\"yourEventType\",\"eventTime\":\"2018-01-23T17:02:19.6069787Z\",\"data\":\"lmao\",\"dataVersion\":\"test\"}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -86,25 +88,5 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
Assert.True(conversionResult.Value is EventGridEvent[]);
|
Assert.True(conversionResult.Value is EventGridEvent[]);
|
||||||
Assert.Equal(2, ((EventGridEvent[])conversionResult.Value).Length);
|
Assert.Equal(2, ((EventGridEvent[])conversionResult.Value).Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_EventGridCollectible_Returns_Unhandled_For_Unsupported_Type()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(string), "{\"id\":\"'1\",\"topic\":\"hello\",\"subject\":\"yoursubject\",\"eventType\":\"yourEventType\",\"eventTime\":\"2018-01-23T17:02:19.6069787Z\",\"data\":\"test\",\"dataVersion\":\"test\"}");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync__EventGridCollectible_Returns_Failed_Bad_Source()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(EventGridEvent[]), "{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,41 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_SourceAsObject_ReturnsUnhandled()
|
public async Task ConvertAsync_Source_IsNotAString_ReturnsUnhandled()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string[]), new object());
|
var context = new TestConverterContext(typeof(string[]), new object());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Equal("Context source must be a non-null string", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_UnsupportedTargetType_ReturnsFailed()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(byte[]), "");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Success()
|
public async Task ConvertAsync_InvalidJson_ThrowsJsonException_ReturnsFailed()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string[]), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
var context = new TestConverterContext(typeof(string[]), @"{""invalid"" :json""}");
|
||||||
|
|
||||||
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
Assert.Equal(ConversionStatus.Failed, conversionResult.Status);
|
||||||
|
Assert.Contains("Binding parameters to complex objects uses JSON serialization", conversionResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConvertAsync_StringArray_ReturnsSuccess()
|
||||||
|
{
|
||||||
|
var context = new TestConverterContext(typeof(string[]), EventGridTestHelper.GetEventGridJsonDataArray());
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
@ -41,19 +63,9 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.EventGrid
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ConvertAsync_Returns_Unhandled_For_Unsupported_Type()
|
public async Task ConvertAsync_StringArray_SingleElement_Returns_Success()
|
||||||
{
|
{
|
||||||
var context = new TestConverterContext(typeof(string), "[{\"specversion\":\"1.0\",\"id\":\"b85d631a-101e-005a-02f2-cee7aa06f148\",\"type\":\"zohan.music.request\",\"source\":\"https://zohan.dev/music/\",\"subject\":\"zohan/music/requests/4322\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"Gerardo\",\"song\":\"Rico Suave\"}},{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"life is very lit\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"life is lit\"}}]");
|
var context = new TestConverterContext(typeof(string[]), $"[{EventGridTestHelper.GetEventGridJsonData()}]");
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
|
||||||
|
|
||||||
Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ConvertAsync_SingleElement_Returns_Success()
|
|
||||||
{
|
|
||||||
var context = new TestConverterContext(typeof(string[]), "[{\"specversion\":\"1.0\",\"id\":\"2947780a-356b-c5a5-feb4-f5261fb2f155\",\"type\":\"test\",\"source\":\"moo\",\"subject\":\"lol test\",\"time\":\"2020-09-14T10:00:00Z\",\"data\":{\"artist\":\"wooo\",\"song\":\"some song\"}}]");
|
|
||||||
|
|
||||||
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
var conversionResult = await _eventGridConverter.ConvertAsync(context);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Microsoft.Azure.Functions.Worker.Grpc.Messages;
|
||||||
|
|
||||||
|
namespace Microsoft.Azure.Functions.Worker.Extensions.Tests
|
||||||
|
{
|
||||||
|
internal static class EventGridTestHelper
|
||||||
|
{
|
||||||
|
public static string GetEventGridJsonData(string id = "2947780a-356b-c5a5-feb4-f5261fb2f155", string song = "Vampire")
|
||||||
|
{
|
||||||
|
return $@"{{
|
||||||
|
""specversion"" : ""1.0"",
|
||||||
|
""id"" : ""{id}"",
|
||||||
|
""type"" : ""UnitTestData"",
|
||||||
|
""source"" : ""UnitTest"",
|
||||||
|
""subject"" : ""Song"",
|
||||||
|
""time"" : ""2020-09-14T10:00:00Z"",
|
||||||
|
""data"" : {{ ""artist"":""Olivia Rodrigo"",""song"":""{song}"" }}
|
||||||
|
}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetEventGridJsonDataArray()
|
||||||
|
{
|
||||||
|
return $@"[
|
||||||
|
{GetEventGridJsonData("2947780a-356b-c5a5-feb4-f5261fb2f155", "Driver's License")},
|
||||||
|
{GetEventGridJsonData("b85d631a-101e-005a-02f2-cee7aa06f148", "Deja Vu")}
|
||||||
|
]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetEventGridEventJsonData(string id = "2947780a-356b-c5a5-feb4-f5261fb2f155", string song = "Vampire")
|
||||||
|
{
|
||||||
|
return $@"{{
|
||||||
|
""id"" : ""{id}"",
|
||||||
|
""topic"" : ""UnitTestData"",
|
||||||
|
""subject"" : ""Song"",
|
||||||
|
""eventType"" : ""MyEvent"",
|
||||||
|
""eventTime"" : ""2020-09-14T10:00:00Z"",
|
||||||
|
""data"" : {{ ""artist"":""Olivia Rodrigo"",""song"":""{song}"" }},
|
||||||
|
""dataVersion"" : ""1.0""
|
||||||
|
}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetEventGridEventJsonDataArray()
|
||||||
|
{
|
||||||
|
return $@"[
|
||||||
|
{GetEventGridEventJsonData("2947780a-356b-c5a5-feb4-f5261fb2f155", "Driver's License")},
|
||||||
|
{GetEventGridEventJsonData("b85d631a-101e-005a-02f2-cee7aa06f148", "Deja Vu")}
|
||||||
|
]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче