diff --git a/src/System.Web.Http/ExceptionHandling/ExceptionHandlerContext.cs b/src/System.Web.Http/ExceptionHandling/ExceptionHandlerContext.cs index b907c744..888ac013 100644 --- a/src/System.Web.Http/ExceptionHandling/ExceptionHandlerContext.cs +++ b/src/System.Web.Http/ExceptionHandling/ExceptionHandlerContext.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. +using System.Net.Http; +using System.Web.Http.Controllers; + namespace System.Web.Http.ExceptionHandling { /// Represents the context within which unhandled exception handling occurs. @@ -19,7 +22,7 @@ namespace System.Web.Http.ExceptionHandling _exceptionContext = exceptionContext; } - /// Gets or sets the exception context providing the exception and related data. + /// Gets the exception context providing the exception and related data. public ExceptionContext ExceptionContext { get { return _exceptionContext; } @@ -30,5 +33,29 @@ namespace System.Web.Http.ExceptionHandling /// If this value is , the exception is left unhandled and will be re-thrown. /// public IHttpActionResult Result { get; set; } + + /// Gets the exception caught. + public Exception Exception + { + get { return _exceptionContext.Exception; } + } + + /// Gets the catch block in which the exception was caught. + public ExceptionContextCatchBlock CatchBlock + { + get { return _exceptionContext.CatchBlock; } + } + + /// Gets the request being processed when the exception was caught. + public HttpRequestMessage Request + { + get { return _exceptionContext.Request; } + } + + /// Gets the request context in which the exception occurred. + public HttpRequestContext RequestContext + { + get { return _exceptionContext.RequestContext; } + } } } diff --git a/src/System.Web.Http/ExceptionHandling/ExceptionLoggerContext.cs b/src/System.Web.Http/ExceptionHandling/ExceptionLoggerContext.cs index 2cabb824..8b03e662 100644 --- a/src/System.Web.Http/ExceptionHandling/ExceptionLoggerContext.cs +++ b/src/System.Web.Http/ExceptionHandling/ExceptionLoggerContext.cs @@ -1,5 +1,10 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. +using System.Diagnostics.Contracts; +using System.Net.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Properties; + namespace System.Web.Http.ExceptionHandling { /// Represents the context within which unhandled exception logging occurs. @@ -21,10 +26,68 @@ namespace System.Web.Http.ExceptionHandling _exceptionContext = exceptionContext; } - /// Gets or sets the exception context providing the exception and related data. + /// Gets the exception context providing the exception and related data. public ExceptionContext ExceptionContext { get { return _exceptionContext; } } + + /// Gets the exception caught. + public Exception Exception + { + get { return _exceptionContext.Exception; } + } + + /// Gets the catch block in which the exception was caught. + public ExceptionContextCatchBlock CatchBlock + { + get { return _exceptionContext.CatchBlock; } + } + + /// Gets the request being processed when the exception was caught. + public HttpRequestMessage Request + { + get { return _exceptionContext.Request; } + } + + /// Gets the request context in which the exception occurred. + public HttpRequestContext RequestContext + { + get { return _exceptionContext.RequestContext; } + } + + /// + /// Gets or sets a value indicating whether the exception can subsequently be handled by an + /// to produce a new response message. + /// + /// + /// + /// Some exceptions are caught after a response is already partially sent, which prevents sending a new + /// response to handle the exception. In such cases, will be called to log the + /// exception, but the will not be called. + /// + /// + /// If this value is , exceptions from this catch block will be provided to both + /// and . If this value is + /// see langword="false"/>, exceptions from this catch block cannot be handled and will only be provided to + /// . + /// + /// + public bool CallsHandler + { + get + { + Contract.Assert(_exceptionContext != null); + ExceptionContextCatchBlock catchBlock = _exceptionContext.CatchBlock; + + if (catchBlock == null) + { + throw new InvalidOperationException(Error.Format(SRResources.TypePropertyMustNotBeNull, + typeof(ExceptionContext).Name, "CatchBlock")); + } + + return catchBlock.CallsHandler; + } + } } } diff --git a/test/System.Web.Http.Test/ExceptionHandling/ExceptionHandlerContextTests.cs b/test/System.Web.Http.Test/ExceptionHandling/ExceptionHandlerContextTests.cs index 29beed65..a1006387 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/ExceptionHandlerContextTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/ExceptionHandlerContextTests.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. +using System.Net.Http; +using System.Web.Http.Controllers; using Microsoft.TestCommon; using Moq; @@ -46,6 +48,80 @@ namespace System.Web.Http.ExceptionHandling Assert.Same(expectedResult, result); } + [Fact] + public void ExceptionGet_ReturnsSpecifiedInstance() + { + // Arrange + Exception expectedException = new InvalidOperationException(); + ExceptionContext context = new ExceptionContext + { + Exception = expectedException + }; + ExceptionHandlerContext product = CreateProductUnderTest(context); + + // Act + Exception exception = product.Exception; + + // Assert + Assert.Same(expectedException, exception); + } + + [Fact] + public void CatchBlockGet_ReturnsSpecifiedInstance() + { + // Arrange + ExceptionContextCatchBlock expectedCatchBlock = new ExceptionContextCatchBlock("IgnoreName", false, false); + ExceptionContext context = new ExceptionContext + { + CatchBlock = expectedCatchBlock + }; + ExceptionHandlerContext product = CreateProductUnderTest(context); + + // Act + ExceptionContextCatchBlock catchBlock = product.CatchBlock; + + // Assert + Assert.Same(expectedCatchBlock, catchBlock); + } + + [Fact] + public void RequestGet_ReturnsSpecifiedInstance() + { + // Arrange + using (HttpRequestMessage expectedRequest = new HttpRequestMessage()) + { + ExceptionContext context = new ExceptionContext + { + Request = expectedRequest + }; + ExceptionHandlerContext product = CreateProductUnderTest(context); + + // Act + HttpRequestMessage request = product.Request; + + // Assert + Assert.Same(expectedRequest, request); + } + } + + [Fact] + public void RequestContextGet_ReturnsSpecifiedInstance() + { + // Arrange + HttpRequestContext expectedRequestContext = new HttpRequestContext(); + ExceptionContext context = new ExceptionContext + { + RequestContext = expectedRequestContext + }; + ExceptionHandlerContext product = CreateProductUnderTest(context); + + // Act + HttpRequestContext requestContext = product.RequestContext; + + // Assert + Assert.Same(expectedRequestContext, requestContext); + } + private static ExceptionContext CreateContext() { return new ExceptionContext(); diff --git a/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerContextTests.cs b/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerContextTests.cs index fcf8f9d0..ac90f71d 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerContextTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerContextTests.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. +using System.Net.Http; +using System.Web.Http.Controllers; using Microsoft.TestCommon; namespace System.Web.Http.ExceptionHandling @@ -30,6 +32,113 @@ namespace System.Web.Http.ExceptionHandling Assert.Same(expectedContext, context); } + [Fact] + public void ExceptionGet_ReturnsSpecifiedInstance() + { + // Arrange + Exception expectedException = new InvalidOperationException(); + ExceptionContext context = new ExceptionContext + { + Exception = expectedException + }; + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act + Exception exception = product.Exception; + + // Assert + Assert.Same(expectedException, exception); + } + + [Fact] + public void CatchBlockGet_ReturnsSpecifiedInstance() + { + // Arrange + ExceptionContextCatchBlock expectedCatchBlock = new ExceptionContextCatchBlock("IgnoreName", false, false); + ExceptionContext context = new ExceptionContext + { + CatchBlock = expectedCatchBlock + }; + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act + ExceptionContextCatchBlock catchBlock = product.CatchBlock; + + // Assert + Assert.Same(expectedCatchBlock, catchBlock); + } + + [Fact] + public void RequestGet_ReturnsSpecifiedInstance() + { + // Arrange + using (HttpRequestMessage expectedRequest = new HttpRequestMessage()) + { + ExceptionContext context = new ExceptionContext + { + Request = expectedRequest + }; + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act + HttpRequestMessage request = product.Request; + + // Assert + Assert.Same(expectedRequest, request); + } + } + + [Fact] + public void RequestContextGet_ReturnsSpecifiedInstance() + { + // Arrange + HttpRequestContext expectedRequestContext = new HttpRequestContext(); + ExceptionContext context = new ExceptionContext + { + RequestContext = expectedRequestContext + }; + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act + HttpRequestContext requestContext = product.RequestContext; + + // Assert + Assert.Same(expectedRequestContext, requestContext); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CallsHandlerGet_ReturnsCatchBlockCallsHandler(bool expectedCallsHandler) + { + // Arrange + ExceptionContext context = new ExceptionContext + { + CatchBlock = new ExceptionContextCatchBlock("IgnoreName", isTopLevel: false, + callsHandler: expectedCallsHandler) + }; + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act + bool callsHandler = product.CallsHandler; + + // Assert + Assert.Equal(expectedCallsHandler, callsHandler); + } + + [Fact] + public void CallsHandlerGet_IfCatchBlockIsNull_Throws() + { + // Arrange + ExceptionContext context = new ExceptionContext(); + Assert.Null(context.CatchBlock); // Guard + ExceptionLoggerContext product = CreateProductUnderTest(context); + + // Act & Assert + Assert.Throws(() => product.CallsHandler, + "ExceptionContext.CatchBlock must not be null."); + } + private static ExceptionContext CreateContext() { return new ExceptionContext();