diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Host/ViewComponentTagHelperDescriptorConventions.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Host/ViewComponentTagHelperDescriptorConventions.cs
new file mode 100644
index 0000000000..36f42c9e01
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Razor.Host/ViewComponentTagHelperDescriptorConventions.cs
@@ -0,0 +1,27 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Host
+{
+ ///
+ /// A library of methods used to generate s for view components.
+ ///
+ public static class ViewComponentTagHelperDescriptorConventions
+ {
+ ///
+ /// The key in a containing
+ /// the short name of a view component.
+ ///
+ public static readonly string ViewComponentNameKey = "ViewComponentName";
+
+ ///
+ /// Indicates whether a represents a view component.
+ ///
+ /// The to check.
+ /// Whether a represents a view component.
+ public static bool IsViewComponentDescriptor(TagHelperDescriptor descriptor) =>
+ descriptor != null && descriptor.PropertyBag.ContainsKey(ViewComponentNameKey);
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/ViewComponentTagHelperDescriptorFactory.cs b/src/Microsoft.AspNetCore.Mvc.Razor/ViewComponentTagHelperDescriptorFactory.cs
new file mode 100644
index 0000000000..6ec113860c
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/ViewComponentTagHelperDescriptorFactory.cs
@@ -0,0 +1,118 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc.Razor.Host;
+using Microsoft.AspNetCore.Mvc.ViewComponents;
+using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
+using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
+
+namespace Microsoft.AspNetCore.Mvc.Razor
+{
+ ///
+ /// Provides methods to create tag helper representations of view components.
+ ///
+ public class ViewComponentTagHelperDescriptorFactory
+ {
+ private readonly IViewComponentDescriptorProvider _descriptorProvider;
+
+ ///
+ /// Creates a new ,
+ /// then creates s for s
+ /// in the given .
+ ///
+ /// The provider of s.
+ public ViewComponentTagHelperDescriptorFactory(IViewComponentDescriptorProvider descriptorProvider)
+ {
+ if (descriptorProvider == null)
+ {
+ throw new ArgumentNullException(nameof(descriptorProvider));
+ }
+
+ _descriptorProvider = descriptorProvider;
+ }
+
+ ///
+ /// Creates representations of s
+ /// in an represented by the given .
+ ///
+ /// The name of the assembly containing
+ /// the s to translate.
+ /// A ,
+ /// one for each .
+ public IEnumerable CreateDescriptors(string assemblyName)
+ {
+ if (assemblyName == null)
+ {
+ throw new ArgumentNullException(nameof(assemblyName));
+ }
+
+ var viewComponentDescriptors = _descriptorProvider
+ .GetViewComponents()
+ .Where(viewComponent => string.Equals(assemblyName, viewComponent.TypeInfo.Assembly.GetName().Name,
+ StringComparison.Ordinal));
+
+ var tagHelperDescriptors = viewComponentDescriptors
+ .Select(viewComponentDescriptor => CreateDescriptor(viewComponentDescriptor));
+
+ return tagHelperDescriptors;
+ }
+
+ private TagHelperDescriptor CreateDescriptor(ViewComponentDescriptor viewComponentDescriptor)
+ {
+ var assemblyName = viewComponentDescriptor.TypeInfo.Assembly.GetName().Name;
+ var tagName = GetTagName(viewComponentDescriptor);
+ var typeName = $"__Generated__{viewComponentDescriptor.ShortName}ViewComponentTagHelper";
+
+ var tagHelperDescriptor = new TagHelperDescriptor
+ {
+ TagName = tagName,
+ TypeName = typeName,
+ AssemblyName = assemblyName
+ };
+
+ SetAttributeDescriptors(viewComponentDescriptor, tagHelperDescriptor);
+
+ tagHelperDescriptor.PropertyBag.Add(
+ ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, viewComponentDescriptor.ShortName);
+
+ return tagHelperDescriptor;
+ }
+
+ private void SetAttributeDescriptors(ViewComponentDescriptor viewComponentDescriptor,
+ TagHelperDescriptor tagHelperDescriptor)
+ {
+ var methodParameters = viewComponentDescriptor.MethodInfo.GetParameters();
+ var attributeDescriptors = new List();
+
+ foreach (var parameter in methodParameters)
+ {
+ var lowerKebabName = TagHelperDescriptorFactory.ToHtmlCase(parameter.Name);
+ var descriptor = new TagHelperAttributeDescriptor
+ {
+ Name = lowerKebabName,
+ PropertyName = parameter.Name,
+ TypeName = parameter.ParameterType.FullName
+ };
+
+ descriptor.IsEnum = parameter.ParameterType.GetTypeInfo().IsEnum;
+ descriptor.IsIndexer = false;
+
+ attributeDescriptors.Add(descriptor);
+ }
+
+ tagHelperDescriptor.Attributes = attributeDescriptors;
+ tagHelperDescriptor.RequiredAttributes = tagHelperDescriptor.Attributes.Select(
+ attribute => new TagHelperRequiredAttributeDescriptor
+ {
+ Name = attribute.Name
+ });
+ }
+
+ private string GetTagName(ViewComponentDescriptor descriptor) =>
+ $"vc:{TagHelperDescriptorFactory.ToHtmlCase(descriptor.ShortName)}";
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperDescriptorConventionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperDescriptorConventionsTest.cs
new file mode 100644
index 0000000000..5f399fafe0
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperDescriptorConventionsTest.cs
@@ -0,0 +1,63 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.AspNetCore.Mvc.ViewComponents;
+using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Host.Test
+{
+ public class ViewComponentTagHelperDescriptorConventionsTest
+ {
+ [Fact]
+ public void IsViewComponentDescriptor_ReturnsFalseForInvalidDescriptor()
+ {
+ //Arrange
+ var tagHelperDescriptor = CreateTagHelperDescriptor();
+
+ // Act
+ var isViewComponentDescriptor = ViewComponentTagHelperDescriptorConventions
+ .IsViewComponentDescriptor(tagHelperDescriptor);
+
+ // Assert
+ Assert.False(isViewComponentDescriptor);
+ }
+
+ [Fact]
+ public void IsViewComponentDescriptor_ReturnsTrueForValidDescriptor()
+ {
+ // Arrange
+ var descriptor = CreateViewComponentTagHelperDescriptor();
+
+ // Act
+ var isViewComponentDescriptor = ViewComponentTagHelperDescriptorConventions
+ .IsViewComponentDescriptor(descriptor);
+
+ // Assert
+ Assert.True(isViewComponentDescriptor);
+ }
+
+ private static TagHelperDescriptor CreateTagHelperDescriptor()
+ {
+ var descriptor = new TagHelperDescriptor
+ {
+ TagName = "tag-name",
+ TypeName = "TypeName",
+ AssemblyName = "AssemblyName",
+ };
+
+ return descriptor;
+ }
+
+ private static TagHelperDescriptor CreateViewComponentTagHelperDescriptor()
+ {
+ var descriptor = CreateTagHelperDescriptor();
+ descriptor.PropertyBag.Add(
+ ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey,
+ "ViewComponentName");
+
+ return descriptor;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/ViewComponentTagHelperDescriptorFactoryTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/ViewComponentTagHelperDescriptorFactoryTest.cs
new file mode 100644
index 0000000000..93cd3f1bb8
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/ViewComponentTagHelperDescriptorFactoryTest.cs
@@ -0,0 +1,193 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc.Razor.Host;
+using Microsoft.AspNetCore.Mvc.ViewComponents;
+using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Test.ViewComponentTagHelpers
+{
+ public class ViewComponentTagHelperDescriptorFactoryTest
+ {
+ public static TheoryData AssemblyData
+ {
+ get
+ {
+ var provider = new TestViewComponentDescriptorProvider();
+
+ var assemblyOne = "Microsoft.AspNetCore.Mvc.Razor";
+ var assemblyTwo = "Microsoft.AspNetCore.Mvc.Razor.Test";
+ var assemblyNone = string.Empty;
+
+ return new TheoryData>
+ {
+ { assemblyOne, new [] { provider.GetTagHelperDescriptorOne() } },
+ { assemblyTwo, new [] { provider.GetTagHelperDescriptorTwo() } },
+ { assemblyNone, Enumerable.Empty() }
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(AssemblyData))]
+ public void CreateDescriptors_ReturnsCorrectDescriptors(
+ string assemblyName,
+ IEnumerable expectedDescriptors)
+ {
+ // Arrange
+ var provider = new TestViewComponentDescriptorProvider();
+ var factory = new ViewComponentTagHelperDescriptorFactory(provider);
+
+ // Act
+ var descriptors = factory.CreateDescriptors(assemblyName);
+
+ // Assert
+ Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.Default);
+ }
+
+ // Test invokes are needed for method creation in TestViewComponentDescriptorProvider.
+ public enum TestEnum
+ {
+ A = 1,
+ B = 2,
+ C = 3
+ }
+
+ public void TestInvokeOne(string foo, string bar)
+ {
+ }
+
+ public void TestInvokeTwo(TestEnum testEnum, Dictionary testDictionary, int baz = 5)
+ {
+ }
+
+ private class TestViewComponentDescriptorProvider : IViewComponentDescriptorProvider
+ {
+ private readonly ViewComponentDescriptor _viewComponentDescriptorOne = new ViewComponentDescriptor
+ {
+ DisplayName = "OneDisplayName",
+ FullName = "OneViewComponent",
+ ShortName = "One",
+ MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
+ .GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeOne)),
+ TypeInfo = typeof(ViewComponentTagHelperDescriptorFactory).GetTypeInfo()
+ };
+
+ private readonly ViewComponentDescriptor _viewComponentDescriptorTwo = new ViewComponentDescriptor
+ {
+ DisplayName = "TwoDisplayName",
+ FullName = "TwoViewComponent",
+ ShortName = "Two",
+ MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
+ .GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeTwo)),
+ TypeInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetTypeInfo()
+ };
+
+ public TagHelperDescriptor GetTagHelperDescriptorOne()
+ {
+ var descriptor = new TagHelperDescriptor
+ {
+ TagName = "vc:one",
+ TypeName = "__Generated__OneViewComponentTagHelper",
+ AssemblyName = "Microsoft.AspNetCore.Mvc.Razor",
+ Attributes = new List
+ {
+ new TagHelperAttributeDescriptor
+ {
+ Name = "foo",
+ PropertyName = "foo",
+ TypeName = typeof(string).FullName
+ },
+ new TagHelperAttributeDescriptor
+ {
+ Name = "bar",
+ PropertyName = "bar",
+ TypeName = typeof(string).FullName
+ }
+ },
+ RequiredAttributes = new List
+ {
+ new TagHelperRequiredAttributeDescriptor
+ {
+ Name = "foo"
+ },
+ new TagHelperRequiredAttributeDescriptor
+ {
+ Name = "bar"
+ }
+ }
+ };
+
+ descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "One");
+ return descriptor;
+ }
+
+ public TagHelperDescriptor GetTagHelperDescriptorTwo()
+ {
+ var descriptor = new TagHelperDescriptor
+ {
+ TagName = "vc:two",
+ TypeName = "__Generated__TwoViewComponentTagHelper",
+ AssemblyName = "Microsoft.AspNetCore.Mvc.Razor.Test",
+ Attributes = new List
+ {
+ new TagHelperAttributeDescriptor
+ {
+ Name = "test-enum",
+ PropertyName = "testEnum",
+ TypeName = typeof(TestEnum).FullName,
+ IsEnum = true
+ },
+
+ new TagHelperAttributeDescriptor
+ {
+ Name = "test-dictionary",
+ PropertyName = "testDictionary",
+ TypeName = typeof(Dictionary).FullName
+ },
+
+ new TagHelperAttributeDescriptor
+ {
+ Name = "baz",
+ PropertyName = "baz",
+ TypeName = typeof(int).FullName
+ }
+ },
+ RequiredAttributes = new List
+ {
+ new TagHelperRequiredAttributeDescriptor
+ {
+ Name = "test-enum"
+ },
+
+ new TagHelperRequiredAttributeDescriptor
+ {
+ Name = "test-dictionary"
+ },
+
+ new TagHelperRequiredAttributeDescriptor
+ {
+ Name = "baz"
+ }
+ }
+ };
+
+ descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "Two");
+ return descriptor;
+ }
+
+ public IEnumerable GetViewComponents()
+ {
+ return new List
+ {
+ _viewComponentDescriptorOne,
+ _viewComponentDescriptorTwo
+ };
+ }
+ }
+ }
+}