Merge branch 'release/2.1' into dev
This commit is contained in:
commit
381ac2946c
|
|
@ -63,6 +63,22 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
}
|
||||
|
||||
ViewData = viewContext.ViewData as ViewDataDictionary<TModel>;
|
||||
|
||||
if (ViewData == null)
|
||||
{
|
||||
// The view data that we have at this point might be of a more derived type than the one defined at compile time.
|
||||
// For example ViewDataDictionary<Derived> where our TModel is Base and Derived : Base.
|
||||
// This can't happen for regular views, but it can happen in razor pages if someone modified the model type through
|
||||
// the page application model.
|
||||
// In that case, we check if the type of the current view data, 'ViewDataDictionary<TRuntime>' is "covariant" with the
|
||||
// one defined at compile time 'ViewDataDictionary<TCompile>'
|
||||
var runtimeType = viewContext.ViewData.ModelMetadata.ModelType;
|
||||
if (runtimeType != null && typeof(TModel) != runtimeType && typeof(TModel).IsAssignableFrom(runtimeType))
|
||||
{
|
||||
ViewData = new ViewDataDictionary<TModel>(viewContext.ViewData, viewContext.ViewData.Model);
|
||||
}
|
||||
}
|
||||
|
||||
if (ViewData == null)
|
||||
{
|
||||
// viewContext may contain a base ViewDataDictionary instance. So complain about that type, not TModel.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Xunit;
|
||||
|
|
@ -286,6 +287,81 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
|
|||
Assert.Equal(expectedString, result.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Contextualize_WorksWithCovariantViewDataDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var helperToContextualize = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<BaseModel>(model: null);
|
||||
|
||||
var viewContext = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<DerivedModel>(model: null)
|
||||
.ViewContext;
|
||||
|
||||
// Act
|
||||
helperToContextualize.Contextualize(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<ViewDataDictionary<BaseModel>>(
|
||||
helperToContextualize.ViewData);
|
||||
|
||||
Assert.Same(helperToContextualize.ViewContext, viewContext);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Contextualize_ThrowsIfViewDataDictionariesAreNotCompatible()
|
||||
{
|
||||
// Arrange
|
||||
var helperToContextualize = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<BaseModel>(model: null);
|
||||
|
||||
var viewContext = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<NonDerivedModel>(model: null)
|
||||
.ViewContext;
|
||||
|
||||
var expectedMessage = $"Property '{nameof(ViewContext.ViewData)}' is of type " +
|
||||
$"'{typeof(ViewDataDictionary<NonDerivedModel>).FullName}'," +
|
||||
$" but this method requires a value of type '{typeof(ViewDataDictionary<BaseModel>).FullName}'.";
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<ArgumentException>("viewContext", () => helperToContextualize.Contextualize(viewContext));
|
||||
Assert.Contains(expectedMessage, exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Contextualize_ThrowsForNonGenericViewDataDictionaries()
|
||||
{
|
||||
// Arrange
|
||||
var helperToContextualize = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<BaseModel>(model: null);
|
||||
|
||||
var viewContext = DefaultTemplatesUtilities
|
||||
.GetHtmlHelper<BaseModel>(model: null)
|
||||
.ViewContext;
|
||||
viewContext.ViewData = new ViewDataDictionary(viewContext.ViewData);
|
||||
|
||||
var expectedMessage = $"Property '{nameof(ViewContext.ViewData)}' is of type " +
|
||||
$"'{typeof(ViewDataDictionary).FullName}'," +
|
||||
$" but this method requires a value of type '{typeof(ViewDataDictionary<BaseModel>).FullName}'.";
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<ArgumentException>("viewContext", () => helperToContextualize.Contextualize(viewContext));
|
||||
Assert.Contains(expectedMessage, exception.Message);
|
||||
}
|
||||
|
||||
private class BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
private class DerivedModel : BaseModel
|
||||
{
|
||||
}
|
||||
|
||||
private class NonDerivedModel
|
||||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("SomeName", "SomeName")]
|
||||
[InlineData("Obj1.Prop1", "Obj1_Prop1")]
|
||||
|
|
|
|||
Loading…
Reference in New Issue