Further stylistic tweaks

This commit is contained in:
SteveSandersonMS
2016-05-31 22:29:27 +01:00
parent 5bb92d02dd
commit cb289fd387
10 changed files with 64 additions and 42 deletions

View File

@@ -25,16 +25,14 @@ namespace Microsoft.AspNetCore.AngularServices
try try
{ {
var request = html.ViewContext.HttpContext.Request; var request = html.ViewContext.HttpContext.Request;
var baseUri = var baseUriString = string.Concat(
new Uri(
string.Concat(
request.Scheme, request.Scheme,
"://", "://",
request.Host.ToUriComponent(), request.Host.ToUriComponent(),
request.PathBase.ToUriComponent(), request.PathBase.ToUriComponent(),
request.Path.ToUriComponent(), request.Path.ToUriComponent(),
request.QueryString.ToUriComponent())); request.QueryString.ToUriComponent());
var fullUri = new Uri(baseUri, url); var fullUri = new Uri(new Uri(baseUriString), url);
var response = await new HttpClient().GetAsync(fullUri.ToString()); var response = await new HttpClient().GetAsync(fullUri.ToString());
var responseBody = await response.Content.ReadAsStringAsync(); var responseBody = await response.Content.ReadAsStringAsync();
return new HtmlString(FormatAsScript(url, response.StatusCode, responseBody)); return new HtmlString(FormatAsScript(url, response.StatusCode, responseBody));
@@ -48,11 +46,13 @@ namespace Microsoft.AspNetCore.AngularServices
} }
private static string FormatAsScript(string url, HttpStatusCode responseStatusCode, string responseBody) private static string FormatAsScript(string url, HttpStatusCode responseStatusCode, string responseBody)
=> {
"<script>" + var preCachedUrl = JsonConvert.SerializeObject(url);
"window.__preCachedResponses = window.__preCachedResponses || {}; " + var preCachedJson = JsonConvert.SerializeObject(new { statusCode = responseStatusCode, body = responseBody });
$"window.__preCachedResponses[{JsonConvert.SerializeObject(url)}] " + return "<script>"
$"= {JsonConvert.SerializeObject(new { statusCode = responseStatusCode, body = responseBody })};" + + "window.__preCachedResponses = window.__preCachedResponses || {};"
"</script>"; + $"window.__preCachedResponses[{preCachedUrl}] = {preCachedJson};"
+ "</script>";
}
} }
} }

View File

@@ -1,11 +1,9 @@
using System;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
namespace Microsoft.AspNetCore.NodeServices namespace Microsoft.AspNetCore.NodeServices
{ {
using System;
public static class Configuration public static class Configuration
{ {
private static readonly string[] DefaultWatchFileExtensions = {".js", ".jsx", ".ts", ".tsx", ".json", ".html"}; private static readonly string[] DefaultWatchFileExtensions = {".js", ".jsx", ".ts", ".tsx", ".json", ".html"};
@@ -20,15 +18,18 @@ namespace Microsoft.AspNetCore.NodeServices
=> AddNodeServices(serviceCollection, DefaultOptions); => AddNodeServices(serviceCollection, DefaultOptions);
public static void AddNodeServices(this IServiceCollection serviceCollection, NodeServicesOptions options) public static void AddNodeServices(this IServiceCollection serviceCollection, NodeServicesOptions options)
=> serviceCollection.AddSingleton(typeof(INodeServices), serviceProvider => {
serviceCollection.AddSingleton(typeof(INodeServices), serviceProvider =>
{ {
var hostEnv = serviceProvider.GetRequiredService<IHostingEnvironment>(); var hostEnv = serviceProvider.GetRequiredService<IHostingEnvironment>();
if (string.IsNullOrEmpty(options.ProjectPath)) if (string.IsNullOrEmpty(options.ProjectPath))
{ {
options.ProjectPath = hostEnv.ContentRootPath; options.ProjectPath = hostEnv.ContentRootPath;
} }
return CreateNodeServices(options); return CreateNodeServices(options);
}); });
}
public static INodeServices CreateNodeServices(NodeServicesOptions options) public static INodeServices CreateNodeServices(NodeServicesOptions options)
{ {

View File

@@ -64,12 +64,14 @@ namespace Microsoft.AspNetCore.NodeServices
{ {
return JsonConvert.DeserializeObject<T>(responseString); return JsonConvert.DeserializeObject<T>(responseString);
} }
if (typeof(T) != typeof(string)) if (typeof(T) != typeof(string))
{ {
throw new ArgumentException( throw new ArgumentException(
"Node module responded with non-JSON string. This cannot be converted to the requested generic type: " + "Node module responded with non-JSON string. This cannot be converted to the requested generic type: " +
typeof(T).FullName); typeof(T).FullName);
} }
return (T)(object)responseString; return (T)(object)responseString;
} }
} }

View File

@@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.NodeServices
private readonly object _childProcessLauncherLock; private readonly object _childProcessLauncherLock;
private readonly string _commandLineArguments; private readonly string _commandLineArguments;
private readonly StringAsTempFile _entryPointScript; private readonly StringAsTempFile _entryPointScript;
private Process _nodeProcess;
private TaskCompletionSource<bool> _nodeProcessIsReadySource; private TaskCompletionSource<bool> _nodeProcessIsReadySource;
private readonly string _projectPath; private readonly string _projectPath;
private bool _disposed; private bool _disposed;
@@ -27,18 +28,28 @@ namespace Microsoft.AspNetCore.NodeServices
_commandLineArguments = commandLineArguments ?? string.Empty; _commandLineArguments = commandLineArguments ?? string.Empty;
} }
protected Process NodeProcess { get; private set; } protected Process NodeProcess
{
get
{
// This is only exposed to support the unreliable InputOutputStreamNodeInstance, which is just to verify that
// other hosting/transport mechanisms are possible. This shouldn't really be exposed, and will be removed.
return this._nodeProcess;
}
}
public Task<T> Invoke<T>(string moduleName, params object[] args) public Task<T> Invoke<T>(string moduleName, params object[] args)
=> InvokeExport<T>(moduleName, null, args); => InvokeExport<T>(moduleName, null, args);
public Task<T> InvokeExport<T>(string moduleName, string exportedFunctionName, params object[] args) public Task<T> InvokeExport<T>(string moduleName, string exportedFunctionName, params object[] args)
=> Invoke<T>(new NodeInvocationInfo {
return Invoke<T>(new NodeInvocationInfo
{ {
ModuleName = moduleName, ModuleName = moduleName,
ExportedFunctionName = exportedFunctionName, ExportedFunctionName = exportedFunctionName,
Args = args Args = args
}); });
}
public void Dispose() public void Dispose()
{ {
@@ -52,7 +63,7 @@ namespace Microsoft.AspNetCore.NodeServices
{ {
lock (_childProcessLauncherLock) lock (_childProcessLauncherLock)
{ {
if (NodeProcess == null || NodeProcess.HasExited) if (_nodeProcess == null || _nodeProcess.HasExited)
{ {
var startInfo = new ProcessStartInfo("node") var startInfo = new ProcessStartInfo("node")
{ {
@@ -79,7 +90,7 @@ namespace Microsoft.AspNetCore.NodeServices
#endif #endif
OnBeforeLaunchProcess(); OnBeforeLaunchProcess();
NodeProcess = Process.Start(startInfo); _nodeProcess = Process.Start(startInfo);
ConnectToInputOutputStreams(); ConnectToInputOutputStreams();
} }
} }
@@ -98,7 +109,7 @@ namespace Microsoft.AspNetCore.NodeServices
var initializationIsCompleted = false; // TODO: Make this thread-safe? (Interlocked.Exchange etc.) var initializationIsCompleted = false; // TODO: Make this thread-safe? (Interlocked.Exchange etc.)
_nodeProcessIsReadySource = new TaskCompletionSource<bool>(); _nodeProcessIsReadySource = new TaskCompletionSource<bool>();
NodeProcess.OutputDataReceived += (sender, evt) => _nodeProcess.OutputDataReceived += (sender, evt) =>
{ {
if (evt.Data == "[Microsoft.AspNetCore.NodeServices:Listening]" && !initializationIsCompleted) if (evt.Data == "[Microsoft.AspNetCore.NodeServices:Listening]" && !initializationIsCompleted)
{ {
@@ -111,7 +122,7 @@ namespace Microsoft.AspNetCore.NodeServices
} }
}; };
NodeProcess.ErrorDataReceived += (sender, evt) => _nodeProcess.ErrorDataReceived += (sender, evt) =>
{ {
if (evt.Data != null) if (evt.Data != null)
{ {
@@ -124,8 +135,8 @@ namespace Microsoft.AspNetCore.NodeServices
} }
}; };
NodeProcess.BeginOutputReadLine(); _nodeProcess.BeginOutputReadLine();
NodeProcess.BeginErrorReadLine(); _nodeProcess.BeginErrorReadLine();
} }
protected virtual void OnBeforeLaunchProcess() protected virtual void OnBeforeLaunchProcess()
@@ -151,9 +162,9 @@ namespace Microsoft.AspNetCore.NodeServices
_entryPointScript.Dispose(); _entryPointScript.Dispose();
} }
if (NodeProcess != null && !NodeProcess.HasExited) if (_nodeProcess != null && !_nodeProcess.HasExited)
{ {
NodeProcess.Kill(); _nodeProcess.Kill();
// TODO: Is there a more graceful way to end it? Or does this still let it perform any cleanup? // TODO: Is there a more graceful way to end it? Or does this still let it perform any cleanup?
} }

View File

@@ -4,7 +4,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
{ {
public JavaScriptModuleExport(string moduleName) public JavaScriptModuleExport(string moduleName)
{ {
this.ModuleName = moduleName; ModuleName = moduleName;
} }
public string ModuleName { get; private set; } public string ModuleName { get; private set; }

View File

@@ -17,13 +17,14 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
}); });
} }
public static async Task<RenderToStringResult> RenderToString( public static Task<RenderToStringResult> RenderToString(
string applicationBasePath, string applicationBasePath,
INodeServices nodeServices, INodeServices nodeServices,
JavaScriptModuleExport bootModule, JavaScriptModuleExport bootModule,
string requestAbsoluteUrl, string requestAbsoluteUrl,
string requestPathAndQuery) string requestPathAndQuery)
=> await nodeServices.InvokeExport<RenderToStringResult>( {
return nodeServices.InvokeExport<RenderToStringResult>(
NodeScript.Value.FileName, NodeScript.Value.FileName,
"renderToString", "renderToString",
applicationBasePath, applicationBasePath,
@@ -32,3 +33,4 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
requestPathAndQuery); requestPathAndQuery);
} }
} }
}

View File

@@ -24,9 +24,14 @@ namespace Microsoft.AspNetCore.SpaServices
string routeKey, string routeKey,
RouteValueDictionary values, RouteValueDictionary values,
RouteDirection routeDirection) RouteDirection routeDirection)
=> !HasDotInLastSegment(values[_clientRouteTokenName] as string ?? string.Empty); {
return !HasDotInLastSegment(values[_clientRouteTokenName] as string ?? string.Empty);
}
private bool HasDotInLastSegment(string uri) private bool HasDotInLastSegment(string uri)
=> uri.IndexOf('.', uri.LastIndexOf('/') + 1) >= 0; {
var lastSegmentStartPos = uri.LastIndexOf('/');
return uri.IndexOf('.', lastSegmentStartPos + 1) >= 0;
}
} }
} }

View File

@@ -17,13 +17,15 @@ namespace Microsoft.AspNetCore.Builder
object defaults, object defaults,
object constraints = null, object constraints = null,
object dataTokens = null) object dataTokens = null)
=> MapSpaFallbackRoute( {
MapSpaFallbackRoute(
routeBuilder, routeBuilder,
name, name,
/* templatePrefix */ null, /* templatePrefix */ null,
defaults, defaults,
constraints, constraints,
dataTokens); dataTokens);
}
public static void MapSpaFallbackRoute( public static void MapSpaFallbackRoute(
this IRouteBuilder routeBuilder, this IRouteBuilder routeBuilder,
@@ -34,7 +36,6 @@ namespace Microsoft.AspNetCore.Builder
object dataTokens = null) object dataTokens = null)
{ {
var template = CreateRouteTemplate(templatePrefix); var template = CreateRouteTemplate(templatePrefix);
var constraintsDict = ObjectToDictionary(constraints); var constraintsDict = ObjectToDictionary(constraints);
constraintsDict.Add(ClientRouteTokenName, new SpaRouteConstraint(ClientRouteTokenName)); constraintsDict.Add(ClientRouteTokenName, new SpaRouteConstraint(ClientRouteTokenName));

View File

@@ -67,9 +67,9 @@ namespace Microsoft.AspNetCore.SpaServices.Webpack
requestMessage.Method = new HttpMethod(context.Request.Method); requestMessage.Method = new HttpMethod(context.Request.Method);
using ( using (
var responseMessage = var responseMessage = await _httpClient.SendAsync(
await requestMessage,
_httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, HttpCompletionOption.ResponseHeadersRead,
context.RequestAborted)) context.RequestAborted))
{ {
if (responseMessage.StatusCode == HttpStatusCode.NotFound) if (responseMessage.StatusCode == HttpStatusCode.NotFound)