public async Task BindAsync_HttpRequestMessage_FromRequestBody() { ParameterInfo parameterInfo = GetType().GetMethod("TestHttpRequestMessageFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); // we intentionally do not send a content type on the request // to ensure that we can still extract binding data in such cases JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://functions/myfunc?code=abc123", null, requestBody.ToString()); request.ContentType = "application/json"; FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(4, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); HttpRequestMessage result = (HttpRequestMessage)(await triggerData.ValueProvider.GetValueAsync()); Assert.NotNull(result); var contentResult = await result.Content.ReadAsAsync <JObject>(); Assert.Equal("Mathew Charles", contentResult["Name"]); }
public async Task BindAsync_Poco_FromRouteParameters() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://functions/myfunc"); Dictionary <string, object> routeData = new Dictionary <string, object> { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; request.HttpContext.Items.Add(HttpExtensionConstants.AzureWebJobsHttpRouteDataKey, routeData); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(4, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco testPoco = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); }
public async Task BindAsync_Poco_MergedBindingData() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunctionEx").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Phone", "(425) 555-6666" } }; var headers = new HeaderDictionary(); headers.Add("Content-Type", "application/json"); HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://functions/myfunc?code=abc123&Age=25", headers, requestBody.ToString()); var services = new ServiceCollection(); services.AddOptions(); services.AddSingleton(Options.Create(new MvcOptions())); var formatter = new Mock <IInputFormatter>(); formatter.Setup(f => f.ReadAsync(It.IsAny <InputFormatterContext>())) .ReturnsAsync((InputFormatterContext c) => { TextReader reader = c.ReaderFactory(c.HttpContext.Request.Body, Encoding.UTF8); JsonSerializer serializer = new JsonSerializer(); object result = serializer.Deserialize(reader, c.Metadata.ModelType); return(InputFormatterResult.Success(result)); }); services.AddMvcCore(o => o.InputFormatters.Add(formatter.Object)); request.HttpContext.RequestServices = services.BuildServiceProvider(); Dictionary <string, object> routeData = new Dictionary <string, object> { { "Location", "Seattle" } }; request.HttpContext.Items.Add(HttpExtensionConstants.AzureWebJobsHttpRouteDataKey, routeData); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(8, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); Assert.Equal("(425) 555-6666", triggerData.BindingData["Phone"]); Assert.Equal("25", triggerData.BindingData["Age"]); TestPocoEx testPoco = (TestPocoEx)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); Assert.Equal("(425) 555-6666", testPoco.Phone); Assert.Equal(25, testPoco.Age); }
public async Task BindAsync_Poco_WebHookData() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/myfunc?code=abc123"); TestPoco testPoco = new TestPoco { Name = "Mathew Charles", Location = "Seattle" }; request.Properties.Add(ScriptConstants.AzureFunctionsWebHookDataKey, testPoco); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco result = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Same(testPoco, result); }
public async Task BindAsync_Poco_FromRequestBody() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/myfunc?code=abc123"); JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; request.Content = new StringContent(requestBody.ToString()); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco testPoco = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); }
public async Task BindAsync_HttpRequestMessage_FromRequestBody() { ParameterInfo parameterInfo = GetType().GetMethod("TestHttpRequestMessageFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); // we intentionally do not send a content type on the request // to ensure that we can still extract binding data in such cases HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/myfunc?code=abc123"); JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; request.Content = new StringContent(requestBody.ToString()); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); HttpRequestMessage result = (HttpRequestMessage)(await triggerData.ValueProvider.GetValueAsync()); Assert.Same(request, result); }
public async Task BindAsync_Poco_FromRouteParameters() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://functions/myfunc"); Dictionary <string, object> routeData = new Dictionary <string, object> { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; request.Properties.Add(ScriptConstants.AzureFunctionsHttpRouteDataKey, routeData); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco testPoco = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); }
public async Task BindAsync_Poco_WebHookData() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://functions/myfunc?code=abc123"); TestPoco testPoco = new TestPoco { Name = "Mathew Charles", Location = "Seattle" }; request.HttpContext.Items.Add(HttpExtensionConstants.AzureWebJobsWebHookDataKey, testPoco); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(5, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco result = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Same(testPoco, result); }
public IServiceProvider GetServiceProvider(FunctionBindingContext context) { var scope = Scope.GetOrAdd(context.FunctionInstanceId, (id) => { return(_serviceProvider.CreateScope()); }); return(scope.ServiceProvider); }
internal static IWriteContext CreateFunctionContext(FunctionBindingContext functionContext) { WriteContext ret = DefaultWriterContext(); if (null != ret) { if (null != functionContext) { ret.CausationIdentifier = functionContext.FunctionInstanceId.ToString("D"); ret.Source = functionContext.MethodName; } } return(ret); }
public async Task BindAsync_Poco_FromRequestBody(bool isChunked) { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; var httpOptions = Options.Create <HttpOptions>(new HttpOptions() { EnableChunkedRequestBinding = isChunked }); HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true, httpOptions); JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Location", "Seattle" } }; var headers = new HeaderDictionary(); headers.Add("Content-Type", "application/json"); HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://functions/myfunc?code=abc123", headers, requestBody.ToString()); if (isChunked) { request.ContentLength = null; request.Headers.Add(HeaderNames.TransferEncoding, "chunked"); } IServiceCollection services = new ServiceCollection(); services.AddMvc(); services.AddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>(); services.AddSingleton <ILoggerFactory, NullLoggerFactory>(); request.HttpContext.RequestServices = services.BuildServiceProvider(); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(5, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco testPoco = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); }
private async Task <IEnumerable <T> > ConvertBlobs(IEnumerable <IListBlobItem> blobItems) { var list = new List <T>(); foreach (var blobItem in blobItems) { var src = (ICloudBlob)blobItem; var funcCtx = new FunctionBindingContext(Guid.Empty, CancellationToken.None, null); var valueCtx = new ValueBindingContext(funcCtx, CancellationToken.None); var converted = await _converter(src, null, valueCtx); list.Add(converted); } return(list); }
private async Task <IEnumerable <T> > ConvertBlobs(IAsyncEnumerable <BlobItem> blobItems, BlobContainerClient blobContainerClient) { var list = new List <T>(); await foreach (var blobItem in blobItems.ConfigureAwait(false)) { BlobBaseClient src = null; switch (blobItem.Properties.BlobType) { case BlobType.Block: if (typeof(T) == typeof(BlobClient)) { // BlobClient is simplified version of BlockBlobClient, i.e. upload results in creation of block blob. src = blobContainerClient.GetBlobClient(blobItem.Name); } else { src = blobContainerClient.GetBlockBlobClient(blobItem.Name); } break; case BlobType.Append: src = blobContainerClient.GetAppendBlobClient(blobItem.Name); break; case BlobType.Page: src = blobContainerClient.GetPageBlobClient(blobItem.Name); break; default: throw new InvalidOperationException($"Unexpected blob type {blobItem.Properties.BlobType}"); } var funcCtx = new FunctionBindingContext(Guid.Empty, CancellationToken.None); var valueCtx = new ValueBindingContext(funcCtx, CancellationToken.None); var converted = await _converter(src, null, valueCtx).ConfigureAwait(false); list.Add(converted); } return(list); }
public async Task BindAsync_HttpRequestMessage_FromQueryParameters() { ParameterInfo parameterInfo = GetType().GetMethod("TestHttpRequestMessageFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://functions/myfunc?code=abc123&Name=Mathew%20Charles&Location=Seattle"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); HttpRequestMessage result = (HttpRequestMessage)triggerData.ValueProvider.GetValue(); Assert.Same(request, result); }
public async Task BindAsync_HttpRequestMessage_FromQueryParameters() { ParameterInfo parameterInfo = GetType().GetMethod("TestHttpRequestMessageFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://functions/myfunc?code=abc123&Name=Mathew%20Charles&location=Hawaii&Location=Ohio&Location=Seattle"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(5, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); HttpRequestMessage result = (HttpRequestMessage)(await triggerData.ValueProvider.GetValueAsync()); Assert.NotNull(result); }
public async Task BindAsync_Poco_MergedBindingData() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunctionEx").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://functions/myfunc?code=abc123&Age=25"); JObject requestBody = new JObject { { "Name", "Mathew Charles" }, { "Phone", "(425) 555-6666" } }; request.Content = new StringContent(requestBody.ToString()); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); Dictionary <string, object> routeData = new Dictionary <string, object> { { "Location", "Seattle" } }; request.Properties.Add(ScriptConstants.AzureFunctionsHttpRouteDataKey, routeData); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(5, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); Assert.Equal("(425) 555-6666", triggerData.BindingData["Phone"]); Assert.Equal("25", triggerData.BindingData["Age"]); TestPocoEx testPoco = (TestPocoEx)triggerData.ValueProvider.GetValue(); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); Assert.Equal("(425) 555-6666", testPoco.Phone); Assert.Equal(25, testPoco.Age); }
public async Task BindAsync_Dynamic() { ParameterInfo parameterInfo = GetType().GetMethod(nameof(TestDynamicFunction)).GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); var headers = new HeaderDictionary(); headers.Add("Content-Type", "application/json"); HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://functions/myfunc?code=abc123", headers, "{ \"value\" : \"This is a test\" }"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(4, triggerData.BindingData.Count); var result = (JObject)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("This is a test", result["value"].ToString()); }
public async Task BindAsync_String() { ParameterInfo parameterInfo = GetType().GetMethod("TestStringFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); var headers = new HeaderDictionary(); headers.Add("Content-Type", "application/text"); HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://functions/myfunc?code=abc123", headers, "This is a test"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(Level.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(2, triggerData.BindingData.Count); string result = (string)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("This is a test", result); }
public async Task BindAsync_Poco_FromQueryParameters() { ParameterInfo parameterInfo = GetType().GetMethod("TestPocoFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, true); HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://functions/myfunc?code=abc123&Name=Mathew%20Charles&Location=Seattle"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(Level.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(4, triggerData.BindingData.Count); Assert.Equal("Mathew Charles", triggerData.BindingData["Name"]); Assert.Equal("Seattle", triggerData.BindingData["Location"]); TestPoco testPoco = (TestPoco)(await triggerData.ValueProvider.GetValueAsync()); Assert.Equal("Mathew Charles", testPoco.Name); Assert.Equal("Seattle", testPoco.Location); }
public async Task BindAsync_String() { ParameterInfo parameterInfo = GetType().GetMethod("TestStringFunction").GetParameters()[0]; HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/myfunc?code=abc123"); request.Content = new StringContent("This is a test"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/text"); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose)); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); ITriggerData triggerData = await binding.BindAsync(request, context); Assert.Equal(0, triggerData.BindingData.Count); string result = (string)triggerData.ValueProvider.GetValue(); Assert.Equal("This is a test", result); }
public async Task BindAsync_ReturnsExpectedTriggerData() { ParameterInfo parameter = GetType().GetMethod("TestTimerJob").GetParameters()[0]; MethodInfo methodInfo = (MethodInfo)parameter.Member; string timerName = string.Format("{0}.{1}", methodInfo.DeclaringType.FullName, methodInfo.Name); Mock <ScheduleMonitor> mockScheduleMonitor = new Mock <ScheduleMonitor>(MockBehavior.Strict); ScheduleStatus status = new ScheduleStatus(); mockScheduleMonitor.Setup(p => p.GetStatusAsync(timerName)).ReturnsAsync(status); TimerTriggerAttribute attribute = parameter.GetCustomAttribute <TimerTriggerAttribute>(); INameResolver nameResolver = new TestNameResolver(); TimerSchedule schedule = TimerSchedule.Create(attribute, nameResolver); TimersConfiguration config = new TimersConfiguration(); config.ScheduleMonitor = mockScheduleMonitor.Object; ILoggerFactory loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new TestLoggerProvider()); TimerTriggerBinding binding = new TimerTriggerBinding(parameter, attribute, schedule, config, loggerFactory.CreateLogger("Test")); // when we bind to a non-TimerInfo (e.g. in a Dashboard invocation) a new // TimerInfo is created, with the ScheduleStatus populated FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); TriggerData triggerData = (TriggerData)(await binding.BindAsync(string.Empty, context)); TimerInfo timerInfo = (TimerInfo)(await triggerData.ValueProvider.GetValueAsync()); Assert.Same(status, timerInfo.ScheduleStatus); // when we pass in a TimerInfo that is used TimerInfo expected = new TimerInfo(schedule, status); triggerData = (TriggerData)(await binding.BindAsync(expected, context)); timerInfo = (TimerInfo)(await triggerData.ValueProvider.GetValueAsync()); Assert.Same(expected, timerInfo); }
public async Task TryCreate_ReturnsTableArgumentBindingExtensionWrapper() { DefaultExtensionRegistry extensions = new DefaultExtensionRegistry(); FooBarTableArgumentBindingProvider fooBarExtensionProvider = new FooBarTableArgumentBindingProvider(); extensions.RegisterExtension <IArgumentBindingProvider <ITableArgumentBinding> >(fooBarExtensionProvider); TableArgumentBindingExtensionProvider provider = new TableArgumentBindingExtensionProvider(extensions); IStorageTableArgumentBinding binding = provider.TryCreate(_parameters[0]); Assert.Equal(typeof(TableArgumentBindingExtensionProvider.TableArgumentBindingExtension), binding.GetType()); Assert.Null(BoundTable); CloudTable table = new CloudTable(new Uri("http://localhost:10000/test/table")); IStorageTable storageTable = new StorageTable(table); FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new StringWriter()); ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None); IValueProvider valueProvider = await binding.BindAsync(storageTable, context); Assert.NotNull(valueProvider); Assert.Same(table, BoundTable); }
public async Task Create_HandlesNullableString() { // Arrange IBindingProvider product = new DataBindingProvider(); string parameterName = "p"; Type parameterType = typeof(string); BindingProviderContext context = CreateBindingContext(parameterName, parameterType); // Act IBinding binding = await product.TryCreateAsync(context); // Assert Assert.NotNull(binding); var functionBindingContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, null); var valueBindingContext = new ValueBindingContext(functionBindingContext, CancellationToken.None); var bindingData = new Dictionary <string, object> { { "p", "Testing" } }; var bindingContext = new BindingContext(valueBindingContext, bindingData); var valueProvider = await binding.BindAsync(bindingContext); var value = await valueProvider.GetValueAsync(); Assert.Equal("Testing", value); bindingData["p"] = null; bindingContext = new BindingContext(valueBindingContext, bindingData); valueProvider = await binding.BindAsync(bindingContext); value = await valueProvider.GetValueAsync(); Assert.Null(value); }
private async Task <string> ExecuteWithLoggingAsync(IFunctionInstance instance, FunctionStartedMessage message, FunctionInstanceLogEntry fastItem, IDictionary <string, ParameterLog> parameterLogCollector, TraceLevel functionTraceLevel, CancellationToken cancellationToken) { IFunctionOutputDefinition outputDefinition = null; IFunctionOutput outputLog = null; ITaskSeriesTimer updateOutputLogTimer = null; TextWriter functionOutputTextWriter = null; Func <Task> initializeOutputAsync = async() => { outputDefinition = await _functionOutputLogger.CreateAsync(instance, cancellationToken); outputLog = outputDefinition.CreateOutput(); functionOutputTextWriter = outputLog.Output; updateOutputLogTimer = StartOutputTimer(outputLog.UpdateCommand, _exceptionHandler); }; if (functionTraceLevel >= TraceLevel.Info) { await initializeOutputAsync(); } try { // Create a linked token source that will allow us to signal function cancellation // (e.g. Based on TimeoutAttribute, etc.) CancellationTokenSource functionCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); using (functionCancellationTokenSource) { // We create a new composite trace writer that will also forward // output to the function output log (in addition to console, user TraceWriter, etc.). TraceWriter traceWriter = new CompositeTraceWriter(_trace, functionOutputTextWriter, functionTraceLevel); // Must bind before logging (bound invoke string is included in log message). FunctionBindingContext functionContext = new FunctionBindingContext(instance.Id, functionCancellationTokenSource.Token, traceWriter); var valueBindingContext = new ValueBindingContext(functionContext, cancellationToken); var parameters = await instance.BindingSource.BindAsync(valueBindingContext); Exception invocationException = null; ExceptionDispatchInfo exceptionInfo = null; string startedMessageId = null; using (ValueProviderDisposable.Create(parameters)) { if (functionTraceLevel >= TraceLevel.Info) { startedMessageId = await LogFunctionStartedAsync(message, outputDefinition, parameters, cancellationToken); } if (_fastLogger != null) { // Log started fastItem.Arguments = message.Arguments; await _fastLogger.AddAsync(fastItem); } try { await ExecuteWithLoggingAsync(instance, parameters, traceWriter, outputDefinition, parameterLogCollector, functionTraceLevel, functionCancellationTokenSource); } catch (Exception ex) { invocationException = ex; } } if (invocationException != null) { if (outputDefinition == null) { // In error cases, even if logging is disabled for this function, we want to force // log errors. So we must delay initialize logging here await initializeOutputAsync(); startedMessageId = await LogFunctionStartedAsync(message, outputDefinition, parameters, cancellationToken); } // In the event of cancellation or timeout, we use the original exception without additional logging. if (invocationException is OperationCanceledException || invocationException is FunctionTimeoutException) { exceptionInfo = ExceptionDispatchInfo.Capture(invocationException); } else { string errorMessage = string.Format("Exception while executing function: {0}", instance.FunctionDescriptor.ShortName); FunctionInvocationException fex = new FunctionInvocationException(errorMessage, instance.Id, instance.FunctionDescriptor.FullName, invocationException); traceWriter.Error(errorMessage, fex, TraceSource.Execution); exceptionInfo = ExceptionDispatchInfo.Capture(fex); } } if (exceptionInfo == null && updateOutputLogTimer != null) { await updateOutputLogTimer.StopAsync(cancellationToken); } // after all execution is complete, flush the TraceWriter traceWriter.Flush(); // We save the exception info above rather than throwing to ensure we always write // console output even if the function fails or was canceled. if (outputLog != null) { await outputLog.SaveAndCloseAsync(fastItem, cancellationToken); } if (exceptionInfo != null) { // release any held singleton lock immediately SingletonLock singleton = null; if (TryGetSingletonLock(parameters, out singleton) && singleton.IsHeld) { await singleton.ReleaseAsync(cancellationToken); } exceptionInfo.Throw(); } return(startedMessageId); } } finally { if (outputLog != null) { ((IDisposable)outputLog).Dispose(); } if (updateOutputLogTimer != null) { ((IDisposable)updateOutputLogTimer).Dispose(); } } }
private async Task <string> ExecuteWithLogMessageAsync(IFunctionInstance instance, FunctionStartedMessage message, IDictionary <string, ParameterLog> parameterLogCollector, CancellationToken cancellationToken) { string startedMessageId; // Create the console output writer IFunctionOutputDefinition outputDefinition = await _functionOutputLogger.CreateAsync(instance, cancellationToken); using (IFunctionOutput outputLog = await outputDefinition.CreateOutputAsync(cancellationToken)) using (ITaskSeriesTimer updateOutputLogTimer = StartOutputTimer(outputLog.UpdateCommand, _backgroundExceptionDispatcher)) { TextWriter consoleOutput = outputLog.Output; FunctionBindingContext functionContext = new FunctionBindingContext(instance.Id, cancellationToken, consoleOutput); // Must bind before logging (bound invoke string is included in log message). IReadOnlyDictionary <string, IValueProvider> parameters = await instance.BindingSource.BindAsync(new ValueBindingContext(functionContext, cancellationToken)); ExceptionDispatchInfo exceptionInfo; using (ValueProviderDisposable.Create(parameters)) { startedMessageId = await LogFunctionStartedAsync(message, outputDefinition, parameters, cancellationToken); try { await ExecuteWithOutputLogsAsync(instance, parameters, consoleOutput, outputDefinition, parameterLogCollector, cancellationToken); exceptionInfo = null; } catch (OperationCanceledException exception) { exceptionInfo = ExceptionDispatchInfo.Capture(exception); } catch (Exception exception) { consoleOutput.WriteLine("--------"); consoleOutput.WriteLine("Exception while executing:"); consoleOutput.Write(exception.ToDetails()); exceptionInfo = ExceptionDispatchInfo.Capture(exception); } } if (exceptionInfo == null && updateOutputLogTimer != null) { await updateOutputLogTimer.StopAsync(cancellationToken); } // We save the exception info rather than doing throw; above to ensure we always write console output, // even if the function fails or was canceled. await outputLog.SaveAndCloseAsync(cancellationToken); if (exceptionInfo != null) { exceptionInfo.Throw(); } return(startedMessageId); } }
public static ILogger ForFunctionBindingContext(this ILogger baseLogger, FunctionBindingContext context) => new LoggerConfiguration() .WriteTo.Logger(baseLogger) .WriteTo.TraceWriter(context.Trace) .Enrich.WithProperty(nameof(context.FunctionInstanceId), context.FunctionInstanceId) .CreateLogger();
private async Task <string> ExecuteWithLogMessageAsync(IFunctionInstance instance, FunctionStartedMessage message, IDictionary <string, ParameterLog> parameterLogCollector, CancellationToken cancellationToken) { string startedMessageId; // Create the console output writer IFunctionOutputDefinition outputDefinition = await _functionOutputLogger.CreateAsync(instance, cancellationToken); // Create a linked token source that will allow us to signal function cancellation // (e.g. Based on TimeoutAttribute, etc.) CancellationTokenSource functionCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); using (IFunctionOutput outputLog = await outputDefinition.CreateOutputAsync(cancellationToken)) using (ITaskSeriesTimer updateOutputLogTimer = StartOutputTimer(outputLog.UpdateCommand, _backgroundExceptionDispatcher)) using (functionCancellationTokenSource) { // We create a new composite trace writer that will also forward // output to the function output log (in addition to console, user TraceWriter, etc.). TraceWriter traceWriter = new CompositeTraceWriter(_trace, outputLog.Output); FunctionBindingContext functionContext = new FunctionBindingContext(instance.Id, functionCancellationTokenSource.Token, traceWriter); // Must bind before logging (bound invoke string is included in log message). IReadOnlyDictionary <string, IValueProvider> parameters = await instance.BindingSource.BindAsync(new ValueBindingContext(functionContext, cancellationToken)); ExceptionDispatchInfo exceptionInfo; using (ValueProviderDisposable.Create(parameters)) { startedMessageId = await LogFunctionStartedAsync(message, outputDefinition, parameters, cancellationToken); try { await ExecuteWithOutputLogsAsync(instance, parameters, traceWriter, outputDefinition, parameterLogCollector, functionCancellationTokenSource); exceptionInfo = null; } catch (OperationCanceledException exception) { exceptionInfo = ExceptionDispatchInfo.Capture(exception); } catch (Exception exception) { string errorMessage = string.Format("Exception while executing function: {0}", instance.FunctionDescriptor.ShortName); FunctionInvocationException functionException = new FunctionInvocationException(errorMessage, instance.Id, instance.FunctionDescriptor.FullName, exception); traceWriter.Error(errorMessage, functionException, TraceSource.Execution); exceptionInfo = ExceptionDispatchInfo.Capture(functionException); } } if (exceptionInfo == null && updateOutputLogTimer != null) { await updateOutputLogTimer.StopAsync(cancellationToken); } // after all execution is complete, flush the TraceWriter traceWriter.Flush(); // We save the exception info rather than doing throw; above to ensure we always write console output, // even if the function fails or was canceled. await outputLog.SaveAndCloseAsync(cancellationToken); if (exceptionInfo != null) { // release any held singleton lock immediately SingletonLock singleton = null; if (TryGetSingletonLock(parameters, out singleton) && singleton.IsHeld) { await singleton.ReleaseAsync(cancellationToken); } exceptionInfo.Throw(); } return(startedMessageId); } }
public T Resolve <T>(FunctionBindingContext context) { ILogger scopedLogger = _container.Resolve <ILogger>().ForFunctionBindingContext(context); return(_container.Resolve <T>(new DependencyOverride <ILogger>(scopedLogger))); }
public ContextResolverValueProvider(IContextResolver resolver, FunctionBindingContext context) { m_resolver = resolver; m_context = context; }
public T Resolve <T>(FunctionBindingContext context) { return(_container.Resolve <T>(new DependencyOverride <TraceWriter>(context.Trace))); }