availableTabs;
try
{
- availableTabs = await GetOpenedBrowserTabs(debuggerHost);
+ availableTabs = await GetOpenedBrowserTabs();
}
catch (Exception ex)
{
@@ -147,28 +237,30 @@ namespace Microsoft.AspNetCore.Builder
var underlyingV8Endpoint = tabToDebug.WebSocketDebuggerUrl;
var proxyEndpoint = $"{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}";
var devToolsUrlAbsolute = new Uri(debuggerHost + tabToDebug.DevtoolsFrontendUrl);
- var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?ws={proxyEndpoint}";
+ var wsParamName = request.IsHttps ? "wss" : "ws";
+ var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?{wsParamName}={proxyEndpoint}";
context.Response.Redirect(devToolsUrlWithProxy);
}
private static string GetLaunchChromeInstructions(string appRootUrl)
{
- var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug");
+ var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug");
+ var debuggerPort = GetDebuggerPort();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return $@"Press Win+R and enter the following:
- chrome --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}
";
+ chrome --remote-debugging-port={debuggerPort} --user-data-dir=""{profilePath}"" {appRootUrl}
";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return $@"In a terminal window execute the following:
- google-chrome --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}
";
+ google-chrome --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}
";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return $@"Execute the following:
- open /Applications/Google\ Chrome.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}
";
+ open /Applications/Google\ Chrome.app --args --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}
";
}
else
{
@@ -178,17 +270,18 @@ namespace Microsoft.AspNetCore.Builder
private static string GetLaunchEdgeInstructions(string appRootUrl)
{
- var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug");
+ var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug");
+ var debugggerPort = GetDebuggerPort();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return $@"Press Win+R and enter the following:
- msedge --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}
";
+ msedge --remote-debugging-port={debugggerPort} --user-data-dir=""{profilePath}"" --no-first-run {appRootUrl}
";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return $@"In a terminal window execute the following:
- open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}
";
+ open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port={debugggerPort} --user-data-dir={profilePath} {appRootUrl}
";
}
else
{
@@ -196,17 +289,24 @@ namespace Microsoft.AspNetCore.Builder
}
}
- private static async Task> GetOpenedBrowserTabs(string debuggerHost)
+ private static async Task GetBrowserVersionInfoAsync()
{
- using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) })
- {
- var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json");
- return JsonConvert.DeserializeObject(jsonResponse);
- }
+ using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
+ var debuggerHost = GetDebuggerHost();
+ return await httpClient.GetStringAsync($"{debuggerHost}/json/version");
+ }
+
+ private static async Task> GetOpenedBrowserTabs()
+ {
+ using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
+ var debuggerHost = GetDebuggerHost();
+ var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json");
+ return JsonSerializer.Deserialize(jsonResponse, JsonOptions);
}
class BrowserTab
{
+ public string Id { get; set; }
public string Type { get; set; }
public string Url { get; set; }
public string Title { get; set; }
diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs
index ee28bd94b7..e1e9b7392b 100644
--- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs
+++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs
@@ -545,7 +545,7 @@ namespace WsProxy {
return assemblies.FirstOrDefault (a => a.Name.Equals (name, StringComparison.InvariantCultureIgnoreCase));
}
- /*
+ /*
V8 uses zero based indexing for both line and column.
PPDBs uses one based indexing for both line and column.
*/
@@ -598,7 +598,7 @@ namespace WsProxy {
PPDBs uses one based indexing for both line and column.
*/
static bool Match (SequencePoint sp, int line, int column)
- {
+ {
var bp = (line: line + 1, column: column + 1);
if (sp.StartLine > bp.line || sp.EndLine < bp.line)
diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs
index 8c440da1ce..eb4cf65b50 100644
--- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs
+++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs
@@ -223,7 +223,7 @@ namespace WsProxy {
Info ("RUNTIME READY, PARTY TIME");
await RuntimeReady (token);
await SendCommand ("Debugger.resume", new JObject (), token);
- SendEvent ("Mono.runtimeReady", new JObject (), token);
+ SendEvent ("Mono.runtimeReady", new JObject (), token);
}
async Task OnBreakPointHit (JObject args, CancellationToken token)
@@ -274,12 +274,18 @@ namespace WsProxy {
var frames = new List ();
int frame_id = 0;
var the_mono_frames = res.Value? ["result"]? ["value"]? ["frames"]?.Values ();
+
foreach (var mono_frame in the_mono_frames) {
var il_pos = mono_frame ["il_pos"].Value ();
var method_token = mono_frame ["method_token"].Value ();
var assembly_name = mono_frame ["assembly_name"].Value ();
var asm = store.GetAssemblyByName (assembly_name);
+ if (asm == null) {
+ Info ($"Unable to find assembly: {assembly_name}");
+ continue;
+ }
+
var method = asm.GetMethodByToken (method_token);
if (method == null) {
@@ -374,7 +380,7 @@ namespace WsProxy {
//Debug ($"\t{is_ready}");
if (is_ready.HasValue && is_ready.Value == true) {
Debug ("RUNTIME LOOK READY. GO TIME!");
- await RuntimeReady (token);
+ await OnRuntimeReady (token);
}
}
@@ -426,33 +432,38 @@ namespace WsProxy {
return;
}
- var values = res.Value?["result"]?["value"]?.Values().ToArray();
+ try {
+ var values = res.Value?["result"]?["value"]?.Values().ToArray() ?? Array.Empty();
+ var var_list = new List();
- var var_list = new List();
+ // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously
+ // results in a "Memory access out of bounds", causing 'values' to be null,
+ // so skip returning variable values in that case.
+ for (int i = 0; i < values.Length; i+=2)
+ {
+ string fieldName = (string)values[i]["name"];
+ if (fieldName.Contains("k__BackingField")){
+ fieldName = fieldName.Replace("k__BackingField", "");
+ fieldName = fieldName.Replace("<", "");
+ fieldName = fieldName.Replace(">", "");
+ }
+ var value = values [i + 1]? ["value"];
+ if (((string)value ["description"]) == null)
+ value ["description"] = value ["value"]?.ToString ();
- // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously
- // results in a "Memory access out of bounds", causing 'values' to be null,
- // so skip returning variable values in that case.
- for (int i = 0; i < values.Length; i+=2)
- {
- string fieldName = (string)values[i]["name"];
- if (fieldName.Contains("k__BackingField")){
- fieldName = fieldName.Replace("k__BackingField", "");
- fieldName = fieldName.Replace("<", "");
- fieldName = fieldName.Replace(">", "");
+ var_list.Add(JObject.FromObject(new {
+ name = fieldName,
+ value
+ }));
+
+ }
+ o = JObject.FromObject(new
+ {
+ result = var_list
+ });
+ } catch (Exception) {
+ Debug ($"failed to parse {res.Value}");
}
- var_list.Add(JObject.FromObject(new
- {
- name = fieldName,
- value = values[i+1]["value"]
- }));
-
- }
- o = JObject.FromObject(new
- {
- result = var_list
- });
-
SendResponse(msg_id, Result.Ok(o), token);
}
@@ -481,41 +492,51 @@ namespace WsProxy {
return;
}
- var values = res.Value? ["result"]? ["value"]?.Values ().ToArray ();
+ try {
+ var values = res.Value? ["result"]? ["value"]?.Values ().ToArray ();
- var var_list = new List ();
- int i = 0;
- // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously
- // results in a "Memory access out of bounds", causing 'values' to be null,
- // so skip returning variable values in that case.
- while (values != null && i < vars.Length && i < values.Length) {
- var value = values [i] ["value"];
- if (((string)value ["description"]) == null)
- value ["description"] = value ["value"]?.ToString();
+ var var_list = new List ();
+ int i = 0;
+ // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously
+ // results in a "Memory access out of bounds", causing 'values' to be null,
+ // so skip returning variable values in that case.
+ while (values != null && i < vars.Length && i < values.Length) {
+ var value = values [i] ["value"];
+ if (((string)value ["description"]) == null)
+ value ["description"] = value ["value"]?.ToString ();
- var_list.Add (JObject.FromObject (new {
- name = vars [i].Name,
- value = values [i] ["value"]
- }));
- i++;
+ var_list.Add (JObject.FromObject (new {
+ name = vars [i].Name,
+ value
+ }));
+ i++;
+ }
+ //Async methods are special in the way that local variables can be lifted to generated class fields
+ //value of "this" comes here either
+ while (i < values.Length) {
+ String name = values [i] ["name"].ToString ();
+
+ if (name.IndexOf (">", StringComparison.Ordinal) > 0)
+ name = name.Substring (1, name.IndexOf (">", StringComparison.Ordinal) - 1);
+
+ var value = values [i + 1] ["value"];
+ if (((string)value ["description"]) == null)
+ value ["description"] = value ["value"]?.ToString ();
+
+ var_list.Add (JObject.FromObject (new {
+ name,
+ value
+ }));
+ i = i + 2;
+ }
+ o = JObject.FromObject (new {
+ result = var_list
+ });
+ SendResponse (msg_id, Result.Ok (o), token);
}
- //Async methods are special in the way that local variables can be lifted to generated class fields
- //value of "this" comes here either
- while (i < values.Length) {
- String name = values [i] ["name"].ToString ();
-
- if (name.IndexOf (">", StringComparison.Ordinal) > 0)
- name = name.Substring (1, name.IndexOf (">", StringComparison.Ordinal) - 1);
- var_list.Add (JObject.FromObject (new {
- name = name,
- value = values [i+1] ["value"]
- }));
- i = i + 2;
+ catch (Exception) {
+ SendResponse (msg_id, res, token);
}
- o = JObject.FromObject (new {
- result = var_list
- });
- SendResponse (msg_id, Result.Ok (o), token);
}
async Task EnableBreakPoint (Breakpoint bp, CancellationToken token)
diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs
index 17c72e9ce7..87ef23027e 100644
--- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs
+++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs
@@ -97,6 +97,7 @@ namespace WsProxy {
internal class WsProxy {
TaskCompletionSource side_exception = new TaskCompletionSource ();
+ TaskCompletionSource client_initiated_close = new TaskCompletionSource ();
List<(int, TaskCompletionSource)> pending_cmds = new List<(int, TaskCompletionSource)> ();
ClientWebSocket browser;
WebSocket ide;
@@ -119,8 +120,16 @@ namespace WsProxy {
byte [] buff = new byte [4000];
var mem = new MemoryStream ();
while (true) {
+
+ if (socket.State != WebSocketState.Open) {
+ Console.WriteLine ($"WSProxy: Socket is no longer open.");
+ client_initiated_close.TrySetResult (true);
+ return null;
+ }
+
var result = await socket.ReceiveAsync (new ArraySegment (buff), token);
if (result.MessageType == WebSocketMessageType.Close) {
+ client_initiated_close.TrySetResult (true);
return null;
}
@@ -144,7 +153,7 @@ namespace WsProxy {
void Send (WebSocket to, JObject o, CancellationToken token)
{
- var bytes = Encoding.UTF8.GetBytes (o.ToString ());
+ var bytes = Encoding.UTF8.GetBytes (o.ToString ());
var queue = GetQueueForSocket (to);
var task = queue.Send (bytes, token);
@@ -199,9 +208,10 @@ namespace WsProxy {
void ProcessIdeMessage (string msg, CancellationToken token)
{
- var res = JObject.Parse (msg);
-
- pending_ops.Add (OnCommand (res ["id"].Value (), res ["method"].Value (), res ["params"] as JObject, token));
+ if (!string.IsNullOrEmpty (msg)) {
+ var res = JObject.Parse (msg);
+ pending_ops.Add (OnCommand (res ["id"].Value (), res ["method"].Value (), res ["params"] as JObject, token));
+ }
}
internal async Task SendCommand (string method, JObject args, CancellationToken token) {
@@ -255,24 +265,25 @@ namespace WsProxy {
Send (this.ide, o, token);
}
- // , HttpContext context)
+ // , HttpContext context)
public async Task Run (Uri browserUri, WebSocket ideSocket)
{
- Debug ("wsproxy start");
+ Debug ($"WsProxy Starting on {browserUri}");
using (this.ide = ideSocket) {
- Debug ("ide connected");
+ Debug ($"WsProxy: IDE waiting for connection on {browserUri}");
queues.Add (new WsQueue (this.ide));
using (this.browser = new ClientWebSocket ()) {
this.browser.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan;
await this.browser.ConnectAsync (browserUri, CancellationToken.None);
queues.Add (new WsQueue (this.browser));
- Debug ("client connected");
+ Debug ($"WsProxy: Client connected on {browserUri}");
var x = new CancellationTokenSource ();
pending_ops.Add (ReadOne (browser, x.Token));
pending_ops.Add (ReadOne (ide, x.Token));
pending_ops.Add (side_exception.Task);
+ pending_ops.Add (client_initiated_close.Task);
try {
while (!x.IsCancellationRequested) {
@@ -280,15 +291,23 @@ namespace WsProxy {
//Console.WriteLine ("pump {0} {1}", task, pending_ops.IndexOf (task));
if (task == pending_ops [0]) {
var msg = ((Task)task).Result;
- pending_ops [0] = ReadOne (browser, x.Token); //queue next read
- ProcessBrowserMessage (msg, x.Token);
+ if (msg != null) {
+ pending_ops [0] = ReadOne (browser, x.Token); //queue next read
+ ProcessBrowserMessage (msg, x.Token);
+ }
} else if (task == pending_ops [1]) {
var msg = ((Task)task).Result;
- pending_ops [1] = ReadOne (ide, x.Token); //queue next read
- ProcessIdeMessage (msg, x.Token);
+ if (msg != null) {
+ pending_ops [1] = ReadOne (ide, x.Token); //queue next read
+ ProcessIdeMessage (msg, x.Token);
+ }
} else if (task == pending_ops [2]) {
var res = ((Task)task).Result;
throw new Exception ("side task must always complete with an exception, what's going on???");
+ } else if (task == pending_ops [3]) {
+ var res = ((Task)task).Result;
+ Debug ($"WsProxy: Client initiated close from {browserUri}");
+ x.Cancel ();
} else {
//must be a background task
pending_ops.Remove (task);
@@ -301,10 +320,11 @@ namespace WsProxy {
}
}
} catch (Exception e) {
- Debug ($"got exception {e}");
+ Debug ($"WsProxy::Run: Exception {e}");
//throw;
} finally {
- x.Cancel ();
+ if (!x.IsCancellationRequested)
+ x.Cancel ();
}
}
}
diff --git a/src/Components/Blazor/Templates/src/Directory.Build.props b/src/Components/Blazor/Templates/src/Directory.Build.props
deleted file mode 100644
index ed5e015014..0000000000
--- a/src/Components/Blazor/Templates/src/Directory.Build.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
- false
- false
-
-
-
-
- 0.8.0-preview-19064-0339
- 3.0.0-preview-19064-0339
-
-
-
diff --git a/src/Components/Blazor/Templates/src/Directory.Build.targets b/src/Components/Blazor/Templates/src/Directory.Build.targets
deleted file mode 100644
index 7c6f423add..0000000000
--- a/src/Components/Blazor/Templates/src/Directory.Build.targets
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
- TemplateBlazorVersion=$(PackageVersion);
- TemplateComponentsVersion=$(ComponentsPackageVersion);
- RepositoryCommit=$(SourceRevisionId);
-
-
-
-
diff --git a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec b/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec
deleted file mode 100644
index fd19750231..0000000000
--- a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- $CommonMetadataElements$
-
-
-
-
-
- $CommonFileElements$
-
-
-
diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs
deleted file mode 100644
index 03d510452d..0000000000
--- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Microsoft.AspNetCore.Blazor.Hosting;
-
-#if (Hosted)
-namespace BlazorWasm_CSharp.Client
-#else
-namespace BlazorWasm_CSharp
-#endif
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
-
- public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
- BlazorWebAssemblyHost.CreateDefaultBuilder()
- .UseBlazorStartup();
- }
-}
diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs
deleted file mode 100644
index b30f14ae06..0000000000
--- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using Microsoft.AspNetCore.Components.Builder;
-using Microsoft.Extensions.DependencyInjection;
-
-#if (Hosted)
-namespace BlazorWasm_CSharp.Client
-#else
-namespace BlazorWasm_CSharp
-#endif
-{
- public class Startup
- {
- public void ConfigureServices(IServiceCollection services)
- {
- }
-
- public void Configure(IComponentsApplicationBuilder app)
- {
- app.AddComponent("app");
- }
- }
-}
diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj
deleted file mode 100644
index 2a77f0c7cc..0000000000
--- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
- netstandard2.0
- 7.3
-
-
-
diff --git a/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj b/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj
index 89023db6b9..53cc678edb 100644
--- a/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj
+++ b/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj
@@ -1,7 +1,7 @@
- netstandard2.0
+ netstandard2.1
Provides experimental support for validation using DataAnnotations.
false
false
diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj
index ef12ac3c4e..e27de695c1 100644
--- a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj
+++ b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj
@@ -1,7 +1,7 @@

- netstandard2.0
+ netstandard2.1
Exe
true
3.0
@@ -11,17 +11,4 @@