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> /// </summary>
public static class ChunkHelper 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> /// <summary>
/// Returns the <see cref="ModelChunk"/> used to determine the model name for the page generated /// 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives

View File

@ -5,20 +5,23 @@ using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
/// <summary>
/// <see cref="Chunk"/> for an <c>@model</c> directive.
/// </summary>
public class ModelChunk : Chunk public class ModelChunk : Chunk
{ {
/// <summary> /// <summary>
/// Represents the chunk for an @model statement. /// Initializes a new instance of <see cref="ModelChunk"/>.
/// </summary> /// </summary>
/// <param name="baseType">The base type of the view.</param> /// <param name="modelType">The type of the view's model.</param>
/// <param name="modelType">The type of the view's Model.</param> public ModelChunk(string modelType)
public ModelChunk(string baseType, string modelType)
{ {
BaseType = baseType;
ModelType = modelType; ModelType = modelType;
} }
public string BaseType { get; private set; } /// <summary>
public string ModelType { get; private set; } /// 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 class ModelChunkGenerator : SpanChunkGenerator
{ {
public ModelChunkGenerator(string baseType, string modelType) public ModelChunkGenerator(string modelType)
{ {
BaseType = baseType;
ModelType = modelType; ModelType = modelType;
} }
public string BaseType { get; private set; } public string ModelType { get; }
public string ModelType { get; private set; }
public override void GenerateChunk(Span target, ChunkGeneratorContext context) 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); context.ChunkTreeBuilder.AddChunk(modelChunk, target, topLevel: true);
} }
public override string ToString() public override string ToString() => ModelType;
{
return BaseType + "<" + ModelType + ">";
}
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
var other = obj as ModelChunkGenerator; var other = obj as ModelChunkGenerator;
return other != null && return other != null &&
string.Equals(ModelType, other.ModelType, StringComparison.Ordinal); string.Equals(ModelType, other.ModelType, StringComparison.Ordinal);
} }
public override int GetHashCode() 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); Visit((InjectChunk)chunk);
} }
else if (chunk is ModelChunk)
{
Visit((ModelChunk)chunk);
}
else else
{ {
base.Accept(chunk); base.Accept(chunk);
@ -42,6 +38,5 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
protected abstract void Visit(InjectChunk chunk); 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Globalization;
using Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.AspNet.Razor.CodeGenerators; using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors; using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
@ -47,8 +45,6 @@ namespace Microsoft.AspNet.Mvc.Razor
_injectAttribute = injectAttribute; _injectAttribute = injectAttribute;
} }
private string Model { get; set; }
protected override CSharpCodeVisitor CreateCSharpCodeVisitor( protected override CSharpCodeVisitor CreateCSharpCodeVisitor(
CSharpCodeWriter writer, CSharpCodeWriter writer,
CodeGeneratorContext context) CodeGeneratorContext context)
@ -71,32 +67,6 @@ namespace Microsoft.AspNet.Mvc.Razor
return csharpCodeVisitor; 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) protected override void BuildConstructor(CSharpCodeWriter writer)
{ {
if (writer == null) if (writer == null)

View File

@ -27,9 +27,5 @@ namespace Microsoft.AspNet.Mvc.Razor
protected override void Visit(InjectChunk chunk) 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 ModelKeyword = "model";
private const string InjectKeyword = "inject"; private const string InjectKeyword = "inject";
private readonly string _baseType;
private SourceLocation? _endInheritsLocation; private SourceLocation? _endInheritsLocation;
private bool _modelStatementFound; private bool _modelStatementFound;
public MvcRazorCodeParser(string baseType) public MvcRazorCodeParser()
{ {
_baseType = baseType;
MapDirectives(ModelDirective, ModelKeyword); MapDirectives(ModelDirective, ModelKeyword);
MapDirectives(InjectDirective, InjectKeyword); MapDirectives(InjectDirective, InjectKeyword);
} }
@ -120,9 +118,10 @@ namespace Microsoft.AspNet.Mvc.Razor
if (!hasTypeError && (EndOfFile || At(CSharpSymbolType.NewLine))) if (!hasTypeError && (EndOfFile || At(CSharpSymbolType.NewLine)))
{ {
// Add an error for the property name only if we successfully read the type name // Add an error for the property name only if we successfully read the type name
Context.OnError(startLocation, Context.OnError(
Resources.FormatMvcRazorCodeParser_InjectDirectivePropertyNameRequired(InjectKeyword), startLocation,
keywordwithSingleWhitespaceLength + remainingWhitespaceLength + typeName.Length); Resources.FormatMvcRazorCodeParser_InjectDirectivePropertyNameRequired(InjectKeyword),
keywordwithSingleWhitespaceLength + remainingWhitespaceLength + typeName.Length);
} }
// Read until end of line. Span now contains 'MyApp.MyService MyServiceName'. // 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. // Parse out 'MyServicePropertyName' from the Span.
var propertyName = Span.GetContent() var propertyName = Span.GetContent()
.Value .Value
.Substring(typeName.Length); .Substring(typeName.Length);
// ';' is optional // ';' is optional
propertyName = RemoveWhitespaceAndTrailingSemicolons(propertyName); propertyName = RemoveWhitespaceAndTrailingSemicolons(propertyName);
@ -149,7 +148,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private SpanChunkGenerator CreateModelChunkGenerator(string model) private SpanChunkGenerator CreateModelChunkGenerator(string model)
{ {
return new ModelChunkGenerator(_baseType, model); return new ModelChunkGenerator(model);
} }
// Internal for unit testing // 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" 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>. // 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 IChunkTreeCache _chunkTreeCache;
private readonly RazorPathNormalizer _pathNormalizer; private readonly RazorPathNormalizer _pathNormalizer;
private ChunkInheritanceUtility _chunkInheritanceUtility; private ChunkInheritanceUtility _chunkInheritanceUtility;
@ -56,10 +59,9 @@ namespace Microsoft.AspNet.Mvc.Razor
: base(new CSharpRazorCodeLanguage()) : base(new CSharpRazorCodeLanguage())
{ {
_pathNormalizer = pathNormalizer; _pathNormalizer = pathNormalizer;
_baseType = BaseType;
_chunkTreeCache = chunkTreeCache; _chunkTreeCache = chunkTreeCache;
DefaultBaseClass = BaseType + "<" + DefaultModel + ">"; DefaultBaseClass = BaseType + ChunkHelper.TModelToken;
DefaultNamespace = "Asp"; DefaultNamespace = "Asp";
// Enable instrumentation by default to allow precompiled views to work with BrowserLink. // Enable instrumentation by default to allow precompiled views to work with BrowserLink.
EnableInstrumentation = true; EnableInstrumentation = true;
@ -282,7 +284,7 @@ namespace Microsoft.AspNet.Mvc.Razor
throw new ArgumentNullException(nameof(incomingCodeParser)); throw new ArgumentNullException(nameof(incomingCodeParser));
} }
return new MvcRazorCodeParser(_baseType); return new MvcRazorCodeParser();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -42,5 +42,20 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert // Assert
Assert.Equal(expected, body.Trim()); 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 ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code(" Foo") factory.Code(" Foo")
.As(new ModelChunkGenerator("RazorView", "Foo")) .As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml() factory.EmptyHtml()
}; };
@ -80,7 +80,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code(modelName + Environment.NewLine) factory.Code(modelName + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", expectedModel)) .As(new ModelChunkGenerator(expectedModel))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.Markup("Bar") factory.Markup("Bar")
.With(new MarkupChunkGenerator()) .With(new MarkupChunkGenerator())
@ -112,7 +112,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code(" ") factory.Code(" ")
.As(new ModelChunkGenerator("RazorView", string.Empty)) .As(new ModelChunkGenerator(string.Empty))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(), factory.EmptyHtml(),
}; };
@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine) factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", "Foo")) .As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(), factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString) factory.CodeTransition(SyntaxConstants.TransitionString)
@ -151,7 +151,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code("Bar") factory.Code("Bar")
.As(new ModelChunkGenerator("RazorView", "Bar")) .As(new ModelChunkGenerator("Bar"))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml() factory.EmptyHtml()
}; };
@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code("Foo" + Environment.NewLine) factory.Code("Foo" + Environment.NewLine)
.As(new ModelChunkGenerator("RazorView", "Foo")) .As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml(), factory.EmptyHtml(),
factory.CodeTransition(SyntaxConstants.TransitionString) factory.CodeTransition(SyntaxConstants.TransitionString)
@ -245,7 +245,7 @@ namespace Microsoft.AspNet.Mvc.Razor
factory.MetaCode("model ") factory.MetaCode("model ")
.Accepts(AcceptedCharacters.None), .Accepts(AcceptedCharacters.None),
factory.Code("Foo") factory.Code("Foo")
.As(new ModelChunkGenerator("RazorView", "Foo")) .As(new ModelChunkGenerator("Foo"))
.Accepts(AcceptedCharacters.AnyExceptNewline), .Accepts(AcceptedCharacters.AnyExceptNewline),
factory.EmptyHtml() factory.EmptyHtml()
}; };
@ -543,11 +543,6 @@ namespace Microsoft.AspNet.Mvc.Razor
private sealed class TestMvcCSharpRazorCodeParser : MvcRazorCodeParser private sealed class TestMvcCSharpRazorCodeParser : MvcRazorCodeParser
{ {
public TestMvcCSharpRazorCodeParser()
: base("RazorView")
{
}
public bool HasDirective(string directive) public bool HasDirective(string directive)
{ {
Action handler; Action handler;

View File

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

View File

@ -8,6 +8,11 @@ namespace Asp
private void @__RazorDesignTimeHelpers__() private void @__RazorDesignTimeHelpers__()
{ {
#pragma warning disable 219 #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 #pragma warning restore 219
} }
#line hidden #line hidden

View File

@ -14,6 +14,11 @@ using MyNamespace
private void @__RazorDesignTimeHelpers__() private void @__RazorDesignTimeHelpers__()
{ {
#pragma warning disable 219 #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 #pragma warning restore 219
} }
#line hidden #line hidden

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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