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);
        }
Example #8
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
            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);
        }
Example #15
0
        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);
        }
Example #17
0
        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);
        }
Example #22
0
        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);
                }
        }
Example #26
0
 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();
Example #27
0
        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);
                    }
        }
Example #28
0
        public T Resolve <T>(FunctionBindingContext context)
        {
            ILogger scopedLogger = _container.Resolve <ILogger>().ForFunctionBindingContext(context);

            return(_container.Resolve <T>(new DependencyOverride <ILogger>(scopedLogger)));
        }
Example #29
0
 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)));
 }