Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
Watch _ViewImports outside the pages root for changes
Browse files Browse the repository at this point in the history
Fixes #6428
  • Loading branch information
pranavkm committed Jun 26, 2017
1 parent 03e555a commit efb65e3
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public ActionDescriptorCollectionProvider(

private IChangeToken GetCompositeChangeToken()
{
if (_actionDescriptorChangeProviders.Length == 1)
{
return _actionDescriptorChangeProviders[0].GetChangeToken();
}

var changeTokens = new IChangeToken[_actionDescriptorChangeProviders.Length];
for (var i = 0; i < _actionDescriptorChangeProviders.Length; i++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
Expand All @@ -14,11 +17,18 @@ public class PageActionDescriptorChangeProvider : IActionDescriptorChangeProvide
{
private readonly IFileProvider _fileProvider;
private readonly string _searchPattern;
private readonly string[] _additionalFilesToTrack;

public PageActionDescriptorChangeProvider(
RazorTemplateEngine templateEngine,
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
IOptions<RazorPagesOptions> razorPagesOptions)
{
if (templateEngine == null)
{
throw new ArgumentNullException(nameof(templateEngine));
}

if (fileProviderAccessor == null)
{
throw new ArgumentNullException(nameof(fileProviderAccessor));
Expand All @@ -30,9 +40,33 @@ public PageActionDescriptorChangeProvider(
}

_fileProvider = fileProviderAccessor.FileProvider;
_searchPattern = razorPagesOptions.Value.RootDirectory.TrimEnd('/') + "/**/*.cshtml";
var rootDirectory = razorPagesOptions.Value.RootDirectory;
Debug.Assert(!string.IsNullOrEmpty(rootDirectory));
rootDirectory = rootDirectory.TrimEnd('/');
var importFileAtPagesRoot = rootDirectory + "/" + templateEngine.Options.ImportsFileName;
_additionalFilesToTrack = templateEngine.GetImportItems(importFileAtPagesRoot)
.Select(item => item.Path)
.ToArray();

_searchPattern = rootDirectory + "/**/*.cshtml";
}

public IChangeToken GetChangeToken() => _fileProvider.Watch(_searchPattern);
public IChangeToken GetChangeToken()
{
var wildcardChangeToken = _fileProvider.Watch(_searchPattern);
if (_additionalFilesToTrack.Length == 0)
{
return wildcardChangeToken;
}

var changeTokens = new IChangeToken[_additionalFilesToTrack.Length + 1];
for (var i = 0; i < _additionalFilesToTrack.Length; i++)
{
changeTokens[i] = _fileProvider.Watch(_additionalFilesToTrack[i]);
}

changeTokens[changeTokens.Length - 1] = wildcardChangeToken;
return new CompositeChangeToken(changeTokens);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// 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.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Moq;
using Xunit;

Expand All @@ -14,13 +17,16 @@ public class PageActionDescriptorChangeProviderTest
public void GetChangeToken_WatchesAllCshtmlFilesUnderFileSystemRoot()
{
// Arrange
var options = new TestOptionsManager<RazorPagesOptions>();
var fileProvider = new Mock<IFileProvider>();
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider.Object));
var options = new TestOptionsManager<RazorPagesOptions>();
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider.Object);
var changeProvider = new PageActionDescriptorChangeProvider(fileProviderAccessor.Object, options);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);

// Act
var changeToken = changeProvider.GetChangeToken();
Expand All @@ -35,20 +41,48 @@ public void GetChangeToken_WatchesAllCshtmlFilesUnderFileSystemRoot()
public void GetChangeToken_WatchesAllCshtmlFilesUnderSpecifiedRootDirectory(string rootDirectory)
{
// Arrange
var fileProvider = new Mock<IFileProvider>();
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider.Object));
var options = new TestOptionsManager<RazorPagesOptions>();
options.Value.RootDirectory = rootDirectory;
var fileProvider = new Mock<IFileProvider>();
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider.Object);
var changeProvider = new PageActionDescriptorChangeProvider(fileProviderAccessor.Object, options);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);

// Act
var changeToken = changeProvider.GetChangeToken();

// Assert
fileProvider.Verify(f => f.Watch("/pages-base-dir/**/*.cshtml"));
}

[Fact]
public void GetChangeToken_WatchesViewImportsOutsidePagesRoot()
{
// Arrange
var fileProvider = new TestFileProvider();
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider));
templateEngine.Options.ImportsFileName = "_ViewImports.cshtml";
var options = new TestOptionsManager<RazorPagesOptions>();
options.Value.RootDirectory = "/dir1/dir2";
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);

// Act & Assert
var compositeChangeToken = Assert.IsType<CompositeChangeToken>(changeProvider.GetChangeToken());
Assert.Collection(compositeChangeToken.ChangeTokens,
changeToken => Assert.Same(fileProvider.GetChangeToken("/dir1/_ViewImports.cshtml"), changeToken),
changeToken => Assert.Same(fileProvider.GetChangeToken("/_ViewImports.cshtml"), changeToken),
changeToken => Assert.Same(fileProvider.GetChangeToken("/dir1/dir2/**/*.cshtml"), changeToken));
}
}
}

0 comments on commit efb65e3

Please sign in to comment.