Merge branch 'release' into dev

This commit is contained in:
Doug Bunting 2014-10-27 16:43:02 -07:00
commit 1f670bf3a7
5 changed files with 145 additions and 5 deletions

View File

@ -17,6 +17,11 @@ namespace MvcSample.Web
return View("MyView", CreateUser());
}
public IActionResult NullUser()
{
return View();
}
public ActionResult ValidationSummary()
{
ModelState.AddModelError("something", "Something happened, show up in validation summary.");

View File

@ -0,0 +1,42 @@
@*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
// ViewBag.Title = "Home Page";
}
@using MvcSample.Web.Models
@model User
<div class="row">
<div style="float: left; border: 5px solid lightblue; margin: 5px; padding: 7px;">
EditorForModel:
@Html.EditorForModel()
</div>
<div style="float: left; border: 5px solid blue; margin: 5px; padding: 7px;">
Editor of empty string:
@Html.Editor("")
</div>
<div style="float: left; border: 5px solid darkblue; margin: 5px; padding: 7px;">
EditorFor of identity expression:
@Html.EditorFor(m => m)
</div>
<div style="float: left; border: 5px solid red; margin: 5px; padding: 7px;">
DisplayForModel:
'@Html.DisplayForModel()'
</div>
<div style="float: left; border: 5px solid green; margin: 5px; padding: 7px;">
Display:
for name '@Html.Display("Name")'
and alive '@Html.Display("Alive")'
</div>
<div style="float: left; border: 5px solid cyan; margin: 5px; padding: 7px;">
Editor:
for name @Html.Editor("Name")
alive @Html.Editor("Alive")
and alive expression @Html.EditorFor(m => m.Alive)
</div>
</div>

View File

@ -33,7 +33,8 @@ namespace Microsoft.AspNet.Mvc
}
/// <summary>
/// <see cref="ViewDataDictionary"/> copy constructor for use when model type does not change.
/// <see cref="ViewDataDictionary"/> copy constructor for use when model type does not change or caller will
/// immediately set the <see cref="Model"/> property.
/// </summary>
public ViewDataDictionary([NotNull] ViewDataDictionary source)
: this(source, source.Model)
@ -50,9 +51,15 @@ namespace Microsoft.AspNet.Mvc
new CopyOnWriteDictionary<string, object>(source, StringComparer.OrdinalIgnoreCase),
new TemplateInfo(source.TemplateInfo))
{
_modelMetadata = source.ModelMetadata;
// If we're constructing a derived ViewDataDictionary (or any other value type),
// SetModel will throw if we try to set it to null. We should not throw in that case.
// Avoid copying information about the object type. To do so when model==null would confuse the
// ViewDataDictionary<TModel>.ModelMetadata getter.
if (source.ModelMetadata?.ModelType != typeof(object))
{
_modelMetadata = source.ModelMetadata;
}
// If we're constructing a derived ViewDataDictionary<TModel> where TModel is a non-Nullable value type,
// SetModel will throw if we try to call it with null. We should not throw in that case.
if (model != null)
{
SetModel(model);

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Microsoft.AspNet.FileSystems;
using Microsoft.CodeAnalysis;
@ -174,7 +175,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
{
var metadata = _metadataFileCache.GetOrAdd(path, _ =>
{
return AssemblyMetadata.CreateFromStream(File.OpenRead(path));
using (var stream = File.OpenRead(path))
{
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
return AssemblyMetadata.Create(moduleMetadata);
}
});
return metadata.GetReference();

View File

@ -159,6 +159,87 @@ namespace Microsoft.AspNet.Mvc.Core
Assert.IsType<CopyOnWriteDictionary<string, object>>(viewData.Data);
}
[Theory]
[InlineData(typeof(int))]
[InlineData(typeof(string))]
[InlineData(typeof(IEnumerable<string>))]
[InlineData(typeof(List<string>))]
[InlineData(typeof(string[]))]
[InlineData(typeof(Dictionary<string, object>))]
public void CopyConstructors_CopyModelMetadata(Type type)
{
// Arrange
var metadataProvider = new EmptyModelMetadataProvider();
var metadata = metadataProvider.GetMetadataForType(() => null, type);
var source = new ViewDataDictionary(metadataProvider)
{
ModelMetadata = metadata,
};
// Act
var viewData1 = new ViewDataDictionary(source);
var viewData2 = new ViewDataDictionary(source, model: null);
// Assert
Assert.Same(metadata, viewData1.ModelMetadata);
Assert.Same(metadata, viewData2.ModelMetadata);
}
[Fact]
public void CopyConstructors_IgnoreModelMetadata_IfForTypeObject()
{
// Arrange
var metadataProvider = new EmptyModelMetadataProvider();
var metadata = metadataProvider.GetMetadataForType(() => null, typeof(object));
var source = new ViewDataDictionary(metadataProvider)
{
ModelMetadata = metadata,
};
// Act
var viewData1 = new ViewDataDictionary(source);
var viewData2 = new ViewDataDictionary(source, model: null);
// Assert
Assert.Null(viewData1.ModelMetadata);
Assert.Null(viewData2.ModelMetadata);
}
[Theory]
[InlineData(typeof(int), "test string", typeof(string))]
[InlineData(typeof(string), 23, typeof(int))]
[InlineData(typeof(IEnumerable<string>), new[] { "1", "2", "3", }, typeof(object[]))]
[InlineData(typeof(List<string>), new[] { 1, 2, 3, }, typeof(object[]))]
public void CopyConstructors_OverrideSourceMetadata_IfModelNonNull(
Type sourceType,
object instance,
Type expectedType)
{
// Arrange
var metadataProvider = new EmptyModelMetadataProvider();
var metadata = metadataProvider.GetMetadataForType(() => null, sourceType);
var source = new ViewDataDictionary(metadataProvider)
{
ModelMetadata = metadata,
};
// Act
var viewData1 = new ViewDataDictionary(source)
{
Model = instance,
};
var viewData2 = new ViewDataDictionary(source, model: instance);
// Assert
Assert.NotNull(viewData1.ModelMetadata);
Assert.Equal(expectedType, viewData1.ModelMetadata.ModelType);
Assert.Equal(expectedType, viewData1.ModelMetadata.RealModelType);
Assert.NotNull(viewData2.ModelMetadata);
Assert.Equal(expectedType, viewData2.ModelMetadata.ModelType);
Assert.Equal(expectedType, viewData2.ModelMetadata.RealModelType);
}
public static TheoryData<object, string, object> Eval_EvaluatesExpressionsData
{
get