diff --git a/src/Microsoft.AspNetCore.AngularServices/PrimeCacheHelper.cs b/src/Microsoft.AspNetCore.AngularServices/PrimeCacheHelper.cs index 388ab06..b2153c7 100644 --- a/src/Microsoft.AspNetCore.AngularServices/PrimeCacheHelper.cs +++ b/src/Microsoft.AspNetCore.AngularServices/PrimeCacheHelper.cs @@ -9,14 +9,31 @@ using Newtonsoft.Json; namespace Microsoft.AspNetCore.AngularServices { + /// + /// Helpers for prepopulating Angular 2's 'http' service with data. + /// public static class PrimeCacheHelper { + /// + /// Performs an HTTP GET request to the specified URL and adds the resulting JSON data + /// to the Angular 'http' service cache. + /// + /// The . + /// The URL to be requested. + /// A task representing the HTML content to be rendered into the document. [Obsolete("Use PrimeCacheAsync instead")] public static Task PrimeCache(this IHtmlHelper html, string url) { return PrimeCacheAsync(html, url); } + /// + /// Performs an HTTP GET request to the specified URL and adds the resulting JSON data + /// to the Angular 'http' service cache. + /// + /// The . + /// The URL to be requested. + /// A task representing the HTML content to be rendered into the document. public static async Task PrimeCacheAsync(this IHtmlHelper html, string url) { // TODO: Consider deduplicating the PrimeCacheAsync calls (that is, if there are multiple requests to precache diff --git a/src/Microsoft.AspNetCore.AngularServices/project.json b/src/Microsoft.AspNetCore.AngularServices/project.json index c6c0d57..c6341f9 100644 --- a/src/Microsoft.AspNetCore.AngularServices/project.json +++ b/src/Microsoft.AspNetCore.AngularServices/project.json @@ -14,7 +14,8 @@ }, "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "xmlDoc": true }, "dependencies": { "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1", diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs index eacca81..a1c9c12 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs @@ -1,8 +1,18 @@ namespace Microsoft.AspNetCore.NodeServices { + /// + /// Represents a way of creating and invoking code in a Node.js environment. + /// public enum NodeHostingModel { + /// + /// An out-of-process Node.js instance where RPC calls are made via HTTP. + /// Http, + + /// + /// An out-of-process Node.js instance where RPC calls are made over binary sockets. + /// Socket, } } diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs index d6660c0..73db500 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs @@ -3,8 +3,16 @@ using Microsoft.AspNetCore.NodeServices.HostingModels; namespace Microsoft.AspNetCore.NodeServices { + /// + /// Supplies INodeServices instances. + /// public static class NodeServicesFactory { + /// + /// Create an instance according to the supplied options. + /// + /// Options for creating the instance. + /// An instance. public static INodeServices CreateNodeServices(NodeServicesOptions options) { if (options == null) diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs index dbf1ce6..5324f13 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs @@ -8,14 +8,25 @@ using Microsoft.Extensions.Logging.Console; namespace Microsoft.AspNetCore.NodeServices { + /// + /// Describes options used to configure an instance. + /// public class NodeServicesOptions { + /// + /// Defines the default . + /// public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http; + internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds); private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000; private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices"; private static readonly string[] DefaultWatchFileExtensions = { ".js", ".jsx", ".ts", ".tsx", ".json", ".html" }; + /// + /// Creates a new instance of . + /// + /// The . public NodeServicesOptions(IServiceProvider serviceProvider) { if (serviceProvider == null) @@ -44,14 +55,49 @@ namespace Microsoft.AspNetCore.NodeServices : new ConsoleLogger(LogCategoryName, null, false); } + /// + /// Specifies which should be used. + /// public NodeHostingModel HostingModel { get; set; } + + /// + /// If set, this callback function will be invoked to supply the instance. + /// public Func NodeInstanceFactory { get; set; } + + /// + /// If set, overrides the path to the root of your application. This path is used when locating Node.js modules relative to your project. + /// public string ProjectPath { get; set; } + + /// + /// If set, the Node.js instance should restart when any matching file on disk within your project changes. + /// public string[] WatchFileExtensions { get; set; } + + /// + /// The Node.js instance's stdout/stderr will be redirected to this . + /// public ILogger NodeInstanceOutputLogger { get; set; } + + /// + /// If true, the Node.js instance will accept incoming V8 debugger connections (e.g., from node-inspector). + /// public bool LaunchWithDebugging { get; set; } - public IDictionary EnvironmentVariables { get; set; } + + /// + /// If is true, the Node.js instance will listen for V8 debugger connections on this port. + /// public int DebuggingPort { get; set; } + + /// + /// If set, starts the Node.js instance with the specified environment variables. + /// + public IDictionary EnvironmentVariables { get; set; } + + /// + /// Specifies the maximum duration, in milliseconds, that your .NET code should wait for Node.js RPC calls to return. + /// public int InvocationTimeoutMilliseconds { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesServiceCollectionExtensions.cs index e2f516e..bc453ae 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesServiceCollectionExtensions.cs @@ -8,9 +8,18 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class NodeServicesServiceCollectionExtensions { + /// + /// Adds NodeServices support to the . + /// + /// The . public static void AddNodeServices(this IServiceCollection serviceCollection) => AddNodeServices(serviceCollection, _ => {}); + /// + /// Adds NodeServices support to the . + /// + /// The . + /// Options for configuring the instances. [Obsolete("Use the AddNodeServices(Action setupAction) overload instead.")] public static void AddNodeServices(this IServiceCollection serviceCollection, NodeServicesOptions options) { @@ -20,6 +29,11 @@ namespace Microsoft.Extensions.DependencyInjection }); } + /// + /// Adds NodeServices support to the . + /// + /// The . + /// A callback that will be invoked to populate the . public static void AddNodeServices(this IServiceCollection serviceCollection, Action setupAction) { if (setupAction == null) diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/INodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/INodeInstance.cs index 68a4319..a1ce021 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/INodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/INodeInstance.cs @@ -4,8 +4,20 @@ using System.Threading.Tasks; namespace Microsoft.AspNetCore.NodeServices.HostingModels { + /// + /// Represents an instance of Node.js to which Remote Procedure Calls (RPC) may be sent. + /// public interface INodeInstance : IDisposable { + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// A that can be used to cancel the invocation. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked. + /// If set, specifies the CommonJS export to be invoked. If not set, the module's default CommonJS export itself must be a function to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. Task InvokeExportAsync(CancellationToken cancellationToken, string moduleName, string exportNameOrNull, params object[] args); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationException.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationException.cs index 733af44..c793ae0 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationException.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationException.cs @@ -2,15 +2,33 @@ using System; namespace Microsoft.AspNetCore.NodeServices.HostingModels { + /// + /// Represents an exception caused by invoking Node.js code. + /// public class NodeInvocationException : Exception { + /// + /// If true, indicates that the invocation failed because the Node.js instance could not be reached. For example, + /// it might have already shut down or previously crashed. + /// public bool NodeInstanceUnavailable { get; private set; } + /// + /// Creates a new instance of . + /// + /// A description of the exception. + /// Additional information, such as a Node.js stack trace, representing the exception. public NodeInvocationException(string message, string details) : base(message + Environment.NewLine + details) { } + /// + /// Creates a new instance of . + /// + /// A description of the exception. + /// Additional information, such as a Node.js stack trace, representing the exception. + /// Specifies a value for the flag. public NodeInvocationException(string message, string details, bool nodeInstanceUnavailable) : this(message, details) { diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationInfo.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationInfo.cs index 92d96f8..86c4273 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationInfo.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeInvocationInfo.cs @@ -1,9 +1,24 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels { + /// + /// Describes an RPC call sent from .NET code to Node.js code. + /// public class NodeInvocationInfo { + /// + /// Specifies the path to the Node.js module (i.e., .js file) relative to the project root. + /// public string ModuleName { get; set; } + + /// + /// If set, specifies the name of CommonJS function export to be invoked. + /// If not set, the Node.js module's default export must itself be a function to be invoked. + /// public string ExportedFunctionName { get; set; } + + /// + /// A sequence of JSON-serializable arguments to be passed to the Node.js function being invoked. + /// public object[] Args { get; set; } } } diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs index 3957cb0..9bbd805 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/OutOfProcessNodeInstance.cs @@ -21,7 +21,11 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels /// public abstract class OutOfProcessNodeInstance : INodeInstance { + /// + /// The to which the Node.js instance's stdout/stderr is being redirected. + /// protected readonly ILogger OutputLogger; + private const string ConnectionEstablishedMessage = "[Microsoft.AspNetCore.NodeServices:Listening]"; private const string DebuggingStartedMessageFormat = @"----- *** Node.js debugging is enabled *** @@ -43,6 +47,18 @@ If you haven't yet installed node-inspector, you can do so as follows: private bool _nodeProcessNeedsRestart; private readonly string[] _watchFileExtensions; + /// + /// Creates a new instance of . + /// + /// The path to the entry point script that the Node instance should load and execute. + /// 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. + /// 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. + /// If true, passes a flag to the Node.js process telling it to accept V8 debugger connections. + /// If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port. public OutOfProcessNodeInstance( string entryPointScript, string projectPath, @@ -71,6 +87,15 @@ If you haven't yet installed node-inspector, you can do so as follows: ConnectToInputOutputStreams(); } + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// A that can be used to cancel the invocation. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked. + /// If set, specifies the CommonJS export to be invoked. If not set, the module's default CommonJS export itself must be a function to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. public async Task InvokeExportAsync( CancellationToken cancellationToken, string moduleName, string exportNameOrNull, params object[] args) { @@ -154,21 +179,41 @@ If you haven't yet installed node-inspector, you can do so as follows: } } + /// + /// Disposes this instance. + /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// Specifies the Node.js function to be invoked and arguments to be passed to it. + /// A that can be used to cancel the invocation. + /// A representing the completion of the RPC call. protected abstract Task InvokeExportAsync( NodeInvocationInfo invocationInfo, CancellationToken cancellationToken); - // This method is virtual, as it provides a way to override the NODE_PATH or the path to node.exe + /// + /// Configures a instance describing how to launch the Node.js process. + /// + /// The entrypoint JavaScript file that the Node.js process should execute. + /// The root path of the project. This is used when locating Node.js modules relative to the project root. + /// Command-line arguments to be passed to the Node.js process. + /// Environment variables to be set on the Node.js process. + /// If true, passes a flag to the Node.js process telling it to accept V8 debugger connections. + /// If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port. + /// protected virtual ProcessStartInfo PrepareNodeProcessStartInfo( string entryPointFilename, string projectPath, string commandLineArguments, IDictionary environmentVars, bool launchWithDebugging, int debuggingPort) { + // This method is virtual, as it provides a way to override the NODE_PATH or the path to node.exe string debuggingArgs; if (launchWithDebugging) { @@ -217,16 +262,28 @@ If you haven't yet installed node-inspector, you can do so as follows: return startInfo; } + /// + /// Virtual method invoked whenever the Node.js process emits a line to its stdout. + /// + /// The line emitted to the Node.js process's stdout. protected virtual void OnOutputDataReceived(string outputData) { OutputLogger.LogInformation(outputData); } + /// + /// Virtual method invoked whenever the Node.js process emits a line to its stderr. + /// + /// The line emitted to the Node.js process's stderr. protected virtual void OnErrorDataReceived(string errorData) { OutputLogger.LogError(errorData); } + /// + /// Disposes the instance. + /// + /// True if the object is disposing or false if it is finalizing. protected virtual void Dispose(bool disposing) { if (!_disposed) @@ -403,6 +460,9 @@ If you haven't yet installed node-inspector, you can do so as follows: EnsureFileSystemWatcherIsDisposed(); } + /// + /// Implements the finalization part of the IDisposable pattern by calling Dispose(false). + /// ~OutOfProcessNodeInstance() { Dispose(false); diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/VirtualConnections/VirtualConnectionClient.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/VirtualConnections/VirtualConnectionClient.cs index f5e2d62..e591c46 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/VirtualConnections/VirtualConnectionClient.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/VirtualConnections/VirtualConnectionClient.cs @@ -7,6 +7,10 @@ using System.Threading.Tasks; namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections { + /// + /// A callback that will be invoked if the encounters a read error. + /// + /// public delegate void VirtualConnectionReadErrorHandler(Exception ex); /// diff --git a/src/Microsoft.AspNetCore.NodeServices/INodeServices.cs b/src/Microsoft.AspNetCore.NodeServices/INodeServices.cs index fbc32d0..c2a9289 100644 --- a/src/Microsoft.AspNetCore.NodeServices/INodeServices.cs +++ b/src/Microsoft.AspNetCore.NodeServices/INodeServices.cs @@ -4,18 +4,71 @@ using System.Threading.Tasks; namespace Microsoft.AspNetCore.NodeServices { + /// + /// Represents the ability to invoke code in a Node.js environment. Although the underlying Node.js instance + /// might change over time (e.g., the process might be restarted), the instance + /// will remain constant. + /// public interface INodeServices : IDisposable { + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. Task InvokeAsync(string moduleName, params object[] args); + + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// A that can be used to cancel the invocation. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. Task InvokeAsync(CancellationToken cancellationToken, string moduleName, params object[] args); + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked. + /// Specifies the CommonJS export to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. Task InvokeExportAsync(string moduleName, string exportedFunctionName, params object[] args); + + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// A that can be used to cancel the invocation. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked. + /// Specifies the CommonJS export to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. Task InvokeExportAsync(CancellationToken cancellationToken, string moduleName, string exportedFunctionName, params object[] args); - + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. [Obsolete("Use InvokeAsync instead")] Task Invoke(string moduleName, params object[] args); + /// + /// Asynchronously invokes code in the Node.js instance. + /// + /// The JSON-serializable data type that the Node.js code will asynchronously return. + /// The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked. + /// Specifies the CommonJS export to be invoked. + /// Any sequence of JSON-serializable arguments to be passed to the Node.js function. + /// A representing the completion of the RPC call. [Obsolete("Use InvokeExportAsync instead")] Task InvokeExport(string moduleName, string exportedFunctionName, params object[] args); } diff --git a/src/Microsoft.AspNetCore.NodeServices/Util/EmbeddedResourceReader.cs b/src/Microsoft.AspNetCore.NodeServices/Util/EmbeddedResourceReader.cs index a7147c1..0531826 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Util/EmbeddedResourceReader.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Util/EmbeddedResourceReader.cs @@ -4,8 +4,17 @@ using System.Reflection; namespace Microsoft.AspNetCore.NodeServices { + /// + /// Contains methods for reading embedded resources. + /// public static class EmbeddedResourceReader { + /// + /// Reads the specified embedded resource from a given assembly. + /// + /// Any in the assembly whose resource is to be read. + /// The path of the resource to be read. + /// The contents of the resource. public static string Read(Type assemblyContainingType, string path) { var asm = assemblyContainingType.GetTypeInfo().Assembly; diff --git a/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs b/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs index 4458b77..999dfa2 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Util/StringAsTempFile.cs @@ -3,19 +3,31 @@ using System.IO; namespace Microsoft.AspNetCore.NodeServices { - // Makes it easier to pass script files to Node in a way that's sure to clean up after the process exits + /// + /// Makes it easier to pass script files to Node in a way that's sure to clean up after the process exits. + /// public sealed class StringAsTempFile : IDisposable { private bool _disposedValue; + /// + /// Create a new instance of . + /// + /// The contents of the temporary file to be created. public StringAsTempFile(string content) { FileName = Path.GetTempFileName(); File.WriteAllText(FileName, content); } + /// + /// Specifies the filename of the temporary file. + /// public string FileName { get; } + /// + /// Disposes the instance and deletes the associated temporary file. + /// public void Dispose() { DisposeImpl(true); @@ -37,6 +49,9 @@ namespace Microsoft.AspNetCore.NodeServices } } + /// + /// Implements the finalization part of the IDisposable pattern by calling Dispose(false). + /// ~StringAsTempFile() { DisposeImpl(false); diff --git a/src/Microsoft.AspNetCore.NodeServices/project.json b/src/Microsoft.AspNetCore.NodeServices/project.json index 44cbb12..c451d9e 100644 --- a/src/Microsoft.AspNetCore.NodeServices/project.json +++ b/src/Microsoft.AspNetCore.NodeServices/project.json @@ -17,7 +17,8 @@ "keyFile": "../../tools/Key.snk", "embed": [ "Content/**/*" - ] + ], + "xmlDoc": true }, "dependencies": { "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0", diff --git a/src/Microsoft.AspNetCore.ReactServices/project.json b/src/Microsoft.AspNetCore.ReactServices/project.json index ebe7697..341fbb9 100644 --- a/src/Microsoft.AspNetCore.ReactServices/project.json +++ b/src/Microsoft.AspNetCore.ReactServices/project.json @@ -14,7 +14,8 @@ }, "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "xmlDoc": true }, "dependencies": { "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1", diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/JavaScriptModuleExport.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/JavaScriptModuleExport.cs index 3403866..65e82d4 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/JavaScriptModuleExport.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/JavaScriptModuleExport.cs @@ -1,14 +1,36 @@ +using System; + namespace Microsoft.AspNetCore.SpaServices.Prerendering { + /// + /// Describes how to find the JavaScript code that performs prerendering. + /// public class JavaScriptModuleExport { + /// + /// Creates a new instance of . + /// + /// The path to the JavaScript module containing prerendering code. public JavaScriptModuleExport(string moduleName) { ModuleName = moduleName; } + /// + /// Specifies the path to the JavaScript module containing prerendering code. + /// public string ModuleName { get; private set; } + + /// + /// If set, specifies the name of the CommonJS export that is the prerendering function to execute. + /// If not set, the JavaScript module's default CommonJS export must itself be the prerendering function. + /// public string ExportName { get; set; } + + /// + /// Obsolete. Do not use. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly. + /// + [Obsolete("Do not use. This feature will be removed. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.")] public string WebpackConfig { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs index 7bce95c..9c5062a 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs @@ -11,6 +11,9 @@ using Newtonsoft.Json; namespace Microsoft.AspNetCore.SpaServices.Prerendering { + /// + /// A tag helper for prerendering JavaScript applications on the server. + /// [HtmlTargetElement(Attributes = PrerenderModuleAttributeName)] public class PrerenderTagHelper : TagHelper { @@ -24,6 +27,10 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering private readonly string _applicationBasePath; private readonly INodeServices _nodeServices; + /// + /// Creates a new instance of . + /// + /// The . public PrerenderTagHelper(IServiceProvider serviceProvider) { var hostEnv = (IHostingEnvironment) serviceProvider.GetService(typeof(IHostingEnvironment)); @@ -39,25 +46,51 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering } } + /// + /// Specifies the path to the JavaScript module containing prerendering code. + /// [HtmlAttributeName(PrerenderModuleAttributeName)] public string ModuleName { get; set; } + /// + /// If set, specifies the name of the CommonJS export that is the prerendering function to execute. + /// If not set, the JavaScript module's default CommonJS export must itself be the prerendering function. + /// [HtmlAttributeName(PrerenderExportAttributeName)] public string ExportName { get; set; } + /// + /// Obsolete. Do not use. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly. + /// + [Obsolete("Do not use. This feature will be removed. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.")] [HtmlAttributeName(PrerenderWebpackConfigAttributeName)] public string WebpackConfigPath { get; set; } + /// + /// An optional JSON-serializable parameter to be supplied to the prerendering code. + /// [HtmlAttributeName(PrerenderDataAttributeName)] public object CustomDataParameter { get; set; } + /// + /// The maximum duration to wait for prerendering to complete. + /// [HtmlAttributeName(PrerenderTimeoutAttributeName)] public int TimeoutMillisecondsParameter { get; set; } + /// + /// The . + /// [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } + /// + /// Executes the tag helper to perform server-side prerendering. + /// + /// The . + /// The . + /// A representing the operation. public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { // We want to pass the original, unencoded incoming URL data through to Node, so that @@ -79,7 +112,9 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering new JavaScriptModuleExport(ModuleName) { ExportName = ExportName, +#pragma warning disable CS0618 // Type or member is obsolete WebpackConfig = WebpackConfigPath +#pragma warning restore CS0618 // Type or member is obsolete }, unencodedAbsoluteUrl, unencodedPathAndQuery, diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs index 9d8724e..8785f34 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/Prerenderer.cs @@ -4,6 +4,9 @@ using Microsoft.AspNetCore.NodeServices; namespace Microsoft.AspNetCore.SpaServices.Prerendering { + /// + /// Performs server-side prerendering by invoking code in Node.js. + /// public static class Prerenderer { private static readonly Lazy NodeScript; @@ -17,6 +20,17 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering }); } + /// + /// 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. + /// 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. + /// An optional JSON-serializable parameter to be supplied to the prerendering code. + /// The maximum duration to wait for prerendering to complete. + /// public static Task RenderToString( string applicationBasePath, INodeServices nodeServices, diff --git a/src/Microsoft.AspNetCore.SpaServices/Prerendering/RenderToStringResult.cs b/src/Microsoft.AspNetCore.SpaServices/Prerendering/RenderToStringResult.cs index cae8d63..82c68c3 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Prerendering/RenderToStringResult.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Prerendering/RenderToStringResult.cs @@ -2,10 +2,28 @@ using Newtonsoft.Json.Linq; namespace Microsoft.AspNetCore.SpaServices.Prerendering { + /// + /// Describes the prerendering result returned by JavaScript code. + /// public class RenderToStringResult { + /// + /// If set, specifies JSON-serializable data that should be added as a set of global JavaScript variables in the document. + /// This can be used to transfer arbitrary data from server-side prerendering code to client-side code (for example, to + /// transfer the state of a Redux store). + /// public JObject Globals { get; set; } + + /// + /// The HTML generated by the prerendering logic. + /// public string Html { get; set; } + + /// + /// If set, specifies that instead of rendering HTML, the response should be an HTTP redirection to this URL. + /// This can be used if the prerendering code determines that the requested URL would lead to a redirection according + /// to the SPA's routing configuration. + /// public string RedirectUrl { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SpaServices/Routing/SpaRouteExtensions.cs b/src/Microsoft.AspNetCore.SpaServices/Routing/SpaRouteExtensions.cs index 919390e..7838aa1 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Routing/SpaRouteExtensions.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Routing/SpaRouteExtensions.cs @@ -7,10 +7,22 @@ using Microsoft.AspNetCore.SpaServices; namespace Microsoft.AspNetCore.Builder { + /// + /// Extension methods useful for configuring routing in a single-page application (SPA). + /// public static class SpaRouteExtensions { private const string ClientRouteTokenName = "clientRoute"; + /// + /// Configures a route that is automatically bypassed if the requested URL appears to be for a static file + /// (e.g., if it has a filename extension). + /// + /// The . + /// The route name. + /// Default route parameters. + /// Route constraints. + /// Route data tokens. public static void MapSpaFallbackRoute( this IRouteBuilder routeBuilder, string name, @@ -27,6 +39,16 @@ namespace Microsoft.AspNetCore.Builder dataTokens); } + /// + /// Configures a route that is automatically bypassed if the requested URL appears to be for a static file + /// (e.g., if it has a filename extension). + /// + /// The . + /// The route name. + /// The template prefix. + /// Default route parameters. + /// Route constraints. + /// Route data tokens. public static void MapSpaFallbackRoute( this IRouteBuilder routeBuilder, string name, diff --git a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs index 9ea3299..8a9e432 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddleware.cs @@ -8,16 +8,29 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.PlatformAbstractions; using Newtonsoft.Json; -// Putting in this namespace so it's always available whenever MapRoute is - namespace Microsoft.AspNetCore.Builder { + /// + /// Extension methods that can be used to enable Webpack dev middleware support. + /// public static class WebpackDevMiddleware { private const string WebpackDevMiddlewareScheme = "http"; private const string WebpackHotMiddlewareEndpoint = "/__webpack_hmr"; private const string DefaultConfigFile = "webpack.config.js"; + /// + /// Enables Webpack dev middleware support. This hosts an instance of the Webpack compiler in memory + /// in your application so that you can always serve up-to-date Webpack-built resources without having + /// to run the compiler manually. Since the Webpack compiler instance is retained in memory, incremental + /// compilation is vastly faster that re-running the compiler from scratch. + /// + /// Incoming requests that match Webpack-built files will be handled by returning the Webpack compiler + /// output directly, regardless of files on disk. If compilation is in progress when the request arrives, + /// the response will pause until updated compiler output is ready. + /// + /// The . + /// Options for configuring the Webpack compiler instance. public static void UseWebpackDevMiddleware( this IApplicationBuilder appBuilder, WebpackDevMiddlewareOptions options = null) diff --git a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddlewareOptions.cs b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddlewareOptions.cs index 8f5e12a..d41d97d 100644 --- a/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddlewareOptions.cs +++ b/src/Microsoft.AspNetCore.SpaServices/Webpack/WebpackDevMiddlewareOptions.cs @@ -2,13 +2,42 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.SpaServices.Webpack { + /// + /// Options for configuring a Webpack dev middleware compiler. + /// public class WebpackDevMiddlewareOptions { + /// + /// If true, hot module replacement (HMR) will be enabled. This automatically updates Webpack-built + /// resources (such as JavaScript, CSS, or images) in your web browser whenever source files are changed. + /// public bool HotModuleReplacement { get; set; } + + /// + /// Overrides the internal port number that client-side HMR code will connect to. + /// public int HotModuleReplacementServerPort { get; set; } + + /// + /// If true, enables React-specific extensions to Webpack's hot module replacement (HMR) feature. + /// This enables React components to be updated without losing their in-memory state. + /// public bool ReactHotModuleReplacement { get; set; } + + /// + /// Specifies the Webpack configuration file to be used. If not set, defaults to 'webpack.config.js'. + /// public string ConfigFile { get; set; } + + /// + /// The root path of your project. Webpack runs in this context. + /// public string ProjectPath { get; set; } + + /// + /// Specifies additional environment variables to be passed to the Node instance hosting + /// the webpack compiler. + /// public IDictionary EnvironmentVariables { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SpaServices/project.json b/src/Microsoft.AspNetCore.SpaServices/project.json index e8c3e59..e71874a 100644 --- a/src/Microsoft.AspNetCore.SpaServices/project.json +++ b/src/Microsoft.AspNetCore.SpaServices/project.json @@ -17,7 +17,8 @@ "keyFile": "../../tools/Key.snk", "embed": [ "Content/**/*" - ] + ], + "xmlDoc": true }, "dependencies": { "Microsoft.AspNetCore.Mvc": "1.0.1",