diff --git a/src/Microsoft.AspNetCore.Hosting/Startup/ConfigureBuilder.cs b/src/Microsoft.AspNetCore.Hosting/Startup/ConfigureBuilder.cs index 22bbc0f8cc..f781cb8976 100644 --- a/src/Microsoft.AspNetCore.Hosting/Startup/ConfigureBuilder.cs +++ b/src/Microsoft.AspNetCore.Hosting/Startup/ConfigureBuilder.cs @@ -37,14 +37,14 @@ namespace Microsoft.AspNetCore.Hosting.Startup { parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType); } - catch (Exception) + catch (Exception ex) { throw new Exception(string.Format( "Could not resolve a service of type '{0}' for the parameter '{1}' of method '{2}' on type '{3}'.", parameterInfo.ParameterType.FullName, parameterInfo.Name, MethodInfo.Name, - MethodInfo.DeclaringType.FullName)); + MethodInfo.DeclaringType.FullName), ex); } } } diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/Startup/ConfigureBuilderTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/Startup/ConfigureBuilderTests.cs new file mode 100644 index 0000000000..737d8bfca1 --- /dev/null +++ b/test/Microsoft.AspNetCore.Hosting.Tests/Startup/ConfigureBuilderTests.cs @@ -0,0 +1,54 @@ +// 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; +using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder.Internal; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Hosting.Startup.Tests +{ + public class ConfigureBuilderTests + { + [Fact] + public void CapturesServiceExceptionDetails() + { + var methodInfo = GetType().GetMethod(nameof(InjectedMethod), BindingFlags.NonPublic | BindingFlags.Static); + Assert.NotNull(methodInfo); + + var services = new ServiceCollection() + .AddSingleton() + .BuildServiceProvider(); + + var applicationBuilder = new ApplicationBuilder(services); + + var builder = new ConfigureBuilder(methodInfo); + Action action = builder.Build(instance:null); + var ex = Assert.Throws(() => action.Invoke(applicationBuilder)); + + Assert.NotNull(ex); + Assert.Equal($"Could not resolve a service of type '{typeof(CrasherService).FullName}' for the parameter" + + $" 'service' of method '{methodInfo.Name}' on type '{methodInfo.DeclaringType.FullName}'.", ex.Message); + + // the inner exception contains the root cause + Assert.NotNull(ex.InnerException); + Assert.Equal("Service instantiation failed", ex.InnerException.Message); + Assert.Contains(nameof(CrasherService), ex.InnerException.StackTrace); + } + + private static void InjectedMethod(CrasherService service) + { + Assert.NotNull(service); + } + + private class CrasherService + { + public CrasherService() + { + throw new Exception("Service instantiation failed"); + } + } + } +}