diff --git a/src/Microsoft.AspNet.Mvc.Common/Microsoft.AspNet.Mvc.Common.kproj b/src/Microsoft.AspNet.Mvc.Common/Microsoft.AspNet.Mvc.Common.kproj index caf1d98985..c76849b092 100644 --- a/src/Microsoft.AspNet.Mvc.Common/Microsoft.AspNet.Mvc.Common.kproj +++ b/src/Microsoft.AspNet.Mvc.Common/Microsoft.AspNet.Mvc.Common.kproj @@ -23,7 +23,6 @@ - diff --git a/src/Microsoft.AspNet.Mvc.Common/PropertyActivator.cs b/src/Microsoft.AspNet.Mvc.Common/PropertyActivator.cs deleted file mode 100644 index 79ee86d091..0000000000 --- a/src/Microsoft.AspNet.Mvc.Common/PropertyActivator.cs +++ /dev/null @@ -1,51 +0,0 @@ -// 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.Linq; -using System.Reflection; - -namespace Microsoft.AspNet.Mvc -{ - internal class PropertyActivator - { - private readonly Func _valueAccessor; - private readonly Action _fastPropertySetter; - - public PropertyActivator(PropertyInfo propertyInfo, - Func valueAccessor) - { - PropertyInfo = propertyInfo; - _valueAccessor = valueAccessor; - _fastPropertySetter = PropertyHelper.MakeFastPropertySetter(propertyInfo); - } - - public PropertyInfo PropertyInfo { get; private set; } - - public object Activate(object view, TContext context) - { - var value = _valueAccessor(context); - _fastPropertySetter(view, value); - return value; - } - - /// - /// Returns a list of properties on a type that are decorated with - /// the specified activateAttributeType and have setters. - /// - public static PropertyActivator[] GetPropertiesToActivate( - Type type, - Type activateAttributeType, - Func> createActivateInfo) - { - return type.GetRuntimeProperties() - .Where(property => - property.IsDefined(activateAttributeType) && - property.GetIndexParameters().Length == 0 && - property.SetMethod != null && - !property.SetMethod.IsStatic) - .Select(createActivateInfo) - .ToArray(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs index a3846764f2..87918e6172 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; using System.Reflection; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.Core; @@ -17,9 +19,10 @@ namespace Microsoft.AspNet.Mvc /// public class DefaultControllerActivator : IControllerActivator { - private readonly Func[]> _getPropertiesToActivate; - private readonly IReadOnlyDictionary> _valueAccessorLookup; - private readonly ConcurrentDictionary[]> _injectActions; + private readonly Func _getPropertiesToActivate; + private readonly Func _createActivateInfo; + private readonly ReadOnlyDictionary> _valueAccessorLookup; + private readonly ConcurrentDictionary _injectActions; /// /// Initializes a new instance of the DefaultControllerActivator class. @@ -27,11 +30,9 @@ namespace Microsoft.AspNet.Mvc public DefaultControllerActivator() { _valueAccessorLookup = CreateValueAccessorLookup(); - _injectActions = new ConcurrentDictionary[]>(); - _getPropertiesToActivate = type => - PropertyActivator.GetPropertiesToActivate(type, - typeof(ActivateAttribute), - CreateActivateInfo); + _getPropertiesToActivate = GetPropertiesToActivate; + _createActivateInfo = CreateActivateInfo; + _injectActions = new ConcurrentDictionary(); } /// @@ -58,7 +59,7 @@ namespace Microsoft.AspNet.Mvc } } - protected virtual IReadOnlyDictionary> CreateValueAccessorLookup() + protected virtual ReadOnlyDictionary> CreateValueAccessorLookup() { var dictionary = new Dictionary> { @@ -77,11 +78,20 @@ namespace Microsoft.AspNet.Mvc } } }; - return dictionary; + return new ReadOnlyDictionary>(dictionary); } - private PropertyActivator CreateActivateInfo( - PropertyInfo property) + private PropertyActivator[] GetPropertiesToActivate(Type controllerType) + { + var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + return controllerType.GetProperties(bindingFlags) + .Where(property => property.IsDefined(typeof(ActivateAttribute)) && + property.GetSetMethod(nonPublic: true) != null) + .Select(_createActivateInfo) + .ToArray(); + } + + private PropertyActivator CreateActivateInfo(PropertyInfo property) { Func valueAccessor; if (!_valueAccessorLookup.TryGetValue(property.PropertyType, out valueAccessor)) @@ -93,7 +103,29 @@ namespace Microsoft.AspNet.Mvc }; } - return new PropertyActivator(property, valueAccessor); + return new PropertyActivator(property, + valueAccessor); + } + + private sealed class PropertyActivator + { + private readonly PropertyInfo _propertyInfo; + private readonly Func _valueAccessor; + private readonly Action _fastPropertySetter; + + public PropertyActivator(PropertyInfo propertyInfo, + Func valueAccessor) + { + _propertyInfo = propertyInfo; + _valueAccessor = valueAccessor; + _fastPropertySetter = PropertyHelper.MakeFastPropertySetter(propertyInfo); + } + + public void Activate(object instance, ActionContext context) + { + var value = _valueAccessor(context); + _fastPropertySetter(instance, value); + } } } } diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/InjectChunkVisitor.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/InjectChunkVisitor.cs index 0136b2a873..9194926bcc 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/InjectChunkVisitor.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/InjectChunkVisitor.cs @@ -11,14 +11,11 @@ namespace Microsoft.AspNet.Mvc.Razor public class InjectChunkVisitor : MvcCSharpCodeVisitor { private readonly List _injectChunks = new List(); - private readonly string _activateAttribute; public InjectChunkVisitor([NotNull] CSharpCodeWriter writer, - [NotNull] CodeGeneratorContext context, - [NotNull] string activateAttributeName) + [NotNull] CodeGeneratorContext context) : base(writer, context) { - _activateAttribute = '[' + activateAttributeName + ']'; } public List InjectChunks @@ -28,14 +25,7 @@ namespace Microsoft.AspNet.Mvc.Razor protected override void Visit([NotNull] InjectChunk chunk) { - Writer.WriteLine(_activateAttribute); - - // Some of the chunks that we visit are either InjectDescriptors that are added by default or - // are chunks from _ViewStart files and are not associated with any Spans. Invoking - // CreateExpressionMapping to produce line mappings on these chunks would fail. We'll skip - // generating code mappings for these chunks. This makes sense since the chunks do not map - // to any code in the current view. - if (Context.Host.DesignTimeMode && chunk.Association != null) + if (Context.Host.DesignTimeMode) { Writer.WriteLine("public"); var code = string.Format(CultureInfo.InvariantCulture, diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/InjectDescriptor.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/InjectDescriptor.cs deleted file mode 100644 index 36b7a566a9..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/InjectDescriptor.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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.Razor.Host; - -namespace Microsoft.AspNet.Mvc.Razor -{ - /// - /// Represents information about an injected property. - /// - public class InjectDescriptor - { - public InjectDescriptor(string typeName, string memberName) - { - if (string.IsNullOrEmpty(typeName)) - { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "typeName"); - } - - if (string.IsNullOrEmpty(memberName)) - { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "memberName"); - } - - TypeName = typeName; - MemberName = memberName; - } - - /// - /// Gets the type name of the injected property - /// - public string TypeName { get; private set; } - - /// - /// Gets the name of the injected property. - /// - public string MemberName { get; private set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/Microsoft.AspNet.Mvc.Razor.Host.kproj b/src/Microsoft.AspNet.Mvc.Razor.Host/Microsoft.AspNet.Mvc.Razor.Host.kproj index 3029d6ab23..227e4f8f8a 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/Microsoft.AspNet.Mvc.Razor.Host.kproj +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/Microsoft.AspNet.Mvc.Razor.Host.kproj @@ -24,7 +24,6 @@ - @@ -34,7 +33,6 @@ - diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcCSharpCodeBuilder.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcCSharpCodeBuilder.cs index 2c1cbe5e7b..9026fc2741 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcCSharpCodeBuilder.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcCSharpCodeBuilder.cs @@ -1,7 +1,6 @@ // 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.Linq; @@ -13,17 +12,11 @@ namespace Microsoft.AspNet.Mvc.Razor { public class MvcCSharpCodeBuilder : CSharpCodeBuilder { - private readonly MvcRazorHostOptions _hostOptions; - - public MvcCSharpCodeBuilder([NotNull] CodeGeneratorContext context, - [NotNull] MvcRazorHostOptions hostOptions) + public MvcCSharpCodeBuilder([NotNull] CodeGeneratorContext context) : base(context) { - _hostOptions = hostOptions; } - private string Model { get; set; } - protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer) { // Grab the last model chunk so it gets intellisense. @@ -32,8 +25,6 @@ namespace Microsoft.AspNet.Mvc.Razor var modelChunk = Context.CodeTreeBuilder.CodeTree.Chunks.OfType() .LastOrDefault(); - Model = modelChunk != null ? modelChunk.ModelType : _hostOptions.DefaultModel; - // If there were any model chunks then we need to modify the class declaration signature. if (modelChunk != null) { @@ -55,18 +46,26 @@ namespace Microsoft.AspNet.Mvc.Razor protected override void BuildConstructor([NotNull] CSharpCodeWriter writer) { - // TODO: Move this to a proper extension point. Right now, we don't have a place to print out properties - // in the generated view. - // Tracked by #773 - base.BuildConstructor(writer); - writer.WriteLineHiddenDirective(); - var injectVisitor = new InjectChunkVisitor(writer, Context, _hostOptions.ActivateAttributeName); + var injectVisitor = new InjectChunkVisitor(writer, Context); injectVisitor.Accept(Context.CodeTreeBuilder.CodeTree.Chunks); writer.WriteLine(); writer.WriteLineHiddenDirective(); + + var arguments = injectVisitor.InjectChunks + .Select(chunk => new KeyValuePair(chunk.TypeName, + chunk.MemberName)); + using (writer.BuildConstructor("public", Context.ClassName, arguments)) + { + foreach (var inject in injectVisitor.InjectChunks) + { + writer.WriteStartAssignment("this." + inject.MemberName) + .Write(inject.MemberName) + .WriteLine(";"); + } + } } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs index f601b3a516..6a08c7806a 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs @@ -2,9 +2,7 @@ // 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.IO; -using System.Linq; using Microsoft.AspNet.Razor; using Microsoft.AspNet.Razor.Generator; using Microsoft.AspNet.Razor.Generator.Compiler; @@ -26,8 +24,6 @@ namespace Microsoft.AspNet.Mvc.Razor "Microsoft.AspNet.Mvc.Rendering" }; - private readonly MvcRazorHostOptions _hostOptions; - // CodeGenerationContext.DefaultBaseClass is set to MyBaseType. // This field holds the type name without the generic decoration (MyBaseType) private readonly string _baseType; @@ -40,11 +36,8 @@ namespace Microsoft.AspNet.Mvc.Razor public MvcRazorHost(string baseType) : base(new CSharpRazorCodeLanguage()) { - // TODO: this needs to flow from the application rather than being initialized here. - // Tracked by #774 - _hostOptions = new MvcRazorHostOptions(); _baseType = baseType; - DefaultBaseClass = baseType + '<' + _hostOptions.DefaultModel + '>'; + DefaultBaseClass = baseType + ""; GeneratedClassContext = new GeneratedClassContext( executeMethodName: "ExecuteAsync", writeMethodName: "Write", @@ -80,34 +73,7 @@ namespace Microsoft.AspNet.Mvc.Razor public override CodeBuilder DecorateCodeBuilder(CodeBuilder incomingBuilder, CodeGeneratorContext context) { - UpdateCodeBuilder(context); - return new MvcCSharpCodeBuilder(context, _hostOptions); - } - - private void UpdateCodeBuilder(CodeGeneratorContext context) - { - var currentChunks = context.CodeTreeBuilder.CodeTree.Chunks; - var existingInjects = new HashSet(currentChunks.OfType() - .Select(c => c.MemberName), - StringComparer.Ordinal); - - var modelChunk = currentChunks.OfType() - .LastOrDefault(); - var model = _hostOptions.DefaultModel; - if (modelChunk != null) - { - model = modelChunk.ModelType; - } - model = '<' + model + '>'; - - // Locate properties by name that haven't already been injected in to the View. - var propertiesToAdd = _hostOptions.DefaultInjectedProperties - .Where(c => !existingInjects.Contains(c.MemberName)); - foreach (var property in propertiesToAdd) - { - var memberName = property.MemberName.Replace("", model); - currentChunks.Add(new InjectChunk(property.TypeName, memberName)); - } + return new MvcCSharpCodeBuilder(context); } } } diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs deleted file mode 100644 index 3ab5f0359c..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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.Collections.Generic; - -namespace Microsoft.AspNet.Mvc.Razor -{ - /// - /// Represents configuration options for the Razor Host - /// - public class MvcRazorHostOptions - { - public MvcRazorHostOptions() - { - DefaultModel = "dynamic"; - ActivateAttributeName = "Microsoft.AspNet.Mvc.ActivateAttribute"; - DefaultInjectedProperties = new List() - { - new InjectDescriptor("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper", "Html") - }; - } - - /// - /// Gets or sets the model that is used by default for generated views - /// when no model is explicily specified. Defaults to dynamic. - /// - public string DefaultModel { get; set; } - - /// - /// Gets or sets the attribue that is used to decorate properties that are injected and need to - /// be activated. - /// - public string ActivateAttributeName { get; set; } - - /// - /// Gets the list of properties that are injected by default. - /// - public IList DefaultInjectedProperties { get; private set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/Properties/Resources.Designer.cs index 4f2663c2b8..1dba347970 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/Properties/Resources.Designer.cs @@ -10,22 +10,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.AspNet.Mvc.Razor.Host.Resources", typeof(Resources).GetTypeInfo().Assembly); - /// - /// Argument cannot be null or empty. - /// - internal static string ArgumentCannotBeNullOrEmpy - { - get { return GetString("ArgumentCannotBeNullOrEmpy"); } - } - - /// - /// Argument cannot be null or empty. - /// - internal static string FormatArgumentCannotBeNullOrEmpy() - { - return GetString("ArgumentCannotBeNullOrEmpy"); - } - /// /// The 'inherits' keyword is not allowed when a '{0}' keyword is used. /// diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/Resources.resx b/src/Microsoft.AspNet.Mvc.Razor.Host/Resources.resx index cfa565507e..f6562cd582 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/Resources.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Argument cannot be null or empty. - The 'inherits' keyword is not allowed when a '{0}' keyword is used. diff --git a/src/Microsoft.AspNet.Mvc.Razor/IRazorViewActivator.cs b/src/Microsoft.AspNet.Mvc.Razor/IRazorViewActivator.cs deleted file mode 100644 index e3b2966170..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/IRazorViewActivator.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -namespace Microsoft.AspNet.Mvc.Razor -{ - /// - /// Provides methods to activate properties on a view instance. - /// - public interface IRazorViewActivator - { - /// - /// When implemented in a type, activates an instantiated view. - /// - /// The view to activate. - /// The for the view. - void Activate(RazorView view, ViewContext context); - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/Microsoft.AspNet.Mvc.Razor.kproj b/src/Microsoft.AspNet.Mvc.Razor/Microsoft.AspNet.Mvc.Razor.kproj index 86c67fcad0..19160b8e8a 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Microsoft.AspNet.Mvc.Razor.kproj +++ b/src/Microsoft.AspNet.Mvc.Razor/Microsoft.AspNet.Mvc.Razor.kproj @@ -30,11 +30,9 @@ - - @@ -44,4 +42,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.AspNet.Mvc.Razor/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.Razor/Properties/Resources.Designer.cs index 9f21c06c0c..ad44f215f9 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Properties/Resources.Designer.cs @@ -186,22 +186,6 @@ namespace Microsoft.AspNet.Mvc.Razor return string.Format(CultureInfo.CurrentCulture, GetString("SectionsNotRendered"), p0); } - /// - /// View of type '{0}' cannot be instatiated by '{1}'. - /// - internal static string ViewCannotBeActivated - { - get { return GetString("ViewCannotBeActivated"); } - } - - /// - /// View of type '{0}' cannot be instatiated by '{1}'. - /// - internal static string FormatViewCannotBeActivated(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("ViewCannotBeActivated"), p0, p1); - } - /// /// View '{0}' must have extension '{1}' when the view represents a full path. /// diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorViewActivator.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorViewActivator.cs deleted file mode 100644 index 57756a434a..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorViewActivator.cs +++ /dev/null @@ -1,125 +0,0 @@ -// 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.Concurrent; -using System.Reflection; -using Microsoft.AspNet.Mvc.Rendering; -using Microsoft.Framework.DependencyInjection; - -namespace Microsoft.AspNet.Mvc.Razor -{ - /// - public class RazorViewActivator : IRazorViewActivator - { - private readonly ITypeActivator _typeActivator; - private readonly ConcurrentDictionary _activationInfo; - - /// - /// Initializes a new instance of the RazorViewActivator class. - /// - public RazorViewActivator(ITypeActivator typeActivator) - { - _typeActivator = typeActivator; - _activationInfo = new ConcurrentDictionary(); - } - - /// - /// Activates the specified view by using the specified ViewContext. - /// - /// The view to activate. - /// The ViewContext for the executing view. - public void Activate([NotNull] RazorView view, [NotNull] ViewContext context) - { - var activationInfo = _activationInfo.GetOrAdd(view.GetType(), - CreateViewActivationInfo); - - context.ViewData = CreateViewDataDictionary(context, activationInfo); - - for (var i = 0; i < activationInfo.PropertyActivators.Length; i++) - { - var activateInfo = activationInfo.PropertyActivators[i]; - activateInfo.Activate(view, context); - } - } - - private ViewDataDictionary CreateViewDataDictionary(ViewContext context, ViewActivationInfo activationInfo) - { - // Create a ViewDataDictionary if the ViewContext.ViewData is not set or the type of - // ViewContext.ViewData is an incompatibile type. - if (context.ViewData == null) - { - // Create ViewDataDictionary(metadataProvider); - return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices, - activationInfo.ViewDataDictionaryType); - } - else if (context.ViewData.GetType() != activationInfo.ViewDataDictionaryType) - { - // Create ViewDataDictionary(ViewDataDictionary); - return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices, - activationInfo.ViewDataDictionaryType, - context.ViewData); - } - - return context.ViewData; - } - - private ViewActivationInfo CreateViewActivationInfo(Type type) - { - var typeInfo = type.GetTypeInfo(); - Type viewDataType; - if (!typeInfo.IsGenericType || typeInfo.GenericTypeArguments.Length != 1) - { - // Ensure that the view is of the type RazorView. - var message = Resources.FormatViewCannotBeActivated(type.FullName, GetType().FullName); - throw new InvalidOperationException(message); - } - - var modelType = typeInfo.GenericTypeArguments[0]; - viewDataType = typeof(ViewDataDictionary<>).MakeGenericType(modelType); - - return new ViewActivationInfo - { - ViewDataDictionaryType = viewDataType, - PropertyActivators = PropertyActivator.GetPropertiesToActivate(type, - typeof(ActivateAttribute), - CreateActivateInfo) - }; - } - - private PropertyActivator CreateActivateInfo(PropertyInfo property) - { - Func valueAccessor; - if (property.PropertyType.IsAssignableFrom(typeof(ViewDataDictionary))) - { - valueAccessor = context => context.ViewData; - } - else - { - valueAccessor = context => - { - var serviceProvider = context.HttpContext.RequestServices; - var value = serviceProvider.GetService(property.PropertyType); - var canHasViewContext = value as ICanHasViewContext; - if (canHasViewContext != null) - { - canHasViewContext.Contextualize(context); - } - - return value; - }; - } - - return new PropertyActivator(property, valueAccessor); - } - - private class ViewActivationInfo - { - public PropertyActivator[] PropertyActivators { get; set; } - - public Type ViewDataDictionaryType { get; set; } - - public Action ViewDataDictionarySetter { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs index 0523215dc5..80790fe364 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorViewOfT.cs @@ -1,7 +1,10 @@ // 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.IO; using System.Threading.Tasks; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.Rendering; using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc.Razor @@ -16,15 +19,43 @@ namespace Microsoft.AspNet.Mvc.Razor } } - [Activate] - public ViewDataDictionary ViewData { get; set; } + public ViewDataDictionary ViewData { get; private set; } + + public IHtmlHelper Html { get; set; } public override Task RenderAsync([NotNull] ViewContext context) { - var viewActivator = context.HttpContext.RequestServices.GetService(); - viewActivator.Activate(this, context); + ViewData = context.ViewData as ViewDataDictionary; + if (ViewData == null) + { + if (context.ViewData != null) + { + ViewData = new ViewDataDictionary(context.ViewData); + } + else + { + var metadataProvider = context.HttpContext.RequestServices.GetService(); + ViewData = new ViewDataDictionary(metadataProvider); + } + + // Have new ViewDataDictionary; make sure it's visible everywhere. + context.ViewData = ViewData; + } + + InitHelpers(context); return base.RenderAsync(context); } + + private void InitHelpers(ViewContext context) + { + Html = context.HttpContext.RequestServices.GetService>(); + + var contextable = Html as ICanHasViewContext; + if (contextable != null) + { + contextable.Contextualize(context); + } + } } } diff --git a/src/Microsoft.AspNet.Mvc.Razor/Resources.resx b/src/Microsoft.AspNet.Mvc.Razor/Resources.resx index 4004db0c14..df7106bffa 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.Razor/Resources.resx @@ -150,9 +150,6 @@ The following sections have been defined but have not been rendered: '{0}'. - - View of type '{0}' cannot be instatiated by '{1}'. - View '{0}' must have extension '{1}' when the view represents a full path. diff --git a/src/Microsoft.AspNet.Mvc/MvcServices.cs b/src/Microsoft.AspNet.Mvc/MvcServices.cs index 966a937df1..a61f9c31b1 100644 --- a/src/Microsoft.AspNet.Mvc/MvcServices.cs +++ b/src/Microsoft.AspNet.Mvc/MvcServices.cs @@ -43,7 +43,6 @@ namespace Microsoft.AspNet.Mvc yield return describe.Scoped(); yield return describe.Transient(); yield return describe.Transient(); - yield return describe.Singleton(); yield return describe.Transient, ReflectedActionDescriptorProvider>(); diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/InjectChunkVisitorTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/InjectChunkVisitorTest.cs index 718069b57c..62a9f76623 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/InjectChunkVisitorTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/InjectChunkVisitorTest.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Razor var writer = new CSharpCodeWriter(); var context = CreateContext(); - var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute"); + var visitor = new InjectChunkVisitor(writer, context); // Act visitor.Accept(new Chunk[] @@ -41,15 +41,13 @@ namespace Microsoft.AspNet.Mvc.Razor { // Arrange var expected = -@"[ActivateAttribute] -public MyType1 MyPropertyName1 { get; private set; } -[ActivateAttribute] +@"public MyType1 MyPropertyName1 { get; private set; } public MyType2 @MyPropertyName2 { get; private set; } "; var writer = new CSharpCodeWriter(); var context = CreateContext(); - var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute"); + var visitor = new InjectChunkVisitor(writer, context); var factory = SpanFactory.CreateCsHtml(); var node = (Span)factory.Code("Some code") .As(new InjectParameterGenerator("MyType", "MyPropertyName")); @@ -71,15 +69,13 @@ public MyType2 @MyPropertyName2 { get; private set; } public void Visit_WithDesignTimeHost_GeneratesPropertiesAndLinePragmas_ForInjectChunks() { // Arrange - var expected = @"[Microsoft.AspNet.Mvc.ActivateAttribute] -public + var expected = @"public #line 1 """" MyType1 MyPropertyName1 #line default #line hidden { get; private set; } -[Microsoft.AspNet.Mvc.ActivateAttribute] public #line 1 """" MyType2 @MyPropertyName2 @@ -92,7 +88,7 @@ MyType2 @MyPropertyName2 var context = CreateContext(); context.Host.DesignTimeMode = true; - var visitor = new InjectChunkVisitor(writer, context, "Microsoft.AspNet.Mvc.ActivateAttribute"); + var visitor = new InjectChunkVisitor(writer, context); var factory = SpanFactory.CreateCsHtml(); var node = (Span)factory.Code("Some code") .As(new InjectParameterGenerator("MyType", "MyPropertyName")); @@ -125,40 +121,7 @@ MyType2 @MyPropertyName2 var expectedLineMappings = new List { BuildLineMapping(1, 0, 1, 32, 3, 0, 17), - BuildLineMapping(28, 1, 8, 573, 26, 8, 20) - }; - - // Act - GeneratorResults results; - using (var buffer = new StringTextBuffer(source)) - { - results = engine.GenerateCode(buffer); - } - - // Assert - Assert.True(results.Success); - Assert.Equal(expectedCode, results.GeneratedCode); - Assert.Empty(results.ParserErrors); - Assert.Equal(expectedLineMappings, results.DesignTimeLineMappings); - } - - [Fact] - public void InjectVisitorWithModel_GeneratesCorrectLineMappings() - { - // Arrange - var host = new MvcRazorHost("RazorView") - { - DesignTimeMode = true - }; - host.NamespaceImports.Clear(); - var engine = new RazorTemplateEngine(host); - var source = ReadResource("TestFiles/Input/InjectWithModel.cshtml"); - var expectedCode = ReadResource("TestFiles/Output/InjectWithModel.cs"); - var expectedLineMappings = new List - { - BuildLineMapping(7, 0, 7, 126, 6, 7, 7), - BuildLineMapping(24, 1, 8, 562, 26, 8, 20), - BuildLineMapping(54, 2, 8, 732, 34, 8, 22) + BuildLineMapping(28, 1, 8, 442, 21, 8, 20) }; // Act diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/Microsoft.AspNet.Mvc.Razor.Host.Test.kproj b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/Microsoft.AspNet.Mvc.Razor.Host.Test.kproj index f2dc6d012b..9b048f99ba 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/Microsoft.AspNet.Mvc.Razor.Host.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/Microsoft.AspNet.Mvc.Razor.Host.Test.kproj @@ -37,8 +37,6 @@ - - diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/InjectWithModel.cshtml b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/InjectWithModel.cshtml deleted file mode 100644 index b4d4a5589a..0000000000 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/InjectWithModel.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@model MyModel -@inject MyApp MyPropertyName -@inject MyService Html \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs index 143623cb75..27799209ba 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs @@ -17,11 +17,6 @@ using MyNamespace #pragma warning restore 219 } #line hidden - public __CompiledTemplate() - { - } - #line hidden - [Microsoft.AspNet.Mvc.ActivateAttribute] public #line 2 "" MyApp MyPropertyName @@ -29,10 +24,12 @@ using MyNamespace #line default #line hidden { get; private set; } - [Microsoft.AspNet.Mvc.ActivateAttribute] - public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper Html { get; private set; } #line hidden + public __CompiledTemplate(MyApp MyPropertyName) + { + this.MyPropertyName = MyPropertyName; + } #pragma warning disable 1998 public override async Task ExecuteAsync() diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs deleted file mode 100644 index e1dc486e03..0000000000 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Razor -{ - using System.Threading.Tasks; - - public class __CompiledTemplate : RazorView< -#line 1 "" - MyModel - -#line default -#line hidden - > - { - private static object @__o; - private void @__RazorDesignTimeHelpers__() - { - #pragma warning disable 219 - #pragma warning restore 219 - } - #line hidden - public __CompiledTemplate() - { - } - #line hidden - [Microsoft.AspNet.Mvc.ActivateAttribute] - public -#line 2 "" - MyApp MyPropertyName - -#line default -#line hidden - { get; private set; } - [Microsoft.AspNet.Mvc.ActivateAttribute] - public -#line 3 "" - MyService Html - -#line default -#line hidden - { get; private set; } - - #line hidden - - #pragma warning disable 1998 - public override async Task ExecuteAsync() - { - } - #pragma warning restore 1998 - } -} diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs index dde6811d13..73f1cdc53b 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs @@ -16,15 +16,12 @@ #pragma warning disable 219 #pragma warning restore 219 } + #line hidden + #line hidden public __CompiledTemplate() { } - #line hidden - [Microsoft.AspNet.Mvc.ActivateAttribute] - public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper Html { get; private set; } - - #line hidden #pragma warning disable 1998 public override async Task ExecuteAsync() diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj b/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj index 4bafa70d9c..449bf94258 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/Microsoft.AspNet.Mvc.Razor.Test.kproj @@ -23,10 +23,9 @@ - - \ No newline at end of file + diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewActivatorTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewActivatorTest.cs deleted file mode 100644 index ae07a97302..0000000000 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewActivatorTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -// 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.IO; -using System.Threading.Tasks; -using Microsoft.AspNet.Http; -using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.AspNet.Mvc.Rendering; -using Microsoft.AspNet.Routing; -using Moq; -using Xunit; - -namespace Microsoft.AspNet.Mvc.Razor -{ - public class RazorViewActivatorTest - { - [Fact] - public void Activate_ActivatesAndContextualizesPropertiesOnViews() - { - // Arrange - var activator = new RazorViewActivator(); - var instance = new TestView(); - - var myService = new MyService(); - var helper = Mock.Of>(); - var serviceProvider = new Mock(); - serviceProvider.Setup(p => p.GetService(typeof(MyService))) - .Returns(myService); - serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper))) - .Returns(helper); - var httpContext = new Mock(); - httpContext.SetupGet(c => c.RequestServices) - .Returns(serviceProvider.Object); - var routeContext = new RouteContext(httpContext.Object); - var actionContext = new ActionContext(routeContext, new ActionDescriptor()); - var viewContext = new ViewContext(actionContext, - instance, - new ViewDataDictionary(Mock.Of()), - TextWriter.Null); - // Act - activator.Activate(instance, viewContext); - - // Assert - Assert.Same(helper, instance.Html); - Assert.Same(myService, instance.MyService); - Assert.Same(viewContext, myService.ViewContext); - Assert.Null(instance.MyService2); - } - - private abstract class TestViewBase : RazorView - { - [Activate] - public MyService MyService { get; set; } - - public MyService MyService2 { get; set; } - } - - private class TestView : TestViewBase - { - [Activate] - internal IHtmlHelper Html { get; private set; } - - public override Task ExecuteAsync() - { - throw new NotImplementedException(); - } - } - - private class MyService : ICanHasViewContext - { - public ViewContext ViewContext { get; private set; } - - public void Contextualize(ViewContext viewContext) - { - ViewContext = viewContext; - } - } - } -} \ No newline at end of file