From 9ed753288f79329c339c72df315783facb157f86 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Mon, 22 Aug 2016 12:35:15 -0700 Subject: [PATCH] [Fixes #5170] Fixed KeyNotFoundException in UrlHelperFactory.GetUrlHelper() --- .../Routing/UrlHelperFactory.cs | 10 +-- .../Routing/UrlHelperTest.cs | 62 +++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Routing/UrlHelperFactory.cs b/src/Microsoft.AspNetCore.Mvc.Core/Routing/UrlHelperFactory.cs index 9c8962f15f..4fdf9daa3b 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Routing/UrlHelperFactory.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Routing/UrlHelperFactory.cs @@ -32,13 +32,15 @@ public IUrlHelper GetUrlHelper(ActionContext context) } // Perf: Create only one UrlHelper per context - var urlHelper = httpContext.Items[typeof(IUrlHelper)] as IUrlHelper; - if (urlHelper == null) + object value; + if (httpContext.Items.TryGetValue(typeof(IUrlHelper), out value) && value is IUrlHelper) { - urlHelper = new UrlHelper(context); - httpContext.Items[typeof(IUrlHelper)] = urlHelper; + return (IUrlHelper)value; } + var urlHelper = new UrlHelper(context); + httpContext.Items[typeof(IUrlHelper)] = urlHelper; + return urlHelper; } } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs index 22ce84c8c4..97e3f61c6a 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/UrlHelperTest.cs @@ -971,6 +971,68 @@ public void GenerateUrl_FastAndSlowPathsReturnsExpected( Assert.Equal(expected, url); } + [Fact] + public void GetUrlHelper_ReturnsSameInstance_IfAlreadyPresent() + { + // Arrange + var expectedUrlHelper = CreateUrlHelper(); + var httpContext = new Mock(); + var mockItems = new Dictionary + { + { typeof(IUrlHelper), expectedUrlHelper } + }; + httpContext.Setup(h => h.Items).Returns(mockItems); + + var actionContext = CreateActionContext(httpContext.Object, Mock.Of()); + var urlHelperFactory = new UrlHelperFactory(); + + // Act + var urlHelper = urlHelperFactory.GetUrlHelper(actionContext); + + // Assert + Assert.Same(expectedUrlHelper, urlHelper); + } + + [Fact] + public void GetUrlHelper_CreatesNewInstance_IfNotAlreadyPresent() + { + // Arrange + var httpContext = new Mock(); + httpContext.Setup(h => h.Items).Returns(new Dictionary()); + + var actionContext = CreateActionContext(httpContext.Object, Mock.Of()); + var urlHelperFactory = new UrlHelperFactory(); + + // Act + var urlHelper = urlHelperFactory.GetUrlHelper(actionContext); + + // Assert + Assert.NotNull(urlHelper); + Assert.Same(urlHelper, actionContext.HttpContext.Items[typeof(IUrlHelper)] as IUrlHelper); + } + + [Fact] + public void GetUrlHelper_CreatesNewInstance_IfExpectedTypeIsNotPresent() + { + // Arrange + var httpContext = new Mock(); + var mockItems = new Dictionary + { + { typeof(IUrlHelper), null } + }; + httpContext.Setup(h => h.Items).Returns(mockItems); + + var actionContext = CreateActionContext(httpContext.Object, Mock.Of()); + var urlHelperFactory = new UrlHelperFactory(); + + // Act + var urlHelper = urlHelperFactory.GetUrlHelper(actionContext); + + // Assert + Assert.NotNull(urlHelper); + Assert.Same(urlHelper, actionContext.HttpContext.Items[typeof(IUrlHelper)] as IUrlHelper); + } + private static HttpContext CreateHttpContext( IServiceProvider services, string appRoot)