diff --git a/Razor.sln b/Razor.sln index 45dea45281..600604db12 100644 --- a/Razor.sln +++ b/Razor.sln @@ -78,6 +78,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test", "test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test.csproj", "{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Razor.Design", "src\Microsoft.AspNetCore.Razor.Design\Microsoft.AspNetCore.Razor.Design.csproj", "{5257B25D-330A-4DCF-ACED-B4709CFBF916}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Razor.Design.Test", "test\Microsoft.AspNetCore.Razor.Design.Test\Microsoft.AspNetCore.Razor.Design.Test.csproj", "{1D90F276-E1CA-4FDF-A173-EB889E7D3150}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -316,6 +320,22 @@ Global {B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Release|Any CPU.Build.0 = Release|Any CPU {B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.Release|Any CPU.Build.0 = Release|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {5257B25D-330A-4DCF-ACED-B4709CFBF916}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Release|Any CPU.Build.0 = Release|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {1D90F276-E1CA-4FDF-A173-EB889E7D3150}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -350,6 +370,8 @@ Global {FAF9986F-E086-4513-9D52-F7BF5FFCF31D} = {C0CC1E1F-1559-44DE-93A8-63259CEA2AAB} {95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED} {B8A3E4CA-D54A-441F-A3BF-E00F060CA042} = {92463391-81BE-462B-AC3C-78C6C760741F} + {5257B25D-330A-4DCF-ACED-B4709CFBF916} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED} + {1D90F276-E1CA-4FDF-A173-EB889E7D3150} = {92463391-81BE-462B-AC3C-78C6C760741F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0035341D-175A-4D05-95E6-F1C2785A1E26} diff --git a/src/Microsoft.AspNetCore.Razor.Design/Microsoft.AspNetCore.Razor.Design.csproj b/src/Microsoft.AspNetCore.Razor.Design/Microsoft.AspNetCore.Razor.Design.csproj new file mode 100644 index 0000000000..809845ddcb --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/Microsoft.AspNetCore.Razor.Design.csproj @@ -0,0 +1,9 @@ + + + + Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor. + net46;netstandard2.0 + + + + diff --git a/src/Microsoft.AspNetCore.Razor.Design/baseline.netcore.json b/src/Microsoft.AspNetCore.Razor.Design/baseline.netcore.json new file mode 100644 index 0000000000..7a73a41bfd --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/baseline.netcore.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Design/baseline.netframework.json b/src/Microsoft.AspNetCore.Razor.Design/baseline.netframework.json new file mode 100644 index 0000000000..7a73a41bfd --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/baseline.netframework.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.props b/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.props new file mode 100644 index 0000000000..3855de69a6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.props @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.targets b/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.targets new file mode 100644 index 0000000000..bfba5fdf50 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/build/Microsoft.AspNetCore.Razor.Design.targets @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.props b/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.props new file mode 100644 index 0000000000..6f078c3657 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.targets b/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.targets new file mode 100644 index 0000000000..22c725f0f2 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Design/buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.targets @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs new file mode 100644 index 0000000000..3f04c34e3c --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs @@ -0,0 +1,46 @@ +// 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.Text; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + internal class Assert : Xunit.Assert + { + public static void BuildPassed(MSBuildResult result) + { + NotNull(result); + + if (result.ExitCode != 0) + { + throw new BuildFailedException(result); + } + } + + private class BuildFailedException : Xunit.Sdk.XunitException + { + public BuildFailedException(MSBuildResult result) + { + Result = result; + } + + public MSBuildResult Result { get; } + + public override string Message + { + get + { + var message = new StringBuilder(); + message.Append("Build failed: "); + message.Append(Result.FileName); + message.Append(" "); + message.Append(Result.Arguments); + message.AppendLine(); + message.AppendLine(); + message.Append(Result.Output); + return message.ToString(); + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/CleanProjectIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/CleanProjectIntegrationTest.cs new file mode 100644 index 0000000000..87c179fe33 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/CleanProjectIntegrationTest.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.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + public class CleanProjectIntegrationTest : MSBuildIntegrationTestBase + { + [Fact] + [InitializeTestProject("SimpleMvc")] + public async Task CleanProject_RunBuild() + { + var result = await DotnetMSBuild("Restore;Build"); // Equivalent to dotnet build + + Assert.BuildPassed(result); + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/InitializeTestProjectAttribute.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/InitializeTestProjectAttribute.cs new file mode 100644 index 0000000000..7074c440c8 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/InitializeTestProjectAttribute.cs @@ -0,0 +1,42 @@ +// 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.Reflection; +using Xunit.Sdk; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + public class InitializeTestProjectAttribute : BeforeAfterTestAttribute + { + private readonly string _projectName; + + public InitializeTestProjectAttribute(string projectName) + { + _projectName = projectName; + } + + public override void Before(MethodInfo methodUnderTest) + { + if (!typeof(MSBuildIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.DeclaringType.GetTypeInfo())) + { + throw new InvalidOperationException($"This should be used on a class derived from {typeof(MSBuildIntegrationTestBase)}"); + } + + MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_projectName); + } + + public override void After(MethodInfo methodUnderTest) + { + if (!typeof(MSBuildIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.DeclaringType.GetTypeInfo())) + { + throw new InvalidOperationException($"This should be used on a class derived from {typeof(MSBuildIntegrationTestBase)}"); + } + + MSBuildIntegrationTestBase.Project.Dispose(); + MSBuildIntegrationTestBase.Project = null; + } + + + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs new file mode 100644 index 0000000000..6384071810 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs @@ -0,0 +1,55 @@ +// 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.Diagnostics; +#if NET461 +using System.Runtime.Remoting; +using System.Runtime.Remoting.Messaging; +#else +using System.Threading; +#endif +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + public abstract class MSBuildIntegrationTestBase + { +#if NET461 +#elif NETCOREAPP2_0 || NETCOREAPP2_1 + private static readonly AsyncLocal _project = new AsyncLocal(); +#else +#error TFM not supported +#endif + + protected MSBuildIntegrationTestBase() + { + } + + // Used by the test framework to set the project that we're working with + internal static ProjectDirectory Project + { +#if NET461 + get + { + var handle = (ObjectHandle)CallContext.LogicalGetData("MSBuildIntegrationTestBase_Project"); + return (ProjectDirectory)handle.Unwrap(); + } + set + { + CallContext.LogicalSetData("MSBuildIntegrationTestBase_Project", new ObjectHandle(value)); + } +#elif NETCOREAPP2_0 || NETCOREAPP2_1 + get { return _project.Value; } + set { _project.Value = value; } +#else +#error TFM not supported +#endif + } + + internal Task DotnetMSBuild(string target) + { + return MSBuildProcessManager.RunProcessAsync($"/t:{target}", Project.DirectoryPath); + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs new file mode 100644 index 0000000000..622313a6f8 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs @@ -0,0 +1,82 @@ +// 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.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + internal static class MSBuildProcessManager + { + public static Task RunProcessAsync(string arguments, string workingDirectory, TimeSpan? timeout = null) + { + timeout = timeout ?? TimeSpan.FromSeconds(30); + + var process = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = "dotnet", + Arguments = "msbuild " + arguments, + WorkingDirectory = workingDirectory, + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardOutput = true, + }, + EnableRaisingEvents = true, + }; + + var completionSource = new TaskCompletionSource(); + var output = new StringBuilder(); + + process.Exited += Process_Exited; + process.ErrorDataReceived += Process_ErrorDataReceived; + process.OutputDataReceived += Process_OutputDataReceived; + + process.Start(); + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + + var timeoutTask = Task.Delay(timeout.Value).ContinueWith((t) => + { + // Don't timeout during debug sessions + while (Debugger.IsAttached) + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + } + + if (process.HasExited) + { + // This will happen on success, the 'real' task has already completed so this value will + // never be visible. + return (MSBuildResult)null; + } + + // This is a timeout. + process.Kill(); + throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {timeout}."); + }); + + return Task.WhenAny(completionSource.Task, timeoutTask).Unwrap(); + + void Process_Exited(object sender, EventArgs e) + { + var result = new MSBuildResult(process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, output.ToString()); + completionSource.SetResult(result); + } + + void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + output.AppendLine(e.Data); + } + + void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + output.AppendLine(e.Data); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildResult.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildResult.cs new file mode 100644 index 0000000000..dc815354e3 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildResult.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. + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + internal class MSBuildResult + { + public MSBuildResult(string fileName, string arguments, int exitCode, string output) + { + FileName = fileName; + Arguments = arguments; + ExitCode = exitCode; + Output = output; + } + + public string Arguments { get; } + + public string FileName { get; } + + public int ExitCode { get; } + + public string Output { get; } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs new file mode 100644 index 0000000000..4ba465412d --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs @@ -0,0 +1,116 @@ +// 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.IO; +using System.Linq; +using System.Threading; +using Microsoft.AspNetCore.Testing; + +namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests +{ + internal class ProjectDirectory : IDisposable + { + public static ProjectDirectory Create(string projectName) + { + var destinationPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(destinationPath); + + try + { + if (Directory.EnumerateFiles(destinationPath).Any()) + { + throw new InvalidOperationException($"{destinationPath} should be empty"); + } + + var solutionRoot = TestPathUtilities.GetSolutionRootDirectory("Razor"); + if (solutionRoot == null) + { + throw new InvalidOperationException("Could not find solution root."); + } + + var projectRoot = Path.Combine(solutionRoot, "test", "testapps", projectName); + if (!Directory.Exists(projectRoot)) + { + throw new InvalidOperationException($"Could not find project at '{projectRoot}'"); + } + + CopyDirectory(new DirectoryInfo(projectRoot), new DirectoryInfo(destinationPath)); + + foreach (var project in Directory.EnumerateFiles(destinationPath, "*.csproj")) + { + RewriteCsproj(projectRoot, project); + } + + return new ProjectDirectory(destinationPath); + } + catch + { + CleanupDirectory(destinationPath); + throw; + } + + void CopyDirectory(DirectoryInfo source, DirectoryInfo destination) + { + foreach (var directory in source.EnumerateDirectories()) + { + if (directory.Name == "bin" || directory.Name == "obj") + { + // Just in case someone has opened the project in an IDE or built it. We don't want to copy + // these folders. + continue; + } + + var created = destination.CreateSubdirectory(directory.Name); + CopyDirectory(directory, created); + } + + foreach (var file in source.EnumerateFiles()) + { + file.CopyTo(Path.Combine(destination.FullName, file.Name)); + } + } + + void RewriteCsproj(string originalProjectRoot, string filePath) + { + // We need to replace $(OriginalProjectRoot) with the path to the original directory + // that way relative references will resolve. + var text = File.ReadAllText(filePath); + text = text.Replace("$(OriginalProjectRoot)", originalProjectRoot); + File.WriteAllText(filePath, text); + } + } + + private ProjectDirectory(string directoryPath) + { + DirectoryPath = directoryPath; + } + + public string DirectoryPath { get; } + + public void Dispose() + { + CleanupDirectory(DirectoryPath); + } + + private static void CleanupDirectory(string filePath) + { + var tries = 5; + var sleep = TimeSpan.FromSeconds(3); + + for (var i = 0; i < tries; i++) + { + try + { + Directory.Delete(filePath, recursive: true); + return; + } + catch when (i < tries - 1) + { + Console.WriteLine($"Failed to delete directory {filePath}, trying again."); + Thread.Sleep(sleep); + } + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/Microsoft.AspNetCore.Razor.Design.Test.csproj b/test/Microsoft.AspNetCore.Razor.Design.Test/Microsoft.AspNetCore.Razor.Design.Test.csproj new file mode 100644 index 0000000000..ee6b42beb0 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/Microsoft.AspNetCore.Razor.Design.Test.csproj @@ -0,0 +1,21 @@ + + + + $(StandardTestTfms) + true + $(DefaultItemExcludes);TestFiles\** + + + + + + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/xunit.runner.json b/test/Microsoft.AspNetCore.Razor.Design.Test/xunit.runner.json new file mode 100644 index 0000000000..fcf172c8fc --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "methodDisplay": "method", + "shadowCopy": false +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Test.MvcShim/Microsoft.AspNetCore.Razor.Test.MvcShim.csproj b/test/Microsoft.AspNetCore.Razor.Test.MvcShim/Microsoft.AspNetCore.Razor.Test.MvcShim.csproj index 0fe0b6a3fc..9583421ebb 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.MvcShim/Microsoft.AspNetCore.Razor.Test.MvcShim.csproj +++ b/test/Microsoft.AspNetCore.Razor.Test.MvcShim/Microsoft.AspNetCore.Razor.Test.MvcShim.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + $(StandardTestTfms);netstandard2.0 true diff --git a/test/testapps/SimpleMvc/Models/ErrorViewModel.cs b/test/testapps/SimpleMvc/Models/ErrorViewModel.cs new file mode 100644 index 0000000000..b4aa044914 --- /dev/null +++ b/test/testapps/SimpleMvc/Models/ErrorViewModel.cs @@ -0,0 +1,11 @@ +using System; + +namespace SimpleMvc.Models +{ + public class ErrorViewModel + { + public string RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + } +} \ No newline at end of file diff --git a/test/testapps/SimpleMvc/Program.cs b/test/testapps/SimpleMvc/Program.cs new file mode 100644 index 0000000000..3e58606bdf --- /dev/null +++ b/test/testapps/SimpleMvc/Program.cs @@ -0,0 +1,10 @@ + +namespace SimpleMvc +{ + public class Program + { + public static void Main(string[] args) + { + } + } +} diff --git a/test/testapps/SimpleMvc/SimpleMvc.csproj b/test/testapps/SimpleMvc/SimpleMvc.csproj new file mode 100644 index 0000000000..266f837eb9 --- /dev/null +++ b/test/testapps/SimpleMvc/SimpleMvc.csproj @@ -0,0 +1,11 @@ + + + netcoreapp2.0 + + + + + + + + diff --git a/test/testapps/SimpleMvc/Views/Home/About.cshtml b/test/testapps/SimpleMvc/Views/Home/About.cshtml new file mode 100644 index 0000000000..3674e37a86 --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Home/About.cshtml @@ -0,0 +1,7 @@ +@{ + ViewData["Title"] = "About"; +} +

@ViewData["Title"]

+

@ViewData["Message"]

+ +

Use this area to provide additional information.

diff --git a/test/testapps/SimpleMvc/Views/Home/Contact.cshtml b/test/testapps/SimpleMvc/Views/Home/Contact.cshtml new file mode 100644 index 0000000000..a11a1867cf --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Home/Contact.cshtml @@ -0,0 +1,17 @@ +@{ + ViewData["Title"] = "Contact"; +} +

@ViewData["Title"]

+

@ViewData["Message"]

+ +
+ One Microsoft Way
+ Redmond, WA 98052-6399
+ P: + 425.555.0100 +
+ +
+ Support: Support@example.com
+ Marketing: Marketing@example.com +
diff --git a/test/testapps/SimpleMvc/Views/Home/Index.cshtml b/test/testapps/SimpleMvc/Views/Home/Index.cshtml new file mode 100644 index 0000000000..00afab6a0c --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Home/Index.cshtml @@ -0,0 +1,108 @@ +@{ + ViewData["Title"] = "Home Page"; +} + + + + diff --git a/test/testapps/SimpleMvc/Views/Shared/Error.cshtml b/test/testapps/SimpleMvc/Views/Shared/Error.cshtml new file mode 100644 index 0000000000..ec2ea6bd03 --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Shared/Error.cshtml @@ -0,0 +1,22 @@ +@model ErrorViewModel +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+ +@if (Model.ShowRequestId) +{ +

+ Request ID: @Model.RequestId +

+} + +

Development Mode

+

+ Swapping to Development environment will display more detailed information about the error that occurred. +

+

+ Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. +

diff --git a/test/testapps/SimpleMvc/Views/Shared/_Layout.cshtml b/test/testapps/SimpleMvc/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000000..1a9473e464 --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Shared/_Layout.cshtml @@ -0,0 +1,71 @@ + + + + + + @ViewData["Title"] - SimpleMvc + + + + + + + + + + + + +
+ @RenderBody() +
+
+

© 2017 - SimpleMvc

+
+
+ + + + + + + + + + + + + @RenderSection("Scripts", required: false) + + diff --git a/test/testapps/SimpleMvc/Views/Shared/_ValidationScriptsPartial.cshtml b/test/testapps/SimpleMvc/Views/Shared/_ValidationScriptsPartial.cshtml new file mode 100644 index 0000000000..a699aafa97 --- /dev/null +++ b/test/testapps/SimpleMvc/Views/Shared/_ValidationScriptsPartial.cshtml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/test/testapps/SimpleMvc/Views/_ViewImports.cshtml b/test/testapps/SimpleMvc/Views/_ViewImports.cshtml new file mode 100644 index 0000000000..da00289ea5 --- /dev/null +++ b/test/testapps/SimpleMvc/Views/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using SimpleMvc +@using SimpleMvc.Models +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/test/testapps/SimpleMvc/Views/_ViewStart.cshtml b/test/testapps/SimpleMvc/Views/_ViewStart.cshtml new file mode 100644 index 0000000000..a5f10045db --- /dev/null +++ b/test/testapps/SimpleMvc/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +}