public async Task InvokeAsync([NotNull] ViewComponentContext context)
        {
            IViewComponentResult result;

            var asyncMethod = ViewComponentMethodSelector.FindAsyncMethod(
                context.ViewComponentDescriptor.Type.GetTypeInfo(),
                context.Arguments);

            if (asyncMethod == null)
            {
                // We support falling back to synchronous if there is no InvokeAsync method, in this case we'll still
                // execute the IViewResult asynchronously.
                var syncMethod = ViewComponentMethodSelector.FindSyncMethod(
                    context.ViewComponentDescriptor.Type.GetTypeInfo(),
                    context.Arguments);
                if (syncMethod == null)
                {
                    throw new InvalidOperationException(
                              Resources.FormatViewComponent_CannotFindMethod_WithFallback(
                                  ViewComponentMethodSelector.SyncMethodName, ViewComponentMethodSelector.AsyncMethodName));
                }
                else
                {
                    result = InvokeSyncCore(syncMethod, context);
                }
            }
            else
            {
                result = await InvokeAsyncCore(asyncMethod, context);
            }

            await result.ExecuteAsync(context);
        }
        public void FindAsyncMethod_ReturnsNull_IfMatchCannotBeFound(Type type, object[] args)
        {
            // Arrange
            var typeInfo = type.GetTypeInfo();

            // Act
            var method = ViewComponentMethodSelector.FindAsyncMethod(typeInfo, args);

            // Assert
            Assert.Null(method);
        }
        public void FindAsyncMethod_ThrowsIfInvokeAsyncDoesNotHaveCorrectReturnType(object[] args)
        {
            // Arrange
            var typeInfo = typeof(TypeWithInvalidInvokeAsync).GetTypeInfo();

            // Act and Assert
            var ex = Assert.Throws <InvalidOperationException>(
                () => ViewComponentMethodSelector.FindAsyncMethod(typeInfo, args));

            Assert.Equal("The async view component method 'InvokeAsync' should be declared to return Task<T>.",
                         ex.Message);
        }
        public void FindAsyncMethod_ReturnsMethodMatchingParameters(Type type, object[] args, string expectedId)
        {
            // Arrange
            var typeInfo = type.GetTypeInfo();

            // Act
            var method = ViewComponentMethodSelector.FindAsyncMethod(typeInfo, args);

            // Assert
            Assert.NotNull(method);
            var data = method.GetCustomAttribute <MethodDataAttribute>();

            Assert.Equal(expectedId, data.Data);
        }