Merge pull request #1785 from aspnet/release/2.1

Add detailed error option (#1763)
This commit is contained in:
BrennanConroy 2018-03-30 11:30:44 -07:00 committed by GitHub
commit ec66d236ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 120 additions and 44 deletions

View File

@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
{ {
@ -38,6 +39,8 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
_dispatcher = new DefaultHubDispatcher<TestHub>( _dispatcher = new DefaultHubDispatcher<TestHub>(
serviceScopeFactory, serviceScopeFactory,
new HubContext<TestHub>(new DefaultHubLifetimeManager<TestHub>(NullLogger<DefaultHubLifetimeManager<TestHub>>.Instance)), new HubContext<TestHub>(new DefaultHubLifetimeManager<TestHub>(NullLogger<DefaultHubLifetimeManager<TestHub>>.Instance)),
Options.Create(new HubOptions<TestHub>()),
Options.Create(new HubOptions()),
new Logger<DefaultHubDispatcher<TestHub>>(NullLoggerFactory.Instance)); new Logger<DefaultHubDispatcher<TestHub>>(NullLoggerFactory.Instance));
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);

View File

@ -56,7 +56,8 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
{ {
_pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult)); _pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult));
await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _successHubProtocolResolver, _userIdProvider); await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _successHubProtocolResolver,
_userIdProvider, enableDetailedErrors: true);
} }
[Benchmark] [Benchmark]
@ -64,7 +65,8 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
{ {
_pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult)); _pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult));
await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _failureHubProtocolResolver, _userIdProvider); await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _failureHubProtocolResolver,
_userIdProvider, enableDetailedErrors: true);
} }
} }

View File

@ -125,7 +125,7 @@ describe("hubConnection", () => {
}); });
it("rethrows an exception from the server when invoking", (done) => { it("rethrows an exception from the server when invoking", (done) => {
const errorMessage = "An unexpected error occurred invoking 'ThrowException' on the server. InvalidOperationException: An error occurred."; const errorMessage = "An unexpected error occurred invoking 'ThrowException' on the server.";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
logger: TestLogger.instance, logger: TestLogger.instance,
protocol, protocol,
@ -198,7 +198,7 @@ describe("hubConnection", () => {
}); });
it("rethrows an exception from the server when streaming", (done) => { it("rethrows an exception from the server when streaming", (done) => {
const errorMessage = "An unexpected error occurred invoking 'StreamThrowException' on the server. InvalidOperationException: An error occurred."; const errorMessage = "An unexpected error occurred invoking 'StreamThrowException' on the server.";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, { const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
logger: TestLogger.instance, logger: TestLogger.instance,
protocol, protocol,
@ -353,7 +353,7 @@ describe("hubConnection", () => {
}); });
hubConnection.onclose((error) => { hubConnection.onclose((error) => {
expect(error.message).toEqual("Server returned an error on close: Connection closed with an error. InvalidOperationException: Unable to resolve service for type 'System.Object' while attempting to activate 'FunctionalTests.UncreatableHub'."); expect(error.message).toEqual("Server returned an error on close: Connection closed with an error.");
done(); done();
}); });
hubConnection.start(); hubConnection.start();

View File

@ -225,7 +225,8 @@ namespace Microsoft.AspNetCore.SignalR
Task.Factory.StartNew(_abortedCallback, this); Task.Factory.StartNew(_abortedCallback, this);
} }
internal async Task<bool> HandshakeAsync(TimeSpan timeout, IList<string> supportedProtocols, IHubProtocolResolver protocolResolver, IUserIdProvider userIdProvider) internal async Task<bool> HandshakeAsync(TimeSpan timeout, IList<string> supportedProtocols, IHubProtocolResolver protocolResolver,
IUserIdProvider userIdProvider, bool enableDetailedErrors)
{ {
try try
{ {
@ -329,7 +330,8 @@ namespace Microsoft.AspNetCore.SignalR
catch (Exception ex) catch (Exception ex)
{ {
Log.HandshakeFailed(_logger, ex); Log.HandshakeFailed(_logger, ex);
await WriteHandshakeResponseAsync(new HandshakeResponseMessage($"An unexpected error occurred during connection handshake. {ex.GetType().Name}: {ex.Message}")); var errorMessage = ErrorMessageHelper.BuildErrorMessage("An unexpected error occurred during connection handshake.", ex, enableDetailedErrors);
await WriteHandshakeResponseAsync(new HandshakeResponseMessage(errorMessage));
return false; return false;
} }
} }

View File

@ -2,14 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Buffers;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.SignalR.Core; using Microsoft.AspNetCore.SignalR.Core;
using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Internal;
using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.SignalR.Internal.Protocol;
using Microsoft.AspNetCore.Sockets;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -25,6 +22,7 @@ namespace Microsoft.AspNetCore.SignalR
private readonly HubOptions _globalHubOptions; private readonly HubOptions _globalHubOptions;
private readonly IUserIdProvider _userIdProvider; private readonly IUserIdProvider _userIdProvider;
private readonly HubDispatcher<THub> _dispatcher; private readonly HubDispatcher<THub> _dispatcher;
private readonly bool _enableDetailedErrors;
public HubConnectionHandler(HubLifetimeManager<THub> lifetimeManager, public HubConnectionHandler(HubLifetimeManager<THub> lifetimeManager,
IHubProtocolResolver protocolResolver, IHubProtocolResolver protocolResolver,
@ -42,6 +40,8 @@ namespace Microsoft.AspNetCore.SignalR
_logger = loggerFactory.CreateLogger<HubConnectionHandler<THub>>(); _logger = loggerFactory.CreateLogger<HubConnectionHandler<THub>>();
_userIdProvider = userIdProvider; _userIdProvider = userIdProvider;
_dispatcher = dispatcher; _dispatcher = dispatcher;
_enableDetailedErrors = _hubOptions.EnableDetailedErrors ?? _globalHubOptions.EnableDetailedErrors ?? false;
} }
public override async Task OnConnectedAsync(ConnectionContext connection) public override async Task OnConnectedAsync(ConnectionContext connection)
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.SignalR
var connectionContext = new HubConnectionContext(connection, keepAlive, _loggerFactory); var connectionContext = new HubConnectionContext(connection, keepAlive, _loggerFactory);
if (!await connectionContext.HandshakeAsync(handshakeTimeout, supportedProtocols, _protocolResolver, _userIdProvider)) if (!await connectionContext.HandshakeAsync(handshakeTimeout, supportedProtocols, _protocolResolver, _userIdProvider, _enableDetailedErrors))
{ {
return; return;
} }
@ -139,9 +139,13 @@ namespace Microsoft.AspNetCore.SignalR
private async Task SendCloseAsync(HubConnectionContext connection, Exception exception) private async Task SendCloseAsync(HubConnectionContext connection, Exception exception)
{ {
CloseMessage closeMessage = exception == null var closeMessage = CloseMessage.Empty;
? CloseMessage.Empty
: new CloseMessage($"Connection closed with an error. {exception.GetType().Name}: {exception.Message}"); if (exception != null)
{
var errorMessage = ErrorMessageHelper.BuildErrorMessage("Connection closed with an error.", exception, _enableDetailedErrors);
closeMessage = new CloseMessage(errorMessage);
}
try try
{ {

View File

@ -17,5 +17,7 @@ namespace Microsoft.AspNetCore.SignalR
public TimeSpan? KeepAliveInterval { get; set; } = null; public TimeSpan? KeepAliveInterval { get; set; } = null;
public IList<string> SupportedProtocols { get; set; } = null; public IList<string> SupportedProtocols { get; set; } = null;
public bool? EnableDetailedErrors { get; set; } = null;
} }
} }

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.SignalR.Internal.Protocol;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;

View File

@ -15,6 +15,7 @@ using Microsoft.AspNetCore.SignalR.Internal.Protocol;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR.Internal namespace Microsoft.AspNetCore.SignalR.Internal
{ {
@ -24,11 +25,14 @@ namespace Microsoft.AspNetCore.SignalR.Internal
private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IHubContext<THub> _hubContext; private readonly IHubContext<THub> _hubContext;
private readonly ILogger<HubDispatcher<THub>> _logger; private readonly ILogger<HubDispatcher<THub>> _logger;
private readonly bool _enableDetailedErrors;
public DefaultHubDispatcher(IServiceScopeFactory serviceScopeFactory, IHubContext<THub> hubContext, ILogger<DefaultHubDispatcher<THub>> logger) public DefaultHubDispatcher(IServiceScopeFactory serviceScopeFactory, IHubContext<THub> hubContext, IOptions<HubOptions<THub>> hubOptions,
IOptions<HubOptions> globalHubOptions, ILogger<DefaultHubDispatcher<THub>> logger)
{ {
_serviceScopeFactory = serviceScopeFactory; _serviceScopeFactory = serviceScopeFactory;
_hubContext = hubContext; _hubContext = hubContext;
_enableDetailedErrors = hubOptions.Value.EnableDetailedErrors ?? globalHubOptions.Value.EnableDetailedErrors ?? false;
_logger = logger; _logger = logger;
DiscoverHubMethods(); DiscoverHubMethods();
} }
@ -172,7 +176,9 @@ namespace Microsoft.AspNetCore.SignalR.Internal
if (hubMethodInvocationMessage.ArgumentBindingException != null) if (hubMethodInvocationMessage.ArgumentBindingException != null)
{ {
Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, hubMethodInvocationMessage.ArgumentBindingException); Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, hubMethodInvocationMessage.ArgumentBindingException);
await SendInvocationError(hubMethodInvocationMessage, connection, $"Failed to invoke '{hubMethodInvocationMessage.Target}'. {hubMethodInvocationMessage.ArgumentBindingException.Message}"); var errorMessage = ErrorMessageHelper.BuildErrorMessage($"Failed to invoke '{hubMethodInvocationMessage.Target}' due to an error on the server.",
hubMethodInvocationMessage.ArgumentBindingException, _enableDetailedErrors);
await SendInvocationError(hubMethodInvocationMessage, connection, errorMessage);
return; return;
} }
@ -209,12 +215,14 @@ namespace Microsoft.AspNetCore.SignalR.Internal
catch (TargetInvocationException ex) catch (TargetInvocationException ex)
{ {
Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex); Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex);
await SendInvocationError(hubMethodInvocationMessage, connection, BuildUnexpectedErrorMessage(hubMethodInvocationMessage.Target, ex.InnerException)); await SendInvocationError(hubMethodInvocationMessage, connection,
ErrorMessageHelper.BuildErrorMessage($"An unexpected error occurred invoking '{hubMethodInvocationMessage.Target}' on the server.", ex.InnerException, _enableDetailedErrors));
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex); Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex);
await SendInvocationError(hubMethodInvocationMessage, connection, BuildUnexpectedErrorMessage(hubMethodInvocationMessage.Target, ex)); await SendInvocationError(hubMethodInvocationMessage, connection,
ErrorMessageHelper.BuildErrorMessage($"An unexpected error occurred invoking '{hubMethodInvocationMessage.Target}' on the server.", ex, _enableDetailedErrors));
} }
finally finally
{ {
@ -223,11 +231,6 @@ namespace Microsoft.AspNetCore.SignalR.Internal
} }
} }
private string BuildUnexpectedErrorMessage(string methodName, Exception exception)
{
return $"An unexpected error occurred invoking '{methodName}' on the server. {exception.GetType().Name}: {exception.Message}";
}
private async Task StreamResultsAsync(string invocationId, HubConnectionContext connection, IAsyncEnumerator<object> enumerator) private async Task StreamResultsAsync(string invocationId, HubConnectionContext connection, IAsyncEnumerator<object> enumerator)
{ {
string error = null; string error = null;
@ -243,7 +246,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal
catch (ChannelClosedException ex) catch (ChannelClosedException ex)
{ {
// If the channel closes from an exception in the streaming method, grab the innerException for the error from the streaming method // If the channel closes from an exception in the streaming method, grab the innerException for the error from the streaming method
error = ex.InnerException == null ? ex.Message : ex.InnerException.Message; error = ErrorMessageHelper.BuildErrorMessage("An error occurred on the server while streaming results.", ex.InnerException ?? ex, _enableDetailedErrors);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -251,7 +254,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal
if (!(ex is OperationCanceledException && connection.ActiveRequestCancellationSources.TryGetValue(invocationId, out var cts) if (!(ex is OperationCanceledException && connection.ActiveRequestCancellationSources.TryGetValue(invocationId, out var cts)
&& cts.IsCancellationRequested)) && cts.IsCancellationRequested))
{ {
error = ex.Message; error = ErrorMessageHelper.BuildErrorMessage("An error occurred on the server while streaming results.", ex, _enableDetailedErrors);
} }
} }
finally finally

View File

@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNetCore.SignalR.Internal
{
internal static class ErrorMessageHelper
{
internal static string BuildErrorMessage(string message, Exception exception, bool includeExceptionDetails)
{
if (!includeExceptionDetails)
{
return message;
}
return message + $" {exception.GetType().Name}: {exception.Message}";
}
}
}

View File

@ -415,7 +415,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
var channel = await connection.StreamAsChannelAsync<int>("StreamException").OrTimeout(); var channel = await connection.StreamAsChannelAsync<int>("StreamException").OrTimeout();
var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout()); var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout());
Assert.Equal("An unexpected error occurred invoking 'StreamException' on the server. InvalidOperationException: Error occurred while streaming.", ex.Message); Assert.Equal("An unexpected error occurred invoking 'StreamException' on the server.", ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
await connection.StartAsync().OrTimeout(); await connection.StartAsync().OrTimeout();
var ex = await Assert.ThrowsAsync<HubException>(() => connection.InvokeAsync("Echo", "p1", 42)).OrTimeout(); var ex = await Assert.ThrowsAsync<HubException>(() => connection.InvokeAsync("Echo", "p1", 42)).OrTimeout();
Assert.Equal("Failed to invoke 'Echo'. Invocation provides 2 argument(s) but target expects 1.", ex.Message); Assert.Equal("Failed to invoke 'Echo' due to an error on the server.", ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -496,7 +496,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
await connection.StartAsync().OrTimeout(); await connection.StartAsync().OrTimeout();
var ex = await Assert.ThrowsAsync<HubException>(() => connection.InvokeAsync("Echo", new int[] { 42 })).OrTimeout(); var ex = await Assert.ThrowsAsync<HubException>(() => connection.InvokeAsync("Echo", new int[] { 42 })).OrTimeout();
Assert.StartsWith("Failed to invoke 'Echo'. Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.", ex.Message); Assert.StartsWith("Failed to invoke 'Echo' due to an error on the server.", ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -553,7 +553,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
var channel = await connection.StreamAsChannelAsync<int>("Stream", 42, 42); var channel = await connection.StreamAsChannelAsync<int>("Stream", 42, 42);
var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout()); var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout());
Assert.Equal("Failed to invoke 'Stream'. Invocation provides 2 argument(s) but target expects 1.", ex.Message); Assert.Equal("Failed to invoke 'Stream' due to an error on the server.", ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -581,7 +581,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
var channel = await connection.StreamAsChannelAsync<int>("Stream", "xyz"); var channel = await connection.StreamAsChannelAsync<int>("Stream", "xyz");
var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout()); var ex = await Assert.ThrowsAsync<HubException>(() => channel.ReadAllAsync().OrTimeout());
Assert.StartsWith("Failed to invoke 'Stream'. Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.", ex.Message); Assert.Equal("Failed to invoke 'Stream' due to an error on the server.", ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -637,11 +637,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
[Theory] [Theory]
[InlineData(nameof(MethodHub.MethodThatThrows))] [InlineData(nameof(MethodHub.MethodThatThrows), true)]
[InlineData(nameof(MethodHub.MethodThatYieldsFailedTask))] [InlineData(nameof(MethodHub.MethodThatYieldsFailedTask), false)]
public async Task HubMethodCanThrowOrYieldFailedTask(string methodName) public async Task HubMethodCanThrowOrYieldFailedTask(string methodName, bool detailedErrors)
{ {
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(); var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
{
builder.AddSignalR(options =>
{
options.EnableDetailedErrors = detailedErrors;
});
});
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<MethodHub>>(); var connectionHandler = serviceProvider.GetService<HubConnectionHandler<MethodHub>>();
@ -651,7 +657,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests
var message = await client.InvokeAsync(methodName).OrTimeout(); var message = await client.InvokeAsync(methodName).OrTimeout();
Assert.Equal($"An unexpected error occurred invoking '{methodName}' on the server. InvalidOperationException: BOOM!", message.Error); if (detailedErrors)
{
Assert.Equal($"An unexpected error occurred invoking '{methodName}' on the server. InvalidOperationException: BOOM!", message.Error);
}
else
{
Assert.Equal($"An unexpected error occurred invoking '{methodName}' on the server.", message.Error);
}
// kill the connection // kill the connection
client.Dispose(); client.Dispose();
@ -1596,10 +1609,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task ReceiveCorrectErrorFromStreamThrowing() [InlineData(true)]
[InlineData(false)]
public async Task ReceiveCorrectErrorFromStreamThrowing(bool detailedErrors)
{ {
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(); var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
builder.AddSignalR(options =>
{
options.EnableDetailedErrors = detailedErrors;
}));
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<StreamingHub>>(); var connectionHandler = serviceProvider.GetService<HubConnectionHandler<StreamingHub>>();
using (var client = new TestClient()) using (var client = new TestClient())
@ -1613,7 +1632,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests
Assert.Equal(1, messages.Count); Assert.Equal(1, messages.Count);
var completion = messages[0] as CompletionMessage; var completion = messages[0] as CompletionMessage;
Assert.NotNull(completion); Assert.NotNull(completion);
Assert.Equal("Exception from observable", completion.Error); if (detailedErrors)
{
Assert.Equal("An error occurred on the server while streaming results. Exception: Exception from observable", completion.Error);
}
else
{
Assert.Equal("An error occurred on the server while streaming results.", completion.Error);
}
client.Dispose(); client.Dispose();
@ -2041,10 +2067,18 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task ErrorInHubOnConnectSendsCloseMessageWithError() [InlineData(true)]
[InlineData(false)]
public async Task ErrorInHubOnConnectSendsCloseMessageWithError(bool detailedErrors)
{ {
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(); var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
{
builder.AddSignalR(options =>
{
options.EnableDetailedErrors = detailedErrors;
});
});
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<OnConnectedThrowsHub>>(); var connectionHandler = serviceProvider.GetService<HubConnectionHandler<OnConnectedThrowsHub>>();
using (var client = new TestClient(false, new JsonHubProtocol())) using (var client = new TestClient(false, new JsonHubProtocol()))
@ -2054,7 +2088,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests
var message = await client.ReadAsync().OrTimeout(); var message = await client.ReadAsync().OrTimeout();
var closeMessage = Assert.IsType<CloseMessage>(message); var closeMessage = Assert.IsType<CloseMessage>(message);
Assert.Equal("Connection closed with an error. InvalidOperationException: Hub OnConnected failed.", closeMessage.Error); if (detailedErrors)
{
Assert.Equal("Connection closed with an error. InvalidOperationException: Hub OnConnected failed.", closeMessage.Error);
}
else
{
Assert.Equal("Connection closed with an error.", closeMessage.Error);
}
await connectionHandlerTask.OrTimeout(); await connectionHandlerTask.OrTimeout();
} }