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 FindSyncMethod_ReturnsNull_IfMatchCannotBeFound(Type type, object[] args)
        {
            // Arrange
            var typeInfo = type.GetTypeInfo();

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

            // Assert
            Assert.Null(method);
        }
        public void FindSyncMethod_ThrowsIfInvokeSyncReturnsTask()
        {
            // Arrange
            var expectedMessage = "The view component method 'Invoke' cannot return a Task.";
            var typeInfo        = typeof(TypeWithInvalidInvokeSync).GetTypeInfo();

            // Act and Assert
            var ex = Assert.Throws <InvalidOperationException>(
                () => ViewComponentMethodSelector.FindSyncMethod(typeInfo, new object[] { "" }));

            Assert.Equal(expectedMessage, ex.Message);
        }
        public void FindSyncMethod_ThrowsIfInvokeSyncIsAVoidMethod()
        {
            // Arrange
            var expectedMessage = "The view component method 'Invoke' should be declared to return a value.";
            var typeInfo        = typeof(TypeWithInvalidInvokeSync).GetTypeInfo();

            // Act and Assert
            var ex = Assert.Throws <InvalidOperationException>(
                () => ViewComponentMethodSelector.FindSyncMethod(typeInfo, new object[] { 4 }));

            Assert.Equal(expectedMessage, ex.Message);
        }
        public void FindSyncMethod_ReturnsMethodMatchingParameters(Type type, object[] args, string expectedId)
        {
            // Arrange
            var typeInfo = type.GetTypeInfo();

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

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

            Assert.Equal(expectedId, data.Data);
        }
        public void Invoke([NotNull] ViewComponentContext context)
        {
            var method = ViewComponentMethodSelector.FindSyncMethod(
                context.ViewComponentDescriptor.Type.GetTypeInfo(),
                context.Arguments);

            if (method == null)
            {
                throw new InvalidOperationException(
                          Resources.FormatViewComponent_CannotFindMethod(ViewComponentMethodSelector.SyncMethodName));
            }

            var result = InvokeSyncCore(method, context);

            result.Execute(context);
        }