Fixes #76 - improve error messages in Hosting

Removed the TODOs from messages, and generally made them more readable.
This commit is contained in:
Eilon Lipton 2015-03-01 22:55:27 -08:00
parent 6bf5eabd9f
commit 16c8d51d0b
5 changed files with 65 additions and 25 deletions

View File

@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Hosting
catch (Exception ex) catch (Exception ex)
{ {
var logger = loggerFactory.Create<Program>(); var logger = loggerFactory.Create<Program>();
logger.WriteError("TODO: Dispose threw an exception", ex); logger.WriteError("Dispose threw an exception.", ex);
} }
shutdownHandle.Set(); shutdownHandle.Set();
}); });

View File

@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Hosting.Server
var assembly = Assembly.Load(new AssemblyName(assemblyName)); var assembly = Assembly.Load(new AssemblyName(assemblyName));
if (assembly == null) if (assembly == null)
{ {
throw new Exception(String.Format("TODO: assembly {0} failed to load message", assemblyName)); throw new Exception(string.Format("The assembly {0} failed to load.", assemblyName));
} }
Type type = null; Type type = null;
@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Hosting.Server
if (type == null) if (type == null)
{ {
throw new Exception(String.Format("TODO: type {0} failed to load message", typeName ?? "<null>")); throw new Exception(string.Format("The type {0} failed to load.", typeName ?? "<null>"));
} }
} }
else else
@ -59,14 +59,14 @@ namespace Microsoft.AspNet.Hosting.Server
if (type == null) if (type == null)
{ {
throw new Exception(String.Format("TODO: type {0} failed to load message", typeName ?? "<null>")); throw new Exception(String.Format("The type {0} failed to load.", typeName ?? "<null>"));
} }
interfaceInfo = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault(interf => interf.Equals(typeof(IServerFactory))); interfaceInfo = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault(interf => interf.Equals(typeof(IServerFactory)));
if (interfaceInfo == null) if (interfaceInfo == null)
{ {
throw new Exception("TODO: IServerFactory interface not found"); throw new Exception(string.Format("The type '{0}' does not implement the '{1}' interface.", type, typeof(IServerFactory).FullName));
} }
} }

View File

@ -31,9 +31,10 @@ namespace Microsoft.AspNet.Hosting.Startup
{ {
if (required) if (required)
{ {
throw new Exception(string.Format("TODO: {0} or {1} method not found", throw new Exception(string.Format("A method named '{0}' or '{1}' in the type '{2}' could not be found.",
methodNameWithEnv, methodNameWithEnv,
methodNameWithNoEnv)); methodNameWithNoEnv,
startupType.FullName));
} }
return null; return null;
@ -42,8 +43,10 @@ namespace Microsoft.AspNet.Hosting.Startup
{ {
if (required) if (required)
{ {
throw new Exception(string.Format("TODO: {0} method does not return " + returnType.Name, throw new Exception(string.Format("The '{0}' method in the type '{1}' must have a return type of '{2}'.",
methodInfo.Name)); methodInfo.Name,
startupType.FullName,
returnType.Name));
} }
return null; return null;
} }
@ -75,10 +78,11 @@ namespace Microsoft.AspNet.Hosting.Startup
catch (Exception) catch (Exception)
{ {
throw new Exception(string.Format( throw new Exception(string.Format(
"TODO: Unable to resolve service for {0} method {1} {2}", "Could not resolve a service of type '{0}' for the parameter '{1}' of method '{2}' on type '{3}'.",
methodInfo.Name, parameterInfo.ParameterType.FullName,
parameterInfo.Name, parameterInfo.Name,
parameterInfo.ParameterType.FullName)); methodInfo.Name,
methodInfo.DeclaringType.FullName));
} }
} }
} }
@ -98,26 +102,26 @@ namespace Microsoft.AspNet.Hosting.Startup
var assembly = Assembly.Load(new AssemblyName(applicationName)); var assembly = Assembly.Load(new AssemblyName(applicationName));
if (assembly == null) if (assembly == null)
{ {
throw new Exception(String.Format("TODO: assembly {0} failed to load message", applicationName)); throw new Exception(String.Format("The assembly '{0}' failed to load.", applicationName));
} }
var startupName1 = "Startup" + environmentName; var startupNameWithEnv = "Startup" + environmentName;
var startupName2 = "Startup"; var startupNameWithoutEnv = "Startup";
// Check the most likely places first // Check the most likely places first
var type = var type =
assembly.GetType(startupName1) ?? assembly.GetType(startupNameWithEnv) ??
assembly.GetType(applicationName + "." + startupName1) ?? assembly.GetType(applicationName + "." + startupNameWithEnv) ??
assembly.GetType(startupName2) ?? assembly.GetType(startupNameWithoutEnv) ??
assembly.GetType(applicationName + "." + startupName2); assembly.GetType(applicationName + "." + startupNameWithoutEnv);
if (type == null) if (type == null)
{ {
// Full scan // Full scan
var definedTypes = assembly.DefinedTypes.ToList(); var definedTypes = assembly.DefinedTypes.ToList();
var startupType1 = definedTypes.Where(info => info.Name.Equals(startupName1, StringComparison.Ordinal)); var startupType1 = definedTypes.Where(info => info.Name.Equals(startupNameWithEnv, StringComparison.Ordinal));
var startupType2 = definedTypes.Where(info => info.Name.Equals(startupName2, StringComparison.Ordinal)); var startupType2 = definedTypes.Where(info => info.Name.Equals(startupNameWithoutEnv, StringComparison.Ordinal));
var typeInfo = startupType1.Concat(startupType2).FirstOrDefault(); var typeInfo = startupType1.Concat(startupType2).FirstOrDefault();
if (typeInfo != null) if (typeInfo != null)
@ -128,9 +132,9 @@ namespace Microsoft.AspNet.Hosting.Startup
if (type == null) if (type == null)
{ {
throw new Exception(String.Format("TODO: {0} or {1} class not found in assembly {2}", throw new Exception(String.Format("A type named '{0}' or '{1}' could not be found in assembly '{2}'.",
startupName1, startupNameWithEnv,
startupName2, startupNameWithoutEnv,
applicationName)); applicationName));
} }

View File

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder;
namespace Microsoft.AspNet.Hosting.Fakes
{
public class StartupWithConfigureServicesNotResolved
{
public StartupWithConfigureServicesNotResolved()
{
}
public void Configure(IApplicationBuilder builder, int notAService)
{
}
}
}

View File

@ -114,7 +114,25 @@ namespace Microsoft.AspNet.Hosting.Tests
var diagnosticMessages = new List<string>(); var diagnosticMessages = new List<string>();
var ex = Assert.Throws<Exception>(() => loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "Boom", diagnosticMessages)); var ex = Assert.Throws<Exception>(() => loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "Boom", diagnosticMessages));
Assert.True(ex.Message.Contains("ConfigureBoom or Configure method not found")); Assert.Equal("A method named 'ConfigureBoom' or 'Configure' in the type 'Microsoft.AspNet.Hosting.Fakes.StartupBoom' could not be found.", ex.Message);
}
[Fact]
public void StartupWithConfigureServicesNotResolvedThrows()
{
var serviceCollection = HostingServices.Create();
var services = serviceCollection.BuildServiceProvider();
var loader = services.GetRequiredService<IStartupLoader>();
var diagnosticMessages = new List<string>();
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "WithConfigureServicesNotResolved", diagnosticMessages);
var app = new ApplicationBuilder(services);
var ex = Assert.Throws<Exception>(() => startup.Invoke(app));
Assert.Equal("Could not resolve a service of type 'System.Int32' for the parameter 'notAService' of method 'Configure' on type 'Microsoft.AspNet.Hosting.Fakes.StartupWithConfigureServicesNotResolved'.", ex.Message);
} }
[Fact] [Fact]