diff --git a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj
index 04407e7792..1feb6f2a3d 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj
+++ b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj
@@ -17,6 +17,7 @@
MicrosoftEntityFrameworkCoreToolsPackageVersion=$(MicrosoftEntityFrameworkCoreToolsPackageVersion);
MicrosoftExtensionsHostingPackageVersion=$(MicrosoftExtensionsHostingPackageVersion);
MicrosoftNETCoreAppRuntimeVersion=$(MicrosoftNETCoreAppRuntimeVersion);
+ TemplateComponentsPackageVersion=$(TemplateComponentsPackageVersion);
@@ -25,6 +26,7 @@
+
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in b/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in
index 4bd3778901..84d28722d2 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in
+++ b/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in
@@ -11,8 +11,10 @@
+
+
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json
index 405e29cca7..bc42542cd3 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json
@@ -22,12 +22,22 @@
"preferNameDirectory": true,
"sources": [
{
- "modifiers": [{
- "condition": "(!SupportPagesAndViews)",
- "exclude": [
- "Areas/**"
- ]
- }]
+ "modifiers": [
+ {
+ "condition": "(!SupportPagesAndViews)",
+ "exclude": [
+ "Areas/**"
+ ]
+ },
+ {
+ "condition": "(SupportPagesAndViews)",
+ "exclude": [
+ "Component1.razor",
+ "ExampleJsInterop.cs",
+ "wwwroot/**"
+ ]
+ }
+ ]
}
],
"symbols": {
@@ -56,7 +66,7 @@
"SupportPagesAndViews": {
"type": "parameter",
"datatype": "bool",
- "defaultValue": "true",
+ "defaultValue": "false",
"description": "Whether to support adding traditional Razor pages and Views in addition to components to this library."
}
},
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json
index bfc7ca434b..e54f38543f 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json
@@ -12,5 +12,14 @@
},
"order": 700,
"icon": "vs-2017.3/RazorClassLibrary.ico",
- "learnMoreLink": "https://go.microsoft.com/fwlink/?linkid=872103"
+ "learnMoreLink": "https://go.microsoft.com/fwlink/?linkid=872103",
+ "symbolInfo": [
+ {
+ "id": "SupportPagesAndViews",
+ "name": {
+ "text": "_Support pages and views"
+ },
+ "isVisible": "true"
+ }
+ ]
}
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor
new file mode 100644
index 0000000000..3c16c3c6d2
--- /dev/null
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor
@@ -0,0 +1,3 @@
+
+ This Blazor component is defined in the RazorClassLibrary-CSharp package.
+
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs
new file mode 100644
index 0000000000..81bea2832e
--- /dev/null
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs
@@ -0,0 +1,16 @@
+using Microsoft.JSInterop;
+using System.Threading.Tasks;
+
+namespace RazorClassLibrary_CSharp
+{
+ public class ExampleJsInterop
+ {
+ public static Task Prompt(IJSRuntime jsRuntime, string message)
+ {
+ // Implemented in exampleJsInterop.js
+ return jsRuntime.InvokeAsync(
+ "exampleJsFunctions.showPrompt",
+ message);
+ }
+ }
+}
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png
new file mode 100644
index 0000000000..e15a3bde6e
Binary files /dev/null and b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png differ
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js
new file mode 100644
index 0000000000..e35d0744fb
--- /dev/null
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js
@@ -0,0 +1,8 @@
+// This file is to show how a library package may provide JavaScript interop features
+// wrapped in a .NET API
+
+window.exampleJsFunctions = {
+ showPrompt: function (message) {
+ return prompt(message, 'Type anything here');
+ }
+};
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css
new file mode 100644
index 0000000000..ebd14018bd
--- /dev/null
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css
@@ -0,0 +1,11 @@
+/*
+ This file is to show how CSS and other static resources (such as images) can be
+ used from a library project/package.
+*/
+
+.my-component {
+ border: 2px dashed red;
+ padding: 1em;
+ margin: 1em 0;
+ background-image: url('background.png');
+}
diff --git a/src/ProjectTemplates/test/BaselineTest.cs b/src/ProjectTemplates/test/BaselineTest.cs
index 913815abee..b6f63f9f38 100644
--- a/src/ProjectTemplates/test/BaselineTest.cs
+++ b/src/ProjectTemplates/test/BaselineTest.cs
@@ -111,6 +111,11 @@ namespace Templates.Test
text += LanguageRegex.Match(arguments)
.Groups.TryGetValue("language", out var language) ? language.Value.Replace("#", "Sharp") : "";
+ if (arguments.Contains("--support-pages-and-views true"))
+ {
+ text += "supportpagesandviewstrue";
+ }
+
return text;
}
diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs
index e7b3c4b2b6..f2e5a94f36 100644
--- a/src/ProjectTemplates/test/Helpers/Project.cs
+++ b/src/ProjectTemplates/test/Helpers/Project.cs
@@ -41,36 +41,44 @@ namespace Templates.Test.Helpers
public ITestOutputHelper Output { get; set; }
public IMessageSink DiagnosticsMessageSink { get; set; }
- internal async Task RunDotNetNewAsync(string templateName, string auth = null, string language = null, bool useLocalDB = false, bool noHttps = false)
+ internal async Task RunDotNetNewAsync(string templateName, string auth = null, string language = null, bool useLocalDB = false, bool noHttps = false, string[] args = null)
{
var hiveArg = $"--debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\"";
- var args = $"new {templateName} {hiveArg}";
+ var argString = $"new {templateName} {hiveArg}";
if (!string.IsNullOrEmpty(auth))
{
- args += $" --auth {auth}";
+ argString += $" --auth {auth}";
}
if (!string.IsNullOrEmpty(language))
{
- args += $" -lang {language}";
+ argString += $" -lang {language}";
}
if (useLocalDB)
{
- args += $" --use-local-db";
+ argString += $" --use-local-db";
}
if (noHttps)
{
- args += $" --no-https";
+ argString += $" --no-https";
+ }
+
+ if (args != null)
+ {
+ foreach (var arg in args)
+ {
+ argString += " " + arg;
+ }
}
// Save a copy of the arguments used for better diagnostic error messages later.
// We omit the hive argument and the template output dir as they are not relevant and add noise.
- ProjectArguments = args.Replace(hiveArg, "");
+ ProjectArguments = argString.Replace(hiveArg, "");
- args += $" -o {TemplateOutputDir}";
+ argString += $" -o {TemplateOutputDir}";
// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63
@@ -78,7 +86,7 @@ namespace Templates.Test.Helpers
await DotNetNewLock.WaitAsync();
try
{
- var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), args);
+ var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString);
await execution.Exited;
return execution;
}
diff --git a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
index bd9cd1d02c..ffd1b0ae4f 100644
--- a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
+++ b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
@@ -48,7 +48,7 @@ namespace Templates.Test.Helpers
NodeLock = NodeLock,
Output = outputHelper,
DiagnosticsMessageSink = DiagnosticsMessageSink,
- ProjectGuid = Guid.NewGuid().ToString("N").Substring(0, 6)
+ ProjectGuid = Path.GetRandomFileName().Replace(".", string.Empty)
};
project.ProjectName = $"AspNet.{key}.{project.ProjectGuid}";
diff --git a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs
index bfafbede5e..69fe97ef60 100644
--- a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs
+++ b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs
@@ -21,6 +21,25 @@ namespace Templates.Test
public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; }
+ [Fact]
+ public async Task RazorClassLibraryTemplate_WithViews_Async()
+ {
+ Project = await ProjectFactory.GetOrCreateProject("razorclasslibwithviews", Output);
+
+ var createResult = await Project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" });
+ Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
+
+ var publishResult = await Project.RunDotNetPublishAsync();
+ Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
+
+ // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
+ // The output from publish will go into bin/Release/netcoreapp3.0/publish and won't be affected by calling build
+ // later, while the opposite is not true.
+
+ var buildResult = await Project.RunDotNetBuildAsync();
+ Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
+ }
+
[Fact]
public async Task RazorClassLibraryTemplateAsync()
{
diff --git a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs
index cfa18a4f3e..95d84c965c 100644
--- a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs
+++ b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs
@@ -203,7 +203,7 @@ namespace Templates.Test.SpaTemplateTest
{
browser.Exists(By.TagName("ul"));
// element gets project ID injected into it during template execution
- browser.Contains(Project.ProjectGuid, () => browser.Title);
+ browser.Contains(Project.ProjectGuid.Replace(".", "._"), () => browser.Title);
// Initially displays the home page
browser.Equal("Hello, world!", () => browser.FindElement(By.TagName("h1")).Text);
diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json
index 22ebb25882..086b4af195 100644
--- a/src/ProjectTemplates/test/template-baselines.json
+++ b/src/ProjectTemplates/test/template-baselines.json
@@ -871,9 +871,20 @@
}
},
"razorclasslib": {
- "None": {
+ "ComponentsOnly": {
"Template": "razorclasslib",
"Arguments": "new razorclasslib",
+ "Files": [
+ "wwwroot/background.png",
+ "wwwroot/exampleJsInterop.js",
+ "wwwroot/styles.css",
+ "Component1.razor",
+ "ExampleJsInterop.cs"
+ ]
+ },
+ "ViewsOnly": {
+ "Template": "razorclasslib",
+ "Arguments": "new razorclasslib --support-pages-and-views true",
"Files": [
"Areas/MyFeature/Pages/Page1.cshtml",
"Areas/MyFeature/Pages/Page1.cshtml.cs"