diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000000000000000000000000000000000000..758d1c575cf7489c5fbcab0d632f129643fdc92f
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,6 @@
+<Project>
+  <Import Project="version.props" />
+  <Import Project="build\common.props" />
+  <Import Project="build\external-dependencies.props" />
+  <Import Project="build\sources.props" />
+</Project>
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000000000000000000000000000000000000..692f3a81da8530fe89b53f1f2857f2dff2aded42
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,6 @@
+<Project>
+  <PropertyGroup>
+    <RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
+    <NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
+  </PropertyGroup>
+</Project>
diff --git a/Microsoft.AspNetCore.sln b/Microsoft.AspNetCore.sln
new file mode 100644
index 0000000000000000000000000000000000000000..809b017e25f3d44caece9a7e64473f0c3bbd5d11
--- /dev/null
+++ b/Microsoft.AspNetCore.sln
@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EE2CAA71-82AA-41C0-AE87-5B4FB77D6CFE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedFx.UnitTests", "test\SharedFx.UnitTests\SharedFx.UnitTests.csproj", "{99CC38EC-902B-4B3F-AD33-177018110199}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x64.Build.0 = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x86.Build.0 = Debug|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|Any CPU.Build.0 = Release|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|x64.ActiveCfg = Release|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|x64.Build.0 = Release|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|x86.ActiveCfg = Release|Any CPU
+		{99CC38EC-902B-4B3F-AD33-177018110199}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{99CC38EC-902B-4B3F-AD33-177018110199} = {EE2CAA71-82AA-41C0-AE87-5B4FB77D6CFE}
+	EndGlobalSection
+EndGlobal
diff --git a/build/SharedFx.targets b/build/SharedFx.targets
index 3abd1b30e5197673594b7dada850e6874112dd38..ed0bb6cf96a4c586326d4155389d0b657d078a24 100644
--- a/build/SharedFx.targets
+++ b/build/SharedFx.targets
@@ -197,7 +197,7 @@
       <VersionLines Include="$(PackageVersion)" />
     </ItemGroup>
 
-     <!-- Publish -->
+    <!-- Publish -->
     <MSBuild Projects="$(SharedFxWorkDirectory)SharedFx.csproj"
       Targets="Publish"
       Properties="$(CommonSharedFxProps);GenerateRuntimeConfigurationFiles=true;SelfContained=false;PublishDir=$(SharedFxPublishDirectory)" />
@@ -528,6 +528,21 @@
       Overwrite="true"/>
   </Target>
 
-  <Target Name="BuildSharedFx" DependsOnTargets="GeneratePropsFiles;ResolveSharedFxFiles;CrossGenAssemblies;CrossGenSymbols;PackSharedFx"/>
+  <Target Name="BuildSharedFx" DependsOnTargets="GeneratePropsFiles;ResolveSharedFxFiles;CrossGenAssemblies;CrossGenSymbols;PackSharedFx;TestSharedFx"/>
+
+  <Target Name="TestSharedFx" DependsOnTargets="DefineSharedFxPrerequisites;ResolveCommitHash">
+    <PropertyGroup>
+      <UnitTestFxProject>$(RepositoryRoot)\test\SharedFx.UnitTests\SharedFx.UnitTests.csproj</UnitTestFxProject>
+      <UnitTestFxTestProps>
+        DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath);
+        DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath);
+        SharedFxOutputPath=$(SharedFxIntermediateOutputPath);
+        RepositoryCommit=$(RepositoryCommit);
+        SharedFxRuntimeIdentifier=$(SharedFXRid)
+      </UnitTestFxTestProps>
+    </PropertyGroup>
+    <MSBuild Projects="$(UnitTestFxProject)" Targets="Restore" Properties="_Dummy=restore;$(UnitTestFxTestProps)" />
+    <MSBuild Projects="$(UnitTestFxProject)" Targets="VSTest" Properties="$(UnitTestFxTestProps)" />
+  </Target>
 
 </Project>
diff --git a/build/common.props b/build/common.props
index 6552ad98ea19c41d7e2751d1e092f7bf5357e8cc..b34f91a0b11e19429bb2d31c552b88b967359a51 100644
--- a/build/common.props
+++ b/build/common.props
@@ -11,8 +11,4 @@
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
 
-  <ItemGroup>
-    <PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkPackageVersion)" PrivateAssets="All" />
-  </ItemGroup>
-
 </Project>
diff --git a/build/dependencies.props b/build/dependencies.props
index e86f1495f95d93e56d6ff64556a438a17f94257b..119224bdb46fccb18e662d8ee1eea4a8fe4878a6 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -11,6 +11,7 @@
   <PropertyGroup>
     <!-- Assign this variable last because it may be updated from DotNetPackageVersionPropsPath as MicrosoftNETCoreAppPackageVersion. -->
     <MicrosoftNETCoreApp21PackageVersion Condition="'$(MicrosoftNETCoreAppPackageVersion)' != ''">$(MicrosoftNETCoreAppPackageVersion)</MicrosoftNETCoreApp21PackageVersion>
+    <MicrosoftNETCoreAppPackageVersion Condition="'$(MicrosoftNETCoreAppPackageVersion)' == ''">$(MicrosoftNETCoreApp21PackageVersion)</MicrosoftNETCoreAppPackageVersion>
 
     <!-- Determined by build tools -->
     <InternalAspNetCoreSdkPackageVersion>$(KoreBuildVersion)</InternalAspNetCoreSdkPackageVersion>
diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj
index 7c95128fdd16d8749bb123ee331034416be18acf..6be1f375d2adf148c17c44fc836cb793798a3d42 100644
--- a/build/tasks/RepoTasks.csproj
+++ b/build/tasks/RepoTasks.csproj
@@ -1,7 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <Import Project="$(RepoTasksSdkPath)\Sdk.props" Condition="'$(RepoTasksSdkPath)' != '' "/>
-  <Import Project="..\dependencies.props" />
-  <Import Project="..\sources.props" />
 
   <PropertyGroup>
     <TargetFramework>netcoreapp2.0</TargetFramework>
diff --git a/build/tools/templates/Archive/Archive.csproj b/build/tools/templates/Archive/Archive.csproj
index e993fa71269e884332075b08821e3a289e19b528..e2843be0e077da7ae752cd1743a4726ec0628bf5 100644
--- a/build/tools/templates/Archive/Archive.csproj
+++ b/build/tools/templates/Archive/Archive.csproj
@@ -1,12 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-  <Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
-
   <PropertyGroup>
     <TargetFramework>netcoreapp2.1</TargetFramework>
     <EnableApiCheck>false</EnableApiCheck>
-    <DotnetCliToolTargetFramework>netcoreapp2.1</DotnetCliToolTargetFramework>
-    <RestoreSources>$(RestoreSources);$(DotNetRestoreSources);</RestoreSources>
     <DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
     <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
   </PropertyGroup>
diff --git a/build/tools/templates/SharedFx/SharedFx.csproj b/build/tools/templates/SharedFx/SharedFx.csproj
index 24bd3aad7ecd3635b5a18ab7864091884268e11e..14e621ae49ed9cdcba1c4f32e60ebc472fc8a5c5 100644
--- a/build/tools/templates/SharedFx/SharedFx.csproj
+++ b/build/tools/templates/SharedFx/SharedFx.csproj
@@ -1,12 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''" />
+<Project Sdk="Microsoft.NET.Sdk" >
 
   <PropertyGroup>
     <TargetFramework>netcoreapp2.1</TargetFramework>
     <DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
     <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
-    <RestoreSources>$(RestoreSources);$(DotNetRestoreSources);</RestoreSources>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 79ca86d0bb88f0ed8fe8cff8f3c7bd1825eb0f3e..34fdc31455c6e20d8f90a347538642ec4af5b25d 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,6 +1,7 @@
 <Project>
-  <Import Project="..\version.props" />
-  <Import Project="..\build\common.props" />
-  <Import Project="..\build\external-dependencies.props" />
-  <Import Project="..\build\sources.props" />
+  <Import Project="..\Directory.Build.props" />
+
+  <ItemGroup>
+    <PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkPackageVersion)" PrivateAssets="All" />
+  </ItemGroup>
 </Project>
diff --git a/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj b/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj
index 6df70d6f229f23ba889b85e82e15503f46888ffd..25ed991894df3100a2f26f80e4c1a848c0ac6a3d 100644
--- a/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj
+++ b/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj
@@ -1,7 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-  <Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
-
   <PropertyGroup>
     <IncludeBuildOutput>false</IncludeBuildOutput>
     <IncludeSymbols>false</IncludeSymbols>
diff --git a/src/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj b/src/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj
index 5927d10ad99b1cfd8a152cb4945f0905bd4103d5..a9f9071719979ed60a38e9825d6a2aa268d76db3 100644
--- a/src/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj
+++ b/src/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj
@@ -1,7 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-  <Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''" />
-
   <PropertyGroup>
     <IncludeBuildOutput>false</IncludeBuildOutput>
     <IncludeSymbols>false</IncludeSymbols>
diff --git a/src/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj b/src/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
index d87e940d0cf88feb30c80279a6df7bf8ed50a22d..25e863ae37794aa7525a362677fc7ad461a68df5 100644
--- a/src/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
+++ b/src/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
@@ -1,7 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-  <Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
-
   <PropertyGroup>
     <IncludeBuildOutput>false</IncludeBuildOutput>
     <IncludeSymbols>false</IncludeSymbols>
diff --git a/test/SharedFx.UnitTests/AssertEx.cs b/test/SharedFx.UnitTests/AssertEx.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c68147c1f6cad44adb3c10976175107262015ffd
--- /dev/null
+++ b/test/SharedFx.UnitTests/AssertEx.cs
@@ -0,0 +1,35 @@
+// 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.IO;
+using Xunit.Sdk;
+
+namespace Microsoft.AspNetCore
+{
+    public class AssertEx
+    {
+        public static void DirectoryExists(string path)
+        {
+            if (!Directory.Exists(path))
+            {
+                throw new XunitException($"Expected directory to exist at {path} but it did not");
+            }
+        }
+
+        public static void FileExists(string path)
+        {
+            if (!File.Exists(path))
+            {
+                throw new XunitException($"Expected file to exist at {path} but it did not");
+            }
+        }
+
+        public static void FileDoesNotExists(string path)
+        {
+            if (File.Exists(path))
+            {
+                throw new XunitException($"File should not exist at {path}");
+            }
+        }
+    }
+}
diff --git a/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj b/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..31a39f032c503bd1df19e69bf95bb712651ed9ef
--- /dev/null
+++ b/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj
@@ -0,0 +1,39 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <RootNamespace>Microsoft.AspNetCore</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
+      <_Parameter1>PackageVersion</_Parameter1>
+      <_Parameter2>$(PackageVersion)</_Parameter2>
+    </AssemblyAttribute>
+    <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
+      <_Parameter1>DotNetRoot</_Parameter1>
+      <_Parameter2>$(SharedFxOutputPath)</_Parameter2>
+    </AssemblyAttribute>
+    <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
+      <_Parameter1>SharedFxRuntimeIdentifier</_Parameter1>
+      <_Parameter2>$(SharedFxRuntimeIdentifier)</_Parameter2>
+    </AssemblyAttribute>
+    <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
+      <_Parameter1>RepositoryCommit</_Parameter1>
+      <_Parameter2>$(RepositoryCommit)</_Parameter2>
+    </AssemblyAttribute>
+    <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
+      <_Parameter1>MicrosoftNETCoreAppPackageVersion</_Parameter1>
+      <_Parameter2>$(MicrosoftNETCoreAppPackageVersion)</_Parameter2>
+    </AssemblyAttribute>
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
+    <PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
+    <PackageReference Include="xunit.analyzers" Version="$(XunitAnalyzersPackageVersion)" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualstudioPackageVersion)" />
+  </ItemGroup>
+
+</Project>
diff --git a/test/SharedFx.UnitTests/SharedFxTests.cs b/test/SharedFx.UnitTests/SharedFxTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d18fa17ef805abd195c09c4354ebcd683dea93d7
--- /dev/null
+++ b/test/SharedFx.UnitTests/SharedFxTests.cs
@@ -0,0 +1,97 @@
+// 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.IO;
+using Newtonsoft.Json.Linq;
+using Xunit;
+
+namespace Microsoft.AspNetCore
+{
+    public class SharedFxTests
+    {
+        [Theory]
+        [MemberData(nameof(GetSharedFxConfig))]
+        public void ItContainsValidRuntimeConfigFile(SharedFxConfig config)
+        {
+            var root = TestData.GetDotNetRoot();
+            var dir = Path.Combine(root, "shared", config.Name, config.Version);
+            var runtimeConfigFilePath = Path.Combine(dir, config.Name + ".runtimeconfig.json");
+
+            AssertEx.FileExists(runtimeConfigFilePath);
+            AssertEx.FileDoesNotExists(Path.Combine(dir, config.Name + ".runtimeconfig.dev.json"));
+
+            var runtimeConfig = JObject.Parse(File.ReadAllText(runtimeConfigFilePath));
+
+            Assert.Equal(config.BaseSharedFxName, (string)runtimeConfig["runtimeOptions"]["framework"]["name"]);
+            Assert.Equal("netcoreapp" + config.Version.Substring(0, 3), (string)runtimeConfig["runtimeOptions"]["tfm"]);
+
+            Assert.Equal(config.BaseSharedFxVersion, (string)runtimeConfig["runtimeOptions"]["framework"]["version"]);
+        }
+
+        [Theory]
+        [MemberData(nameof(GetSharedFxConfig))]
+        public void ItContainsValidDepsJson(SharedFxConfig config)
+        {
+            var root = TestData.GetDotNetRoot();
+            var dir = Path.Combine(root, "shared", config.Name, config.Version);
+            var depsFilePath = Path.Combine(dir, config.Name + ".deps.json");
+
+            var target = $".NETCoreApp,Version=v{config.Version.Substring(0, 3)}/{config.RuntimeIdentifier}";
+
+            AssertEx.FileExists(depsFilePath);
+
+            var depsFile = JObject.Parse(File.ReadAllText(depsFilePath));
+
+            Assert.Equal(target, (string)depsFile["runtimeTarget"]["name"]);
+            Assert.NotNull(depsFile["targets"][target]);
+            Assert.NotNull(depsFile["compilationOptions"]);
+            Assert.Empty(depsFile["compilationOptions"]);
+            Assert.NotEmpty(depsFile["runtimes"][config.RuntimeIdentifier]);
+        }
+
+        [Theory]
+        [MemberData(nameof(GetSharedFxConfig))]
+        public void ItContainsVersionFile(SharedFxConfig config)
+        {
+            var root = TestData.GetDotNetRoot();
+            var versionFile = Path.Combine(root, "shared", config.Name, config.Version, ".version");
+            AssertEx.FileExists(versionFile);
+            var lines = File.ReadAllLines(versionFile);
+            Assert.Equal(2, lines.Length);
+            Assert.Equal(TestData.GetRepositoryCommit(), lines[0]);
+            Assert.Equal(config.Version, lines[1]);
+        }
+
+
+        public static TheoryData<SharedFxConfig> GetSharedFxConfig()
+            => new TheoryData<SharedFxConfig>
+            {
+                new SharedFxConfig
+                {
+                    Name = "Microsoft.AspNetCore.All",
+                    Version = TestData.GetPackageVersion(),
+                    // Intentionally assert aspnetcore frameworks align versions with each other and netcore
+                    BaseSharedFxVersion = TestData.GetPackageVersion(),
+                    BaseSharedFxName = "Microsoft.AspNetCore.App",
+                    RuntimeIdentifier = TestData.GetSharedFxRuntimeIdentifier(),
+                },
+                new SharedFxConfig
+                {
+                    Name = "Microsoft.AspNetCore.App",
+                    Version = TestData.GetPackageVersion(),
+                    BaseSharedFxName = "Microsoft.NETCore.App",
+                    BaseSharedFxVersion = TestData.GetMicrosoftNETCoreAppPackageVersion(),
+                    RuntimeIdentifier = TestData.GetSharedFxRuntimeIdentifier(),
+                },
+            };
+
+        public class SharedFxConfig
+        {
+            public string Name { get; set; }
+            public string Version { get; set; }
+            public string BaseSharedFxName { get; set; }
+            public string BaseSharedFxVersion { get; set; }
+            public string RuntimeIdentifier { get; set; }
+        }
+    }
+}
diff --git a/test/SharedFx.UnitTests/TestData.cs b/test/SharedFx.UnitTests/TestData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..eb01f60e8b2d3f04553eb393a16b14ca0042b4f3
--- /dev/null
+++ b/test/SharedFx.UnitTests/TestData.cs
@@ -0,0 +1,24 @@
+// 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.Linq;
+using System.Reflection;
+
+namespace Microsoft.AspNetCore
+{
+    public class TestData
+    {
+        public static string GetPackageVersion() => GetTestDataValue("PackageVersion");
+
+        public static string GetMicrosoftNETCoreAppPackageVersion() => GetTestDataValue("MicrosoftNETCoreAppPackageVersion");
+
+        public static string GetDotNetRoot() => GetTestDataValue("DotNetRoot");
+
+        public static string GetRepositoryCommit() => GetTestDataValue("RepositoryCommit");
+
+        public static string GetSharedFxRuntimeIdentifier() => GetTestDataValue("SharedFxRuntimeIdentifier");
+
+        private static string GetTestDataValue(string key)
+             => typeof(TestData).Assembly.GetCustomAttributes<TestDataAttribute>().Single(d => d.Key == key).Value;
+    }
+}
diff --git a/test/SharedFx.UnitTests/TestDataAttribute.cs b/test/SharedFx.UnitTests/TestDataAttribute.cs
new file mode 100644
index 0000000000000000000000000000000000000000..68085e6807031fe2839ab8812af73e5ed289c999
--- /dev/null
+++ b/test/SharedFx.UnitTests/TestDataAttribute.cs
@@ -0,0 +1,20 @@
+// 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;
+
+namespace Microsoft.AspNetCore
+{
+    [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+    internal class TestDataAttribute : Attribute
+    {
+        public TestDataAttribute(string key, string value)
+        {
+            Key = key;
+            Value = value;
+        }
+
+        public string Key { get; }
+        public string Value { get; }
+    }
+}
diff --git a/version.props b/version.props
index 43106355c092fb4e46ee1c29e3c49291f0a07903..1652259436456221097fc6f45822f23ae02c4cc7 100644
--- a/version.props
+++ b/version.props
@@ -5,6 +5,7 @@
     <AspNetCorePatchVersion>3</AspNetCorePatchVersion>
     <VersionPrefix>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion)</VersionPrefix>
     <PrereleaseVersionLabel>rtm</PrereleaseVersionLabel>
+    <BuildNumber Condition="'$(BuildNumber)' == ''">t000</BuildNumber>
 
     <!-- The 'human friendly' version to display in installers. In pre-release builds, this might be "2.0.7 Preview 2" -->
     <PackageBrandingVersion>$(VersionPrefix)</PackageBrandingVersion>