Add tests for PageActionInvokerProvider (#5882)

This commit is contained in:
Ryan Brandenburg 2017-03-09 16:19:20 -08:00 committed by GitHub
parent 7f3f6957be
commit 1c74e31715
7 changed files with 413 additions and 48 deletions

View File

@ -4,6 +4,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
public interface IPageLoader
{
Type Load(PageActionDescriptor actionDescriptor);
CompiledPageActionDescriptor Load(PageActionDescriptor actionDescriptor);
}
}

View File

@ -4,8 +4,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class DefaultPageLoader : IPageLoader
{
private const string ModelPropertyName = "Model";
private readonly RazorCompilationService _razorCompilationService;
private readonly ICompilationService _compilationService;
private readonly RazorProject _project;
@ -33,22 +34,20 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_logger = logger;
}
public Type Load(PageActionDescriptor actionDescriptor)
public CompiledPageActionDescriptor Load(PageActionDescriptor actionDescriptor)
{
var item = _project.GetItem(actionDescriptor.RelativePath);
if (!item.Exists)
{
throw new InvalidOperationException($"File {actionDescriptor.RelativePath} was not found.");
}
RazorCodeDocument codeDocument;
RazorCSharpDocument cSharpDocument;
_logger.RazorFileToCodeCompilationStart(item.Path);
var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;
codeDocument = CreateCodeDocument(item);
cSharpDocument = _razorCompilationService.ProcessCodeDocument(codeDocument);
var codeDocument = CreateCodeDocument(item);
var cSharpDocument = _razorCompilationService.ProcessCodeDocument(codeDocument);
_logger.RazorFileToCodeCompilationEnd(item.Path, startTimestamp);
@ -63,7 +62,21 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
}
compilationResult.EnsureSuccessful();
return compilationResult.CompiledType;
// If a model type wasn't set in code then the model property's type will be the same
// as the compiled type.
var pageType = compilationResult.CompiledType.GetTypeInfo();
var modelType = pageType.GetProperty(ModelPropertyName)?.PropertyType.GetTypeInfo();
if (modelType == pageType)
{
modelType = null;
}
return new CompiledPageActionDescriptor(actionDescriptor)
{
ModelTypeInfo = modelType,
PageTypeInfo = pageType,
};
}
private RazorCodeDocument CreateCodeDocument(RazorProjectItem item)

View File

@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageActionInvokerProvider : IActionInvokerProvider
{
private static readonly string[] _handlerMethodNames = new string[] { "OnGet", "OnPost" };
private const string PageStartFileName = "_PageStart.cshtml";
private const string ModelPropertyName = "Model";
private readonly IPageLoader _loader;
private readonly IPageFactoryProvider _pageFactoryProvider;
private readonly IPageModelFactoryProvider _modelFactoryProvider;
@ -166,34 +166,20 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
FilterItem[] cachedFilters)
{
var actionDescriptor = (PageActionDescriptor)context.ActionContext.ActionDescriptor;
var compiledType = _loader.Load(actionDescriptor).GetTypeInfo();
// If a model type wasn't set in code then the model property's type will be the same
// as the compiled type.
var modelType = compiledType.GetProperty(ModelPropertyName)?.PropertyType.GetTypeInfo();
if (modelType == compiledType)
{
modelType = null;
}
var compiledActionDescriptor = new CompiledPageActionDescriptor(actionDescriptor)
{
ModelTypeInfo = modelType,
PageTypeInfo = compiledType,
};
var compiledActionDescriptor = _loader.Load(actionDescriptor);
var pageFactory = _pageFactoryProvider.CreatePageFactory(compiledActionDescriptor);
var pageDisposer = _pageFactoryProvider.CreatePageDisposer(compiledActionDescriptor);
Func<PageContext, object> modelFactory = null;
Action<PageContext, object> modelReleaser = null;
if (modelType == null)
if (compiledActionDescriptor.ModelTypeInfo == null)
{
PopulateHandlerMethodDescriptors(compiledType, compiledActionDescriptor);
PopulateHandlerMethodDescriptors(compiledActionDescriptor.PageTypeInfo, compiledActionDescriptor);
}
else
{
PopulateHandlerMethodDescriptors(modelType, compiledActionDescriptor);
PopulateHandlerMethodDescriptors(compiledActionDescriptor.ModelTypeInfo, compiledActionDescriptor);
modelFactory = _modelFactoryProvider.CreateModelFactory(compiledActionDescriptor);
modelReleaser = _modelFactoryProvider.CreateModelDisposer(compiledActionDescriptor);
@ -211,30 +197,34 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
cachedFilters);
}
private List<Func<IRazorPage>> GetPageStartFactories(CompiledPageActionDescriptor descriptor)
// Internal for testing.
internal List<Func<IRazorPage>> GetPageStartFactories(CompiledPageActionDescriptor descriptor)
{
var pageStartFactories = new List<Func<IRazorPage>>();
var pageStartItems = _razorProject.FindHierarchicalItems(descriptor.ViewEnginePath, PageStartFileName);
foreach (var item in pageStartItems)
{
var factoryResult = _razorPageFactoryProvider.CreateFactory(item.Path);
if (factoryResult.Success)
if(item.Exists)
{
pageStartFactories.Insert(0, factoryResult.RazorPageFactory);
var factoryResult = _razorPageFactoryProvider.CreateFactory(item.Path);
if (factoryResult.Success)
{
pageStartFactories.Insert(0, factoryResult.RazorPageFactory);
}
}
}
return pageStartFactories;
}
private static void PopulateHandlerMethodDescriptors(TypeInfo type, CompiledPageActionDescriptor actionDescriptor)
// Internal for testing.
internal static void PopulateHandlerMethodDescriptors(TypeInfo type, CompiledPageActionDescriptor actionDescriptor)
{
var methods = type.GetMethods();
for (var i = 0; i < methods.Length; i++)
for (var i = 0; i < _handlerMethodNames.Length; i++)
{
var method = methods[i];
if (method.Name.StartsWith("OnGet", StringComparison.Ordinal) ||
method.Name.StartsWith("OnPost", StringComparison.Ordinal))
var methodName = _handlerMethodNames[i];
var method = type.GetMethod(methodName);
if (method != null && !method.IsGenericMethod)
{
actionDescriptor.HandlerMethods.Add(new HandlerMethodDescriptor()
{
@ -245,7 +235,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
}
}
private class InnerCache
internal class InnerCache
{
public InnerCache(int version)
{

View File

@ -95,6 +95,31 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal("Hello, handler!", content.Trim());
}
[Fact]
public async Task HelloWorldWithPageModelHandler_CanPostContent()
{
// Arrange
var getRequest = new HttpRequestMessage(HttpMethod.Get, "http://localhost/HelloWorldWithPageModelHandler?message=message");
var getResponse = await Client.SendAsync(getRequest);
var getResponseBody = await getResponse.Content.ReadAsStringAsync();
var formToken = AntiforgeryTestHelper.RetrieveAntiforgeryToken(getResponseBody, "/HelloWorlWithPageModelHandler");
var cookie = AntiforgeryTestHelper.RetrieveAntiforgeryCookie(getResponse);
var postRequest = new HttpRequestMessage(HttpMethod.Post, "http://localhost/HelloWorldWithPageModelHandler");
postRequest.Headers.Add("Cookie", cookie.Key + "=" + cookie.Value);
postRequest.Headers.Add("RequestVerificationToken", formToken);
// Act
var response = await Client.SendAsync(postRequest);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
Assert.StartsWith("Hello, You posted!", content.Trim());
}
[Fact]
public async Task HelloWorldWithPageModelHandler_CanGetContent()
{
@ -108,7 +133,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello, pagemodel!", content.Trim());
Assert.StartsWith("Hello, pagemodel!", content.Trim());
}
[Fact]

View File

@ -2,7 +2,9 @@
// 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.Diagnostics;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
@ -14,6 +16,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Primitives;
using Moq;
@ -37,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(object));
.Returns(CreateCompiledPageActionDescriptor(descriptor));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
@ -69,6 +72,61 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Assert.Null(entry.ReleaseModel);
}
[Fact]
public void OnProvidersExecuting_SetsHandlers()
{
// Arrange
var descriptor = new PageActionDescriptor
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
};
Func<PageContext, object> factory = _ => null;
Action<PageContext, object> releaser = (_, __) => { };
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestSetPageWithModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
var pageFactoryProvider = new Mock<IPageFactoryProvider>();
pageFactoryProvider.Setup(f => f.CreatePageFactory(It.IsAny<CompiledPageActionDescriptor>()))
.Returns(factory);
pageFactoryProvider.Setup(f => f.CreatePageDisposer(It.IsAny<CompiledPageActionDescriptor>()))
.Returns(releaser);
var modelFactoryProvider = new Mock<IPageModelFactoryProvider>();
var invokerProvider = CreateInvokerProvider(
loader.Object,
actionDescriptorProvider.Object,
pageFactoryProvider.Object,
modelFactoryProvider.Object);
var context = new ActionInvokerProviderContext(
new ActionContext(new DefaultHttpContext(), new RouteData(), descriptor));
// Act
invokerProvider.OnProvidersExecuting(context);
// Assert
Assert.NotNull(context.Result);
var actionInvoker = Assert.IsType<PageActionInvoker>(context.Result);
var entry = actionInvoker.CacheEntry;
Assert.Collection(entry.ActionDescriptor.HandlerMethods,
handlerDescriptor =>
{
Assert.Equal(nameof(TestSetPageModel.OnGet), handlerDescriptor.Method.Name);
Assert.NotNull(handlerDescriptor.Executor);
},
handlerDescriptor =>
{
Assert.Equal(nameof(TestSetPageModel.OnPost), handlerDescriptor.Method.Name);
Assert.NotNull(handlerDescriptor.Executor);
});
}
[Fact]
public void OnProvidersExecuting_WithModel_PopulatesCacheEntry()
{
@ -85,7 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(PageWithModel));
.Returns(CreateCompiledPageActionDescriptor(descriptor, pageType: typeof(PageWithModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
@ -137,7 +195,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(PageWithModel));
.Returns(CreateCompiledPageActionDescriptor(descriptor, pageType: typeof(PageWithModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
@ -184,7 +242,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(PageWithModel));
.Returns(CreateCompiledPageActionDescriptor(descriptor, pageType: typeof(PageWithModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
@ -215,7 +273,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
});
}
[Fact]
public void OnProvidersExecuting_CachesEntries()
{
@ -227,7 +284,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
};
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(object));
.Returns(CreateCompiledPageActionDescriptor(descriptor));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
@ -274,7 +331,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(object));
.Returns(CreateCompiledPageActionDescriptor(descriptor));
var invokerProvider = CreateInvokerProvider(
loader.Object,
actionDescriptorProvider.Object);
@ -299,6 +356,229 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Assert.NotSame(entry1, entry2);
}
[Fact]
public void PopulateHandlerMethodDescriptors_DiscoversHandlersFromBaseType()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var actionDescriptor = CreateCompiledPageActionDescriptor(descriptor, typeof(InheritsMethods));
var type = actionDescriptor.ModelTypeInfo ?? actionDescriptor.PageTypeInfo;
// Act
PageActionInvokerProvider.PopulateHandlerMethodDescriptors(type, actionDescriptor);
// Assert
Assert.Collection(actionDescriptor.HandlerMethods,
(handler) =>
{
Assert.Equal("OnGet", handler.Method.Name);
Assert.Equal(typeof(InheritsMethods), handler.Method.DeclaringType);
},
(handler) =>
{
Assert.Equal("OnPost", handler.Method.Name);
Assert.Equal(typeof(TestSetPageModel), handler.Method.DeclaringType);
});
}
[Fact]
public void PopulateHandlerMethodDescriptors_ProtectedMethodsNotFound()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var actionDescriptor = CreateCompiledPageActionDescriptor(descriptor, typeof(ProtectedModel));
var type = actionDescriptor.ModelTypeInfo ?? actionDescriptor.PageTypeInfo;
// Act
PageActionInvokerProvider.PopulateHandlerMethodDescriptors(type, actionDescriptor);
// Assert
Assert.Empty(actionDescriptor.HandlerMethods);
}
[Fact]
public void PopulateHandlerMethodDescriptors_IgnoreGenericTypeParameters()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var actionDescriptor = CreateCompiledPageActionDescriptor(descriptor, typeof(GenericClassModel));
var type = actionDescriptor.ModelTypeInfo ?? actionDescriptor.PageTypeInfo;
// Act
PageActionInvokerProvider.PopulateHandlerMethodDescriptors(type, actionDescriptor);
// Assert
Assert.Empty(actionDescriptor.HandlerMethods);
}
[Fact]
public void PopulateHandlerMethodDescriptors_AllowOnlyOneMethod()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var actionDescriptor = CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel));
var type = actionDescriptor.ModelTypeInfo ?? actionDescriptor.PageTypeInfo;
// Act
PageActionInvokerProvider.PopulateHandlerMethodDescriptors(type, actionDescriptor);
// Assert
var handler = Assert.Single(actionDescriptor.HandlerMethods);
Assert.Equal("OnGet", handler.Method.Name);
}
[Fact]
public void GetPageStartFactories_FindsFullHeirarchy()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
var fileProvider = new TestFileProvider();
fileProvider.AddFile("/View/Deeper/Not_PageStart.cshtml", "page content");
fileProvider.AddFile("/View/Wrong/_PageStart.cshtml", "page content");
fileProvider.AddFile("/_PageStart.cshtml", "page content ");
fileProvider.AddFile("/Views/_PageStart.cshtml", "@page starts!");
fileProvider.AddFile("/Views/Deeper/_PageStart.cshtml", "page content");
var razorProject = CreateRazorProject(fileProvider);
var mock = new Mock<IRazorPageFactoryProvider>();
mock.Setup(p => p.CreateFactory("/Views/Deeper/_PageStart.cshtml"))
.Returns(new RazorPageFactoryResult(() => null, new List<IChangeToken>()))
.Verifiable();
mock.Setup(p => p.CreateFactory("/Views/_PageStart.cshtml"))
.Returns(new RazorPageFactoryResult(() => null, new List<IChangeToken>()))
.Verifiable();
mock.Setup(p => p.CreateFactory("/_PageStart.cshtml"))
.Returns(new RazorPageFactoryResult(() => null, new List<IChangeToken>()))
.Verifiable();
var razorPageFactoryProvider = mock.Object;
var invokerProvider = CreateInvokerProvider(
loader.Object,
actionDescriptorProvider.Object,
pageProvider: null,
modelProvider: null,
razorPageFactoryProvider: razorPageFactoryProvider,
razorProject: razorProject);
var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);
// Act
var factories = invokerProvider.GetPageStartFactories(compiledDescriptor);
// Assert
mock.Verify();
}
[Fact]
public void GetPageStartFactories_NoFactoriesForMissingFiles()
{
// Arrange
var descriptor = new PageActionDescriptor()
{
RelativePath = "Path1",
FilterDescriptors = new FilterDescriptor[0],
ViewEnginePath = "/Views/Deeper/Index.cshtml"
};
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel)));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
// No files
var fileProvider = new TestFileProvider();
var razorProject = CreateRazorProject(fileProvider);
var invokerProvider = CreateInvokerProvider(
loader.Object,
actionDescriptorProvider.Object,
pageProvider: null,
modelProvider: null,
razorPageFactoryProvider: CreateRazorPageFactoryProvider(),
razorProject: razorProject);
var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);
// Act
var factories = invokerProvider.GetPageStartFactories(compiledDescriptor);
// Assert
Assert.Empty(factories);
}
private IRazorPageFactoryProvider CreateRazorPageFactoryProvider()
{
var mock = new Mock<IRazorPageFactoryProvider>();
mock.Setup(p => p.CreateFactory(It.IsAny<string>()))
.Returns(new RazorPageFactoryResult(() => null, new List<IChangeToken>()));
return mock.Object;
}
private RazorProject CreateRazorProject(IFileProvider fileProvider)
{
return new DefaultRazorProject(fileProvider);
}
private static CompiledPageActionDescriptor CreateCompiledPageActionDescriptor(
PageActionDescriptor descriptor,
Type pageType = null)
{
TypeInfo modelTypeInfo = null;
if (pageType != null)
{
modelTypeInfo = pageType.GetTypeInfo().GetProperty("Model")?.PropertyType.GetTypeInfo();
}
return new CompiledPageActionDescriptor(descriptor)
{
ModelTypeInfo = modelTypeInfo,
PageTypeInfo = (pageType ?? typeof(object)).GetTypeInfo()
};
}
private static PageActionInvokerProvider CreateInvokerProvider(
IPageLoader loader,
IActionDescriptorCollectionProvider actionDescriptorProvider,
@ -334,6 +614,53 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
NullLoggerFactory.Instance);
}
private class GenericClassModel
{
public void OnGet<T>()
{
}
}
private class TestSetPageWithModel
{
public TestSetPageModel Model { get; set; }
}
private class InheritsMethods : TestSetPageModel
{
public new void OnGet()
{
}
}
private class ProtectedModel
{
protected void OnGet()
{
}
private void OnPost()
{
}
}
private class TestSetPageModel
{
public void OnGet()
{
}
public void OnPost()
{
}
}
private class PageWithModel
{
public TestPageModel Model { get; set; }

View File

@ -13,5 +13,10 @@ namespace RazorPagesWebSite
{
Message = message;
}
public void OnPost()
{
Message = "You posted!";
}
}
}

View File

@ -1,4 +1,9 @@
@page
@model RazorPagesWebSite.HelloWorldWithPageModelHandler
Hello, @Model.Message!
Hello, @Model.Message!
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}