diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs index bc8f101547..f7f17724cc 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs @@ -209,8 +209,7 @@ namespace Microsoft.AspNet.Mvc.Rendering if (templateInfo.TemplateDepth > 1) { - // TODO: add ModelMetadata.SimpleDisplayText and use here (return SimpleDisplayText) - return modelMetadata.Model.ToString(); + return modelMetadata.Model == null ? modelMetadata.NullDisplayText : modelMetadata.SimpleDisplayText; } var serviceProvider = html.ViewContext.HttpContext.RequestServices; diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs index cc5cf71319..c39b2193c7 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs @@ -210,8 +210,7 @@ namespace Microsoft.AspNet.Mvc.Rendering if (templateInfo.TemplateDepth > 1) { - // TODO: add ModelMetadata.SimpleDisplayText and use here (return SimpleDisplayText, not ToString()) - return modelMetadata.Model == null ? modelMetadata.NullDisplayText : modelMetadata.Model.ToString(); + return modelMetadata.Model == null ? modelMetadata.NullDisplayText : modelMetadata.SimpleDisplayText; } var serviceProvider = html.ViewContext.HttpContext.RequestServices; diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj index 76b1c2d20e..705ded6643 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj @@ -59,6 +59,9 @@ + + + diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultDisplayTemplatesTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultDisplayTemplatesTests.cs new file mode 100644 index 0000000000..912a9c993c --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultDisplayTemplatesTests.cs @@ -0,0 +1,74 @@ +// 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 System; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.Rendering; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Core.Test +{ + public class DefaultDisplayTemplateTests + { + [Fact] + public void ObjectTemplateDisplaysSimplePropertiesOnObjectByDefault() + { + var expected = + "
Property1
" + Environment.NewLine + + "
Model = p1, ModelType = System.String, PropertyName = Property1," + + " SimpleDisplayText = p1
" + Environment.NewLine + + "
Property2
" + Environment.NewLine + + "
Model = (null), ModelType = System.String, PropertyName = Property2," + + " SimpleDisplayText = (null)
" + Environment.NewLine; + + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "p1", Property2 = null }; + var html = DefaultTemplatesUtilities.GetHtmlHelper(model); + + // Act + var result = DefaultDisplayTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(expected, result); + } + + [Fact] + public void ObjectTemplateDisplaysNullDisplayTextWhenObjectIsNull() + { + // Arrange + var html = DefaultTemplatesUtilities.GetHtmlHelper(null); + var metadata = + new EmptyModelMetadataProvider() + .GetMetadataForType(null, typeof(DefaultTemplatesUtilities.ObjectTemplateModel)); + metadata.NullDisplayText = "(null value)"; + html.ViewData.ModelMetadata = metadata; + + // Act + var result = DefaultDisplayTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(metadata.NullDisplayText, result); + } + + [Fact] + public void ObjectTemplateDisplaysSimpleDisplayTextWhenTemplateDepthGreaterThanOne() + { + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel(); + var html = DefaultTemplatesUtilities.GetHtmlHelper(model); + var metadata = + new EmptyModelMetadataProvider() + .GetMetadataForType(() => model, typeof(DefaultTemplatesUtilities.ObjectTemplateModel)); + metadata.SimpleDisplayText = "Simple Display Text"; + html.ViewData.ModelMetadata = metadata; + html.ViewData.TemplateInfo.AddVisited("foo"); + html.ViewData.TemplateInfo.AddVisited("bar"); + + // Act + var result = DefaultDisplayTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(metadata.SimpleDisplayText, result); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultEditorTemplatesTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultEditorTemplatesTests.cs new file mode 100644 index 0000000000..c5eee798a2 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultEditorTemplatesTests.cs @@ -0,0 +1,78 @@ +// 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 System; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.Rendering; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Core.Test +{ + public class DefaultEditorTemplatesTests + { + [Fact] + public void ObjectTemplateEditsSimplePropertiesOnObjectByDefault() + { + var expected = + "
" + Environment.NewLine + + "
Model = p1, ModelType = System.String, PropertyName = Property1," + + " SimpleDisplayText = p1
" + Environment.NewLine + + "
" + Environment.NewLine + + "
Model = (null), ModelType = System.String, PropertyName = Property2," + + " SimpleDisplayText = (null)
" + Environment.NewLine; + + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "p1", Property2 = null }; + var html = DefaultTemplatesUtilities.GetHtmlHelper(model); + + // Act + var result = DefaultEditorTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(expected, result); + } + + [Fact] + public void ObjectTemplateDisplaysNullDisplayTextWithNullModelAndTemplateDepthGreaterThanOne() + { + // Arrange + var html = DefaultTemplatesUtilities.GetHtmlHelper(null); + var metadata = + new EmptyModelMetadataProvider() + .GetMetadataForType(null, typeof(DefaultTemplatesUtilities.ObjectTemplateModel)); + metadata.NullDisplayText = "Null Display Text"; + metadata.SimpleDisplayText = "Simple Display Text"; + html.ViewData.ModelMetadata = metadata; + html.ViewData.TemplateInfo.AddVisited("foo"); + html.ViewData.TemplateInfo.AddVisited("bar"); + + // Act + var result = DefaultEditorTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(metadata.NullDisplayText, result); + } + + [Fact] + public void ObjectTemplateDisplaysSimpleDisplayTextWithNonNullModelTemplateDepthGreaterThanOne() + { + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel(); + var html = DefaultTemplatesUtilities.GetHtmlHelper(model); + var metadata = + new EmptyModelMetadataProvider() + .GetMetadataForType(() => model, typeof(DefaultTemplatesUtilities.ObjectTemplateModel)); + html.ViewData.ModelMetadata = metadata; + metadata.NullDisplayText = "Null Display Text"; + metadata.SimpleDisplayText = "Simple Display Text"; + html.ViewData.TemplateInfo.AddVisited("foo"); + html.ViewData.TemplateInfo.AddVisited("bar"); + + // Act + var result = DefaultEditorTemplates.ObjectTemplate(html); + + // Assert + Assert.Equal(metadata.SimpleDisplayText, result); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs new file mode 100644 index 0000000000..b48e7d3630 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs @@ -0,0 +1,119 @@ +// 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 System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.AspNet.Routing; +using Microsoft.AspNet.Security.DataProtection; +using Microsoft.Framework.OptionsModel; +using Moq; + +namespace Microsoft.AspNet.Mvc.Core.Test +{ + public class DefaultTemplatesUtilities + { + public class ObjectTemplateModel + { + public ObjectTemplateModel() + { + ComplexInnerModel = new object(); + } + + public string Property1 { get; set; } + public string Property2 { get; set; } + public object ComplexInnerModel { get; set; } + } + + public static HtmlHelper GetHtmlHelper(object model) + { + var provider = new DataAnnotationsModelMetadataProvider(); + var viewData = new ViewDataDictionary(provider); + viewData.Model = model; + viewData.ModelMetadata = + provider.GetMetadataForType(() => model, typeof(ObjectTemplateModel)); + + var httpContext = new Mock(); + httpContext + .Setup(o => o.Response) + .Returns(Mock.Of()); + httpContext + .Setup(o => o.Items) + .Returns(new Dictionary()); + + var view = new Mock(); + view + .Setup(v => v.RenderAsync(It.IsAny())) + .Callback(async (ViewContext v) => + { + await v.Writer.WriteAsync(FormatOutput(v.ViewData.ModelMetadata)); + }) + .Returns(Task.FromResult(0)); + + var routeDictionary = new Dictionary(); + var viewEngine = new Mock(); + viewEngine + .Setup(v => v.FindPartialView(routeDictionary, It.IsAny())) + .Returns(ViewEngineResult.Found("MyView", view.Object)); + + var serviceProvider = new Mock(); + serviceProvider + .Setup(s => s.GetService(typeof(IViewEngine))) + .Returns(viewEngine.Object); + serviceProvider + .Setup(s => s.GetService(typeof(IUrlHelper))) + .Returns(new Mock().Object); + serviceProvider + .Setup(s => s.GetService(typeof(IViewComponentHelper))) + .Returns(new Mock().Object); + + httpContext + .Setup(o => o.RequestServices) + .Returns(serviceProvider.Object); + + var actionContext = new ActionContext(httpContext.Object, + new RouteData() { Values = routeDictionary }, + new ActionDescriptor()); + + var viewContext = new ViewContext(actionContext, view.Object, viewData, new StringWriter()); + + var htmlHelper = new HtmlHelper( + viewEngine.Object, + provider, + new Mock().Object, + GetAntiForgeryInstance(), + new Mock().Object); + htmlHelper.Contextualize(viewContext); + + return htmlHelper; + } + + private static AntiForgery GetAntiForgeryInstance() + { + var claimExtractor = new Mock(); + var dataProtectionProvider = new Mock(); + var additionalDataProvider = new Mock(); + var optionsAccessor = new Mock>(); + optionsAccessor.SetupGet(o => o.Options).Returns(new MvcOptions()); + return new AntiForgery(claimExtractor.Object, + dataProtectionProvider.Object, + additionalDataProvider.Object, + optionsAccessor.Object); + } + + private static string FormatOutput(ModelMetadata metadata) + { + return string.Format(CultureInfo.InvariantCulture, + "Model = {0}, ModelType = {1}, PropertyName = {2}, SimpleDisplayText = {3}", + metadata.Model ?? "(null)", + metadata.ModelType == null ? "(null)" : metadata.ModelType.FullName, + metadata.PropertyName ?? "(null)", + metadata.SimpleDisplayText ?? "(null)"); + } + } +} \ No newline at end of file