Allow @model specified in a page work with @inherits directive in

_ViewImports

Fixes #3144
This commit is contained in:
Pranav K 2015-09-22 17:07:09 -07:00
parent 80add92de8
commit 89f58aa49f
30 changed files with 211 additions and 360 deletions

View File

@ -12,7 +12,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
/// </summary>
public static class ChunkHelper
{
private const string TModelToken = "<TModel>";
/// <summary>
/// Token that is replaced by the model name in <c>@inherits</c> and <c>@inject</c>
/// chunks as part of <see cref="ChunkInheritanceUtility"/>.
/// </summary>
public static readonly string TModelToken = "<TModel>";
/// <summary>
/// Returns the <see cref="ModelChunk"/> used to determine the model name for the page generated

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives

View File

@ -5,20 +5,23 @@ using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// <see cref="Chunk"/> for an <c>@model</c> directive.
/// </summary>
public class ModelChunk : Chunk
{
/// <summary>
/// Represents the chunk for an @model statement.
/// Initializes a new instance of <see cref="ModelChunk"/>.
/// </summary>
/// <param name="baseType">The base type of the view.</param>
/// <param name="modelType">The type of the view's Model.</param>
public ModelChunk(string baseType, string modelType)
/// <param name="modelType">The type of the view's model.</param>
public ModelChunk(string modelType)
{
BaseType = baseType;
ModelType = modelType;
}
public string BaseType { get; private set; }
public string ModelType { get; private set; }
/// <summary>
/// Gets the type of the view's model.
/// </summary>
public string ModelType { get; }
}
}

View File

@ -10,36 +10,31 @@ namespace Microsoft.AspNet.Razor.Generator
{
public class ModelChunkGenerator : SpanChunkGenerator
{
public ModelChunkGenerator(string baseType, string modelType)
public ModelChunkGenerator(string modelType)
{
BaseType = baseType;
ModelType = modelType;
}
public string BaseType { get; private set; }
public string ModelType { get; private set; }
public string ModelType { get; }
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
{
var modelChunk = new ModelChunk(BaseType, ModelType);
var modelChunk = new ModelChunk(ModelType);
context.ChunkTreeBuilder.AddChunk(modelChunk, target, topLevel: true);
}
public override string ToString()
{
return BaseType + "<" + ModelType + ">";
}
public override string ToString() => ModelType;
public override bool Equals(object obj)
{
var other = obj as ModelChunkGenerator;
return other != null &&
string.Equals(ModelType, other.ModelType, StringComparison.Ordinal);
string.Equals(ModelType, other.ModelType, StringComparison.Ordinal);
}
public override int GetHashCode()
{
return ModelType.GetHashCode();
return StringComparer.Ordinal.GetHashCode(ModelType);
}
}
}

View File

@ -1,37 +0,0 @@
// 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 Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
namespace Microsoft.AspNet.Mvc.Razor
{
public class ModelChunkVisitor : MvcCSharpCodeVisitor
{
public ModelChunkVisitor(
CSharpCodeWriter writer,
CodeGeneratorContext context)
: base(writer, context)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
}
protected override void Visit(ModelChunk chunk)
{
var csharpVisitor = new CSharpCodeVisitor(Writer, Context);
Writer.Write(chunk.BaseType).Write("<");
csharpVisitor.CreateExpressionCodeMapping(chunk.ModelType, chunk);
Writer.Write(">");
}
}
}

View File

@ -31,10 +31,6 @@ namespace Microsoft.AspNet.Mvc.Razor
{
Visit((InjectChunk)chunk);
}
else if (chunk is ModelChunk)
{
Visit((ModelChunk)chunk);
}
else
{
base.Accept(chunk);
@ -42,6 +38,5 @@ namespace Microsoft.AspNet.Mvc.Razor
}
protected abstract void Visit(InjectChunk chunk);
protected abstract void Visit(ModelChunk chunk);
}
}

View File

@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
@ -47,8 +45,6 @@ namespace Microsoft.AspNet.Mvc.Razor
_injectAttribute = injectAttribute;
}
private string Model { get; set; }
protected override CSharpCodeVisitor CreateCSharpCodeVisitor(
CSharpCodeWriter writer,
CodeGeneratorContext context)
@ -71,32 +67,6 @@ namespace Microsoft.AspNet.Mvc.Razor
return csharpCodeVisitor;
}
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
{
// Grab the last model chunk so it gets intellisense.
var modelChunk = ChunkHelper.GetModelChunk(Context.ChunkTreeBuilder.ChunkTree);
Model = modelChunk != null ? modelChunk.ModelType : _defaultModel;
// If there were any model chunks then we need to modify the class declaration signature.
if (modelChunk != null)
{
writer.Write(string.Format(CultureInfo.InvariantCulture, "public class {0} : ", Context.ClassName));
var modelVisitor = new ModelChunkVisitor(writer, Context);
// This generates the base class signature
modelVisitor.Accept(modelChunk);
writer.WriteLine();
return new CSharpCodeWritingScope(writer);
}
else
{
return base.BuildClassDeclaration(writer);
}
}
protected override void BuildConstructor(CSharpCodeWriter writer)
{
if (writer == null)

View File

@ -27,9 +27,5 @@ namespace Microsoft.AspNet.Mvc.Razor
protected override void Visit(InjectChunk chunk)
{
}
protected override void Visit(ModelChunk chunk)
{
}
}
}

View File

@ -16,13 +16,11 @@ namespace Microsoft.AspNet.Mvc.Razor
{
private const string ModelKeyword = "model";
private const string InjectKeyword = "inject";
private readonly string _baseType;
private SourceLocation? _endInheritsLocation;
private bool _modelStatementFound;
public MvcRazorCodeParser(string baseType)
public MvcRazorCodeParser()
{
_baseType = baseType;
MapDirectives(ModelDirective, ModelKeyword);
MapDirectives(InjectDirective, InjectKeyword);
}
@ -120,9 +118,10 @@ namespace Microsoft.AspNet.Mvc.Razor
if (!hasTypeError && (EndOfFile || At(CSharpSymbolType.NewLine)))
{
// Add an error for the property name only if we successfully read the type name
Context.OnError(startLocation,
Resources.FormatMvcRazorCodeParser_InjectDirectivePropertyNameRequired(InjectKeyword),
keywordwithSingleWhitespaceLength + remainingWhitespaceLength + typeName.Length);
Context.OnError(
startLocation,
Resources.FormatMvcRazorCodeParser_InjectDirectivePropertyNameRequired(InjectKeyword),
keywordwithSingleWhitespaceLength + remainingWhitespaceLength + typeName.Length);
}
// Read until end of line. Span now contains 'MyApp.MyService MyServiceName'.
@ -135,8 +134,8 @@ namespace Microsoft.AspNet.Mvc.Razor
// Parse out 'MyServicePropertyName' from the Span.
var propertyName = Span.GetContent()
.Value
.Substring(typeName.Length);
.Value
.Substring(typeName.Length);
// ';' is optional
propertyName = RemoveWhitespaceAndTrailingSemicolons(propertyName);
@ -149,7 +148,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private SpanChunkGenerator CreateModelChunkGenerator(string model)
{
return new ModelChunkGenerator(_baseType, model);
return new ModelChunkGenerator(model);
}
// Internal for unit testing

View File

@ -42,11 +42,14 @@ namespace Microsoft.AspNet.Mvc.Razor
{
LookupText = "Microsoft.AspNet.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNet.Mvc.Razor"
},
new SetBaseTypeChunk
{
// Microsoft.Aspnet.Mvc.Razor.RazorPage<TModel>
TypeName = BaseType + ChunkHelper.TModelToken
}
};
// CodeGenerationContext.DefaultBaseClass is set to MyBaseType<dynamic>.
// This field holds the type name without the generic decoration (MyBaseType)
private readonly string _baseType;
private readonly IChunkTreeCache _chunkTreeCache;
private readonly RazorPathNormalizer _pathNormalizer;
private ChunkInheritanceUtility _chunkInheritanceUtility;
@ -56,10 +59,9 @@ namespace Microsoft.AspNet.Mvc.Razor
: base(new CSharpRazorCodeLanguage())
{
_pathNormalizer = pathNormalizer;
_baseType = BaseType;
_chunkTreeCache = chunkTreeCache;
DefaultBaseClass = BaseType + "<" + DefaultModel + ">";
DefaultBaseClass = BaseType + ChunkHelper.TModelToken;
DefaultNamespace = "Asp";
// Enable instrumentation by default to allow precompiled views to work with BrowserLink.
EnableInstrumentation = true;
@ -282,7 +284,7 @@ namespace Microsoft.AspNet.Mvc.Razor
throw new ArgumentNullException(nameof(incomingCodeParser));
}
return new MvcRazorCodeParser(_baseType);
return new MvcRazorCodeParser();
}
/// <inheritdoc />

View File

@ -42,5 +42,20 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
Assert.Equal(expected, body.Trim());
}
[Fact]
public async Task ViewAndViewComponentsReplaceTModelTokenFromInheritedBasePages()
{
// Arrange
var expected =
@"WriteLiteral says:<h1>Write says:BobWriteLiteral says:</h1>
Write says:WriteLiteral says:<strong>Write says:98052WriteLiteral says:</strong>";
// Act
var body = await Client.GetStringAsync("Directives/ViewReplacesTModelTokenFromInheritedBasePages");
// Assert
Assert.Equal(expected, body.Trim());
}
}
}

View File

@ -1,117 +0,0 @@
// 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 Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.AspNet.Razor;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Generator;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor
{
public class ModelChunkVisitorTest
{
[Fact]
public void Visit_IgnoresNonModelChunks()
{
// Arrange
var writer = new CSharpCodeWriter();
var context = CreateContext();
var visitor = new ModelChunkVisitor(writer, context);
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new CodeAttributeChunk()
});
var code = writer.GenerateCode();
// Assert
Assert.Empty(code);
}
[Fact]
public void Visit_GeneratesBaseClass_ForModelChunks()
{
// Arrange
var expected =
"MyBase<" + Environment.NewLine +
"#line 1 \"\"" + Environment.NewLine +
"My_Generic.After.Periods" + Environment.NewLine +
Environment.NewLine +
"#line default" + Environment.NewLine +
"#line hidden" + Environment.NewLine +
">";
var writer = new CSharpCodeWriter();
var context = CreateContext();
var visitor = new ModelChunkVisitor(writer, context);
var factory = SpanFactory.CreateCsHtml();
var node = (Span)factory.Code("Some code")
.As(new ModelChunkGenerator("MyBase", "MyGeneric"));
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new ModelChunk("MyBase", "My_Generic.After.Periods") { Association = node }
});
var code = writer.GenerateCode();
// Assert
Assert.Equal(expected, code);
}
[Fact]
public void Visit_WithDesignTimeHost_GeneratesBaseClass_ForModelChunks()
{
// Arrange
var expected =
"MyBase<" + Environment.NewLine +
"#line 1 \"\"" + Environment.NewLine +
"My_Generic.After.Periods" + Environment.NewLine +
Environment.NewLine +
"#line default" + Environment.NewLine +
"#line hidden" + Environment.NewLine +
">";
var writer = new CSharpCodeWriter();
var context = CreateContext();
context.Host.DesignTimeMode = true;
var visitor = new ModelChunkVisitor(writer, context);
var factory = SpanFactory.CreateCsHtml();
var node = (Span)factory.Code("Some code")
.As(new ModelChunkGenerator("MyType", "MyPropertyName"));
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new ModelChunk("MyBase", "My_Generic.After.Periods") { Association = node }
});
var code = writer.GenerateCode();
// Assert
Assert.Equal(expected, code);
}
private static CodeGeneratorContext CreateContext()
{
var fileProvider = new TestFileProvider();
return new CodeGeneratorContext(
new ChunkGeneratorContext(
new MvcRazorHost(new DefaultChunkTreeCache(fileProvider)),
"MyClass",
"MyNamespace",
string.Empty,
shouldGenerateLinePragmas: true),
new ErrorSink());
}
}
}

View File

@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code(" Foo")
.As(new ModelChunkGenerator("RazorView", "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -80,7 +80,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code(modelName + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", expectedModel))
.As(new ModelChunkGenerator(expectedModel))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.Markup("Bar")
.With(new MarkupChunkGenerator())
@ -112,7 +112,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code(" ")
.As(new ModelChunkGenerator("RazorView", string.Empty))
.As(new ModelChunkGenerator(string.Empty))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(),
};
@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString)
@ -151,7 +151,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Bar")
.As(new ModelChunkGenerator("RazorView", "Bar"))
.As(new ModelChunkGenerator("Bar"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString)
@ -245,7 +245,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo")
.As(new ModelChunkGenerator("RazorView", "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -543,11 +543,6 @@ namespace Microsoft.AspNet.Mvc.Razor
private sealed class TestMvcCSharpRazorCodeParser : MvcRazorCodeParser
{
public TestMvcCSharpRazorCodeParser()
: base("RazorView")
{
}
public bool HasDirective(string directive)
{
Action handler;

View File

@ -20,7 +20,6 @@ using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Testing;
using Microsoft.Framework.Internal;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor
@ -127,38 +126,38 @@ namespace Microsoft.AspNet.Mvc.Razor
{
DesignTimeMode = true
};
var expectedLineMappings = new List<LineMapping>
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 7,
documentLineIndex: 0,
documentCharacterIndex: 7,
generatedAbsoluteIndex: 444,
generatedLineIndex: 12,
generatedCharacterIndex: 7,
contentLength: 8),
BuildLineMapping(
documentAbsoluteIndex: 33,
documentLineIndex: 2,
documentCharacterIndex: 14,
generatedAbsoluteIndex: 823,
generatedLineIndex: 25,
generatedAbsoluteIndex: 718,
generatedLineIndex: 19,
generatedCharacterIndex: 14,
contentLength: 85),
BuildLineMapping(
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 0,
generatedAbsoluteIndex: 910,
generatedLineIndex: 25,
generatedCharacterIndex: 0,
contentLength: 46),
BuildLineMapping(
documentAbsoluteIndex: 139,
documentLineIndex: 4,
documentCharacterIndex: 17,
generatedAbsoluteIndex: 2313,
generatedLineIndex: 55,
generatedAbsoluteIndex: 2371,
generatedLineIndex: 54,
generatedCharacterIndex: 95,
contentLength: 3),
BuildLineMapping(
documentAbsoluteIndex: 166,
documentLineIndex: 5,
documentCharacterIndex: 18,
generatedAbsoluteIndex: 2626,
generatedLineIndex: 61,
generatedAbsoluteIndex: 2684,
generatedLineIndex: 60,
generatedCharacterIndex: 87,
contentLength: 5),
};
@ -198,20 +197,28 @@ namespace Microsoft.AspNet.Mvc.Razor
host.NamespaceImports.Clear();
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 0,
generatedAbsoluteIndex: 343,
generatedLineIndex: 11,
generatedCharacterIndex: 0,
contentLength: 45),
BuildLineMapping(
documentAbsoluteIndex: 13,
documentLineIndex: 0,
documentCharacterIndex: 13,
generatedAbsoluteIndex: 1269,
generatedLineIndex: 32,
generatedAbsoluteIndex: 1412,
generatedLineIndex: 37,
generatedCharacterIndex: 13,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 43,
documentLineIndex: 2,
documentCharacterIndex: 5,
generatedAbsoluteIndex: 1353,
generatedLineIndex: 37,
generatedAbsoluteIndex: 1496,
generatedLineIndex: 42,
generatedCharacterIndex: 6,
contentLength: 21),
};
@ -230,7 +237,7 @@ namespace Microsoft.AspNet.Mvc.Razor
DesignTimeMode = true
};
host.NamespaceImports.Clear();
var expectedLineMappings = new List<LineMapping>
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 1,
@ -240,12 +247,20 @@ namespace Microsoft.AspNet.Mvc.Razor
generatedLineIndex: 3,
generatedCharacterIndex: 0,
contentLength: 17),
BuildLineMapping(
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 0,
generatedAbsoluteIndex: 443,
generatedLineIndex: 17,
generatedCharacterIndex: 0,
contentLength: 45),
BuildLineMapping(
documentAbsoluteIndex: 28,
documentLineIndex: 1,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 706,
generatedLineIndex: 26,
generatedAbsoluteIndex: 850,
generatedLineIndex: 31,
generatedCharacterIndex: 8,
contentLength: 20),
};
@ -267,27 +282,27 @@ namespace Microsoft.AspNet.Mvc.Razor
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 7,
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 7,
generatedAbsoluteIndex: 214,
generatedLineIndex: 6,
generatedCharacterIndex: 7,
contentLength: 7),
documentCharacterIndex: 0,
generatedAbsoluteIndex: 363,
generatedLineIndex: 11,
generatedCharacterIndex: 0,
contentLength: 45),
BuildLineMapping(
documentAbsoluteIndex: 24,
documentLineIndex: 1,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 731,
generatedLineIndex: 26,
generatedAbsoluteIndex: 788,
generatedLineIndex: 25,
generatedCharacterIndex: 8,
contentLength: 20),
BuildLineMapping(
documentAbsoluteIndex: 54,
documentLineIndex: 2,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 957,
generatedLineIndex: 34,
generatedAbsoluteIndex: 1014,
generatedLineIndex: 33,
generatedCharacterIndex: 8,
contentLength: 23),
};
@ -309,43 +324,43 @@ namespace Microsoft.AspNet.Mvc.Razor
var expectedLineMappings = new[]
{
BuildLineMapping(
documentAbsoluteIndex: 7,
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 7,
generatedAbsoluteIndex: 222,
generatedLineIndex: 6,
generatedCharacterIndex: 7,
contentLength: 7),
documentCharacterIndex: 0,
generatedAbsoluteIndex: 371,
generatedLineIndex: 11,
generatedCharacterIndex: 0,
contentLength: 45),
BuildLineMapping(
documentAbsoluteIndex: 24,
documentLineIndex: 1,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 747,
generatedLineIndex: 26,
generatedAbsoluteIndex: 804,
generatedLineIndex: 25,
generatedCharacterIndex: 8,
contentLength: 20),
BuildLineMapping(
documentAbsoluteIndex: 58,
documentLineIndex: 2,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 977,
generatedLineIndex: 34,
generatedAbsoluteIndex: 1034,
generatedLineIndex: 33,
generatedCharacterIndex: 8,
contentLength: 23),
BuildLineMapping(
documentAbsoluteIndex: 93,
documentLineIndex: 3,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 1210,
generatedLineIndex: 42,
generatedAbsoluteIndex: 1267,
generatedLineIndex: 41,
generatedCharacterIndex: 8,
contentLength: 21),
BuildLineMapping(
documentAbsoluteIndex: 129,
documentLineIndex: 4,
documentCharacterIndex: 8,
generatedAbsoluteIndex: 1441,
generatedLineIndex: 50,
generatedAbsoluteIndex: 1498,
generatedLineIndex: 49,
generatedCharacterIndex: 8,
contentLength: 24),
};
@ -366,7 +381,14 @@ namespace Microsoft.AspNet.Mvc.Razor
host.NamespaceImports.Clear();
var expectedLineMappings = new[]
{
BuildLineMapping(7, 0, 7, 194, 6, 7, 30),
BuildLineMapping(
documentAbsoluteIndex: 0,
documentLineIndex: 0,
documentCharacterIndex: 0,
generatedAbsoluteIndex: 366,
generatedLineIndex: 11,
generatedCharacterIndex: 0,
contentLength: 68),
};
// Act and Assert

View File

@ -8,6 +8,11 @@ namespace Asp
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#line 1 "TestFiles/Input/Basic.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<dynamic> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -14,6 +14,11 @@ using MyNamespace
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#line 1 "TestFiles/Input/Inject.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<dynamic> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -2,18 +2,17 @@ namespace Asp
{
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_InjectWithModel_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/InjectWithModel.cshtml"
MyModel
#line default
#line hidden
>
public class ASPV_TestFiles_Input_InjectWithModel_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel>
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#line 1 "TestFiles/Input/InjectWithModel.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -2,18 +2,17 @@ namespace Asp
{
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_InjectWithSemicolon_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/InjectWithSemicolon.cshtml"
MyModel
#line default
#line hidden
>
public class ASPV_TestFiles_Input_InjectWithSemicolon_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel>
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#line 1 "TestFiles/Input/InjectWithSemicolon.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -2,18 +2,17 @@ namespace Asp
{
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_Model_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/Model.cshtml"
System.Collections.IEnumerable
#line default
#line hidden
>
public class ASPV_TestFiles_Input_Model_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<System.Collections.IEnumerable>
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#line 1 "TestFiles/Input/Model.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<System.Collections.IEnumerable> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -8,13 +8,7 @@ namespace Asp
using Microsoft.AspNet.Mvc.Rendering;
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_ModelExpressionTagHelper_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
DateTime
#line default
#line hidden
>
public class ASPV_TestFiles_Input_ModelExpressionTagHelper_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<DateTime>
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
@ -28,6 +22,11 @@ namespace Asp
#line default
#line hidden
;
#line 1 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
Microsoft.AspNet.Mvc.Razor.RazorPage<DateTime> __inheritsHelper = null;
#line default
#line hidden
#pragma warning restore 219
}
#line hidden

View File

@ -8,13 +8,7 @@ namespace Asp
using Microsoft.AspNet.Mvc.Rendering;
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_InjectWithModel_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/InjectWithModel.cshtml"
MyModel
#line default
#line hidden
>
public class ASPV_TestFiles_Input_InjectWithModel_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel>
{
#line hidden
public ASPV_TestFiles_Input_InjectWithModel_cshtml()

View File

@ -8,13 +8,7 @@ namespace Asp
using Microsoft.AspNet.Mvc.Rendering;
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_InjectWithSemicolon_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/InjectWithSemicolon.cshtml"
MyModel
#line default
#line hidden
>
public class ASPV_TestFiles_Input_InjectWithSemicolon_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<MyModel>
{
#line hidden
public ASPV_TestFiles_Input_InjectWithSemicolon_cshtml()

View File

@ -8,13 +8,7 @@ namespace Asp
using Microsoft.AspNet.Mvc.Rendering;
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_Model_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/Model.cshtml"
System.Collections.IEnumerable
#line default
#line hidden
>
public class ASPV_TestFiles_Input_Model_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<System.Collections.IEnumerable>
{
#line hidden
public ASPV_TestFiles_Input_Model_cshtml()

View File

@ -9,13 +9,7 @@ namespace Asp
using Microsoft.AspNet.Mvc.Rendering;
using System.Threading.Tasks;
public class ASPV_TestFiles_Input_ModelExpressionTagHelper_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<
#line 1 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
DateTime
#line default
#line hidden
>
public class ASPV_TestFiles_Input_ModelExpressionTagHelper_cshtml : Microsoft.AspNet.Mvc.Razor.RazorPage<DateTime>
{
#line hidden
#pragma warning disable 0414

View File

@ -16,8 +16,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
{
public class MvcRazorCodeParserTest
{
private const string DefaultBaseType = "Microsoft.AspNet.ViewPage";
[Fact]
public void Constructor_AddsModelKeyword()
{
@ -43,7 +41,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code(" Foo")
.As(new ModelChunkGenerator(DefaultBaseType, "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -67,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo?" + Environment.NewLine)
.As(new ModelChunkGenerator(DefaultBaseType, "Foo?"))
.As(new ModelChunkGenerator("Foo?"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.Markup("Bar")
.With(new MarkupChunkGenerator())
@ -92,7 +90,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo[[]][]" + Environment.NewLine)
.As(new ModelChunkGenerator(DefaultBaseType, "Foo[[]][]"))
.As(new ModelChunkGenerator("Foo[[]][]"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.Markup("Bar")
.With(new MarkupChunkGenerator())
@ -117,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("$rootnamespace$.MyModel")
.As(new ModelChunkGenerator(DefaultBaseType, "$rootnamespace$.MyModel"))
.As(new ModelChunkGenerator("$rootnamespace$.MyModel"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -142,7 +140,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code(" ")
.As(new ModelChunkGenerator(DefaultBaseType, string.Empty))
.As(new ModelChunkGenerator(string.Empty))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -174,7 +172,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator(DefaultBaseType, "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString)
@ -182,7 +180,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Bar")
.As(new ModelChunkGenerator(DefaultBaseType, "Bar"))
.As(new ModelChunkGenerator("Bar"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -219,7 +217,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator(DefaultBaseType, "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString)
@ -272,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None),
factory.Code("Foo")
.As(new ModelChunkGenerator(DefaultBaseType, "Foo"))
.As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml()
};
@ -314,12 +312,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host.Test
private sealed class TestMvcCSharpRazorCodeParser : MvcRazorCodeParser
{
public TestMvcCSharpRazorCodeParser(string baseType = DefaultBaseType)
: base(baseType)
{
}
public bool HasDirective(string directive)
{
Action handler;

View File

@ -0,0 +1,16 @@
// 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 Microsoft.AspNet.Mvc;
namespace RazorWebSite.Components
{
[ViewComponent(Name = "InheritingViewComponent")]
public class InheritingViewComponent : ViewComponent
{
public IViewComponentResult Invoke(Address address)
{
return View("/Views/InheritingInherits/_ViewComponent", address);
}
}
}

View File

@ -17,5 +17,19 @@ namespace RazorWebSite
return View("/Views/Directives/Scoped/ViewInheritsBasePageFromViewImports.cshtml",
new Person { Name = "Person2" });
}
public IActionResult ViewReplacesTModelTokenFromInheritedBasePages()
{
var model = new Person
{
Name = "Bob",
Address = new Address
{
ZipCode = "98052"
}
};
return View("/Views/InheritingInherits/Index", model);
}
}
}

View File

@ -0,0 +1,3 @@
@model Person
<h1>@Model.Name</h1>
@Component.Invoke("InheritingViewComponent", Model.Address)

View File

@ -0,0 +1,2 @@
@model Address
<strong>@Model.ZipCode</strong>

View File

@ -0,0 +1 @@
@inherits MyBasePage<TModel>