diff --git a/build/common.props b/build/common.props index 89ade5d..72ab892 100644 --- a/build/common.props +++ b/build/common.props @@ -16,7 +16,8 @@ - + + diff --git a/build/dependencies.props b/build/dependencies.props index 4370015..639387b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,10 +2,10 @@ 2.0.0-* 5.0.2 - 4.3.0 2.1.0-* 10.0.1 $(BundledNETStandardPackageVersion) + 2.0.0-* 2.0.0-* 4.7.0 diff --git a/build/repo.targets b/build/repo.targets deleted file mode 100644 index 537aa36..0000000 --- a/build/repo.targets +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - diff --git a/samples/misc/LatencyTest/LatencyTest.csproj b/samples/misc/LatencyTest/LatencyTest.csproj index 8c17cdb..43d5f17 100644 --- a/samples/misc/LatencyTest/LatencyTest.csproj +++ b/samples/misc/LatencyTest/LatencyTest.csproj @@ -1,9 +1,9 @@  - + - netcoreapp2.0 + netcoreapp2.0;net461 false exe diff --git a/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj b/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj index 0604193..4bbb9ec 100644 --- a/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj +++ b/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj @@ -1,9 +1,9 @@ - + - netcoreapp2.0 + netcoreapp2.0;net461 true false diff --git a/samples/misc/Webpack/ActionResults/PrerenderResult.cs b/samples/misc/Webpack/ActionResults/PrerenderResult.cs index e80b5b1..4f2c8f5 100644 --- a/samples/misc/Webpack/ActionResults/PrerenderResult.cs +++ b/samples/misc/Webpack/ActionResults/PrerenderResult.cs @@ -27,6 +27,7 @@ namespace Webpack.ActionResults { var nodeServices = context.HttpContext.RequestServices.GetRequiredService(); var hostEnv = context.HttpContext.RequestServices.GetRequiredService(); + var applicationLifetime = context.HttpContext.RequestServices.GetRequiredService(); var applicationBasePath = hostEnv.ContentRootPath; var request = context.HttpContext.Request; var response = context.HttpContext.Response; @@ -34,6 +35,7 @@ namespace Webpack.ActionResults var prerenderedHtml = await Prerenderer.RenderToString( applicationBasePath, nodeServices, + applicationLifetime.ApplicationStopping, _moduleExport, request.GetEncodedUrl(), request.Path + request.QueryString.Value, diff --git a/samples/misc/Webpack/Webpack.csproj b/samples/misc/Webpack/Webpack.csproj index 9cabae2..eedacab 100644 --- a/samples/misc/Webpack/Webpack.csproj +++ b/samples/misc/Webpack/Webpack.csproj @@ -1,9 +1,9 @@ - + - netcoreapp2.0 + netcoreapp2.0;net461 true false diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj b/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj index 8ebd6a6..91b1a4b 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj @@ -4,7 +4,7 @@ Socket-based RPC for Microsoft.AspNetCore.NodeServices. - netcoreapp2.0 + netstandard2.0 aspnetcore;aspnetcoremvc;nodeservices true @@ -15,14 +15,6 @@ - - - - - - - - diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs index d50d146..5fcd667 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs @@ -18,11 +18,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections PipeDirection.InOut, PipeOptions.Asynchronous); -#if NET451 - _namedPipeClientStream.Connect(); -#else await _namedPipeClientStream.ConnectAsync().ConfigureAwait(false); -#endif return _namedPipeClientStream; } diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs index 535a762..cbd1f99 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs @@ -11,9 +11,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections public static StreamConnection Create() { -#if NET451 - return new NamedPipeConnection(); -#else var useNamedPipes = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( System.Runtime.InteropServices.OSPlatform.Windows); if (useNamedPipes) @@ -24,7 +21,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections { return new UnixDomainSocketConnection(); } -#endif } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs index 1f12a71..6e7ebac 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs @@ -10,16 +10,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections private NetworkStream _networkStream; private Socket _socket; -#if NET451 - public override Task Open(string address) - { - // The 'null' assignments avoid the compiler warnings about unassigned fields. - // Note that this whole class isn't supported on .NET 4.5.1, since that's not cross-platform. - _networkStream = null; - _socket = null; - throw new System.PlatformNotSupportedException(); - } -#else public override async Task Open(string address) { var endPoint = new UnixDomainSocketEndPoint("/tmp/" + address); @@ -28,7 +18,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections _networkStream = new NetworkStream(_socket); return _networkStream; } -#endif public override void Dispose() { diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs index ff43b01..b001163 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs @@ -59,11 +59,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections } else { -#if NET451 - _encodedPath = new byte[0]; -#else _encodedPath = Array.Empty(); -#endif _path = string.Empty; } } diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs index b656978..1e6afd1 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs @@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets options.ProjectPath, options.WatchFileExtensions, MakeNewCommandLineOptions(socketAddress), + options.ApplicationStoppingToken, options.NodeInstanceOutputLogger, options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/VirtualConnections/VirtualConnection.cs b/src/Microsoft.AspNetCore.NodeServices.Sockets/VirtualConnections/VirtualConnection.cs index 611dff1..391b1f7 100644 --- a/src/Microsoft.AspNetCore.NodeServices.Sockets/VirtualConnections/VirtualConnection.cs +++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/VirtualConnections/VirtualConnection.cs @@ -12,11 +12,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections /// internal class VirtualConnection : Stream { -#if NET451 - private readonly static Task CompletedTask = Task.FromResult((object)null); -#else private readonly static Task CompletedTask = Task.CompletedTask; -#endif private VirtualConnectionClient _host; private readonly BufferBlock _receivedDataQueue = new BufferBlock(); private ArraySegment _receivedDataNotYetUsed; diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs index 43d703b..73dd228 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using Microsoft.AspNetCore.NodeServices.HostingModels; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; @@ -42,6 +43,12 @@ namespace Microsoft.AspNetCore.NodeServices EnvironmentVariables["NODE_ENV"] = hostEnv.IsDevelopment() ? "development" : "production"; // De-facto standard values for Node } + var applicationLifetime = serviceProvider.GetService(); + if (applicationLifetime != null) + { + ApplicationStoppingToken = applicationLifetime.ApplicationStopping; + } + // If the DI system gives us a logger, use it. Otherwise, set up a default one. var loggerFactory = serviceProvider.GetService(); NodeInstanceOutputLogger = loggerFactory != null @@ -93,5 +100,10 @@ namespace Microsoft.AspNetCore.NodeServices /// Specifies the maximum duration, in milliseconds, that your .NET code should wait for Node.js RPC calls to return. /// public int InvocationTimeoutMilliseconds { get; set; } + + /// + /// A token that indicates when the host application is stopping. + /// + public CancellationToken ApplicationStoppingToken { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs index 8beea51..b1b0fe9 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs @@ -42,6 +42,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels options.ProjectPath, options.WatchFileExtensions, MakeCommandLineOptions(port), + options.ApplicationStoppingToken, options.NodeInstanceOutputLogger, options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs index 7f6f172..e353292 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs @@ -45,6 +45,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels /// The root path of the current project. This is used when resolving Node.js module paths relative to the project root. /// The filename extensions that should be watched within the project root. The Node instance will automatically shut itself down if any matching file changes. /// Additional command-line arguments to be passed to the Node.js instance. + /// A token that indicates when the host application is stopping. /// The to which the Node.js instance's stdout/stderr (and other log information) should be written. /// Environment variables to be set on the Node.js process. /// The maximum duration, in milliseconds, to wait for RPC calls to complete. @@ -55,6 +56,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels string projectPath, string[] watchFileExtensions, string commandLineArguments, + CancellationToken applicationStoppingToken, ILogger nodeOutputLogger, IDictionary environmentVars, int invocationTimeoutMilliseconds, @@ -67,7 +69,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels } OutputLogger = nodeOutputLogger; - _entryPointScript = new StringAsTempFile(entryPointScript); + _entryPointScript = new StringAsTempFile(entryPointScript, applicationStoppingToken); _invocationTimeoutMilliseconds = invocationTimeoutMilliseconds; _launchWithDebugging = launchWithDebugging; @@ -315,11 +317,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels private static void SetEnvironmentVariable(ProcessStartInfo startInfo, string name, string value) { -#if NET451 - startInfo.EnvironmentVariables[name] = value; -#else startInfo.Environment[name] = value; -#endif } private static Process LaunchNodeProcess(ProcessStartInfo startInfo) diff --git a/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj b/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj index f5be3ac..cbf7828 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj +++ b/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj @@ -4,7 +4,7 @@ Invoke Node.js modules at runtime in ASP.NET Core applications. - netcoreapp2.0 + netstandard2.0 aspnetcore;aspnetcoremvc;nodeservices true true @@ -20,12 +20,6 @@ - - - - - - diff --git a/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs b/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs index 22f4b01..c15bca3 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; namespace Microsoft.AspNetCore.NodeServices { @@ -11,27 +12,21 @@ namespace Microsoft.AspNetCore.NodeServices private bool _disposedValue; private bool _hasDeletedTempFile; private object _fileDeletionLock = new object(); + private IDisposable _applicationLifetimeRegistration; /// /// Create a new instance of . /// /// The contents of the temporary file to be created. - public StringAsTempFile(string content) + /// A token that indicates when the host application is stopping. + public StringAsTempFile(string content, CancellationToken applicationStoppingToken) { FileName = Path.GetTempFileName(); File.WriteAllText(FileName, content); // Because .NET finalizers don't reliably run when the process is terminating, also // add event handlers for other shutdown scenarios. -#if NET451 - AppDomain.CurrentDomain.ProcessExit += HandleProcessExit; - AppDomain.CurrentDomain.DomainUnload += HandleProcessExit; -#else - // Note that this still doesn't capture SIGKILL (at least on macOS) - there doesn't - // appear to be a way of doing that. So in that case, the temporary file will be - // left behind. - System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += HandleAssemblyUnloading; -#endif + _applicationLifetimeRegistration = applicationStoppingToken.Register(EnsureTempFileDeleted); } /// @@ -55,12 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices if (disposing) { // Dispose managed state -#if NET451 - AppDomain.CurrentDomain.ProcessExit -= HandleProcessExit; - AppDomain.CurrentDomain.DomainUnload -= HandleProcessExit; -#else - System.Runtime.Loader.AssemblyLoadContext.Default.Unloading -= HandleAssemblyUnloading; -#endif + _applicationLifetimeRegistration.Dispose(); } EnsureTempFileDeleted(); @@ -81,18 +71,6 @@ namespace Microsoft.AspNetCore.NodeServices } } -#if NET451 - private void HandleProcessExit(object sender, EventArgs args) - { - EnsureTempFileDeleted(); - } -#else - private void HandleAssemblyUnloading(System.Runtime.Loader.AssemblyLoadContext context) - { - EnsureTempFileDeleted(); - } -#endif - /// /// Implements the finalization part of the IDisposable pattern by calling Dispose(false). /// diff --git a/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj b/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj index 53d7c7b..5d90573 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj +++ b/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj @@ -4,7 +4,7 @@ Helpers for building single-page applications on ASP.NET MVC Core. - netcoreapp2.0 + netstandard2.0 aspnetcore;aspnetcoremvc;nodeservices true true @@ -13,7 +13,8 @@ - + + diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs index bad274f..c2c5308 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Features; @@ -24,6 +25,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering private static INodeServices _fallbackNodeServices; // Used only if no INodeServices was registered with DI private readonly string _applicationBasePath; + private readonly CancellationToken _applicationStoppingToken; private readonly INodeServices _nodeServices; /// @@ -35,6 +37,9 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering var hostEnv = (IHostingEnvironment) serviceProvider.GetService(typeof(IHostingEnvironment)); _nodeServices = (INodeServices) serviceProvider.GetService(typeof(INodeServices)) ?? _fallbackNodeServices; _applicationBasePath = hostEnv.ContentRootPath; + + var applicationLifetime = (IApplicationLifetime) serviceProvider.GetService(typeof(IApplicationLifetime)); + _applicationStoppingToken = applicationLifetime.ApplicationStopping; // Consider removing the following. Having it means you can get away with not putting app.AddNodeServices() // in your startup file, but then again it might be confusing that you don't need to. @@ -101,6 +106,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering var result = await Prerenderer.RenderToString( _applicationBasePath, _nodeServices, + _applicationStoppingToken, new JavaScriptModuleExport(ModuleName) { ExportName = ExportName diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs index 43c2ed0..e7ce841 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.NodeServices; @@ -9,22 +10,16 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering /// public static class Prerenderer { - private static readonly Lazy NodeScript; + private static readonly object CreateNodeScriptLock = new object(); - static Prerenderer() - { - NodeScript = new Lazy(() => - { - var script = EmbeddedResourceReader.Read(typeof(Prerenderer), "/Content/Node/prerenderer.js"); - return new StringAsTempFile(script); // Will be cleaned up on process exit - }); - } + private static StringAsTempFile NodeScript; /// /// Performs server-side prerendering by invoking code in Node.js. /// /// The root path to your application. This is used when resolving project-relative paths. /// The instance of that will be used to invoke JavaScript code. + /// A token that indicates when the host application is stopping. /// The path to the JavaScript file containing the prerendering logic. /// The URL of the currently-executing HTTP request. This is supplied to the prerendering code. /// The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code. @@ -35,6 +30,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering public static Task RenderToString( string applicationBasePath, INodeServices nodeServices, + CancellationToken applicationStoppingToken, JavaScriptModuleExport bootModule, string requestAbsoluteUrl, string requestPathAndQuery, @@ -43,7 +39,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering string requestPathBase) { return nodeServices.InvokeExportAsync( - NodeScript.Value.FileName, + GetNodeScriptFilename(applicationStoppingToken), "renderToString", applicationBasePath, bootModule, @@ -53,5 +49,19 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering timeoutMilliseconds, requestPathBase); } + + private static string GetNodeScriptFilename(CancellationToken applicationStoppingToken) + { + lock(CreateNodeScriptLock) + { + if (NodeScript == null) + { + var script = EmbeddedResourceReader.Read(typeof(Prerenderer), "/Content/Node/prerenderer.js"); + NodeScript = new StringAsTempFile(script, applicationStoppingToken); // Will be cleaned up on process exit + } + } + + return NodeScript.FileName; + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs index 8afd7b6..9f02223 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs @@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Builder // Get a filename matching the middleware Node script var script = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware), "/Content/Node/webpack-dev-middleware.js"); - var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit + var nodeScript = new StringAsTempFile(script, nodeServicesOptions.ApplicationStoppingToken); // Will be cleaned up on process exit // Ideally, this would be relative to the application's PathBase (so it could work in virtual directories) // but it's not clear that such information exists during application startup, as opposed to within the context diff --git a/templates/AngularSpa/AngularSpa.csproj b/templates/AngularSpa/AngularSpa.csproj index 96f705d..7ff4100 100644 --- a/templates/AngularSpa/AngularSpa.csproj +++ b/templates/AngularSpa/AngularSpa.csproj @@ -9,7 +9,6 @@ - diff --git a/templates/AureliaSpa/AureliaSpa.csproj b/templates/AureliaSpa/AureliaSpa.csproj index 4fd7951..ff88f56 100644 --- a/templates/AureliaSpa/AureliaSpa.csproj +++ b/templates/AureliaSpa/AureliaSpa.csproj @@ -9,7 +9,6 @@ - diff --git a/templates/KnockoutSpa/KnockoutSpa.csproj b/templates/KnockoutSpa/KnockoutSpa.csproj index 4fd7951..ff88f56 100644 --- a/templates/KnockoutSpa/KnockoutSpa.csproj +++ b/templates/KnockoutSpa/KnockoutSpa.csproj @@ -9,7 +9,6 @@ - diff --git a/templates/ReactReduxSpa/ReactReduxSpa.csproj b/templates/ReactReduxSpa/ReactReduxSpa.csproj index 96f705d..7ff4100 100644 --- a/templates/ReactReduxSpa/ReactReduxSpa.csproj +++ b/templates/ReactReduxSpa/ReactReduxSpa.csproj @@ -9,7 +9,6 @@ - diff --git a/templates/ReactSpa/ReactSpa.csproj b/templates/ReactSpa/ReactSpa.csproj index 4fd7951..ff88f56 100644 --- a/templates/ReactSpa/ReactSpa.csproj +++ b/templates/ReactSpa/ReactSpa.csproj @@ -9,7 +9,6 @@ - diff --git a/templates/VueSpa/VueSpa.csproj b/templates/VueSpa/VueSpa.csproj index 4fd7951..ff88f56 100644 --- a/templates/VueSpa/VueSpa.csproj +++ b/templates/VueSpa/VueSpa.csproj @@ -9,7 +9,6 @@ -