diff --git a/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProject.cs b/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProject.cs
index 52ddafebe3..d6e623c4f1 100644
--- a/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProject.cs
+++ b/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProject.cs
@@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(root));
}
-
+
Root = root.Replace('\\', '/').TrimEnd('/');
}
@@ -36,16 +36,24 @@ namespace Microsoft.AspNetCore.Razor.Language
.EnumerateFiles("*.cshtml", SearchOption.AllDirectories)
.Select(file =>
{
- var relativePath = file.FullName.Substring(absoluteBasePath.Length).Replace(Path.DirectorySeparatorChar, '/');
- return new FileSystemRazorProjectItem(basePath, relativePath, file);
+ var relativePhysicalPath = file.FullName.Substring(absoluteBasePath.Length + 1); // Include leading separator
+ var filePath = "/" + relativePhysicalPath.Replace(Path.DirectorySeparatorChar, '/');
+
+ return new FileSystemRazorProjectItem(basePath, filePath, relativePhysicalPath, file);
});
}
public override RazorProjectItem GetItem(string path)
{
+ var absoluteBasePath = NormalizeAndEnsureValidPath("/");
var absolutePath = NormalizeAndEnsureValidPath(path);
- return new FileSystemRazorProjectItem("/", path, new FileInfo(absolutePath));
+ var file = new FileInfo(absolutePath);
+
+ var relativePhysicalPath = file.FullName.Substring(absoluteBasePath.Length + 1); // Include leading separator
+ var filePath = "/" + relativePhysicalPath.Replace(Path.DirectorySeparatorChar, '/');
+
+ return new FileSystemRazorProjectItem("/", filePath, relativePhysicalPath, new FileInfo(absolutePath));
}
protected override string NormalizeAndEnsureValidPath(string path)
diff --git a/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProjectItem.cs b/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProjectItem.cs
index 96a45027c8..210670d06a 100644
--- a/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProjectItem.cs
+++ b/src/Microsoft.AspNetCore.Razor.Language/FileSystemRazorProjectItem.cs
@@ -11,12 +11,14 @@ namespace Microsoft.AspNetCore.Razor.Language
/// Initializes a new instance of .
///
/// The base path.
- /// The path.
+ /// The physical path of the base path.
+ /// The path.
/// The .
- public FileSystemRazorProjectItem(string basePath, string path, FileInfo file)
+ public FileSystemRazorProjectItem(string basePath, string filePath, string relativePhysicalPath, FileInfo file)
{
BasePath = basePath;
- FilePath = path;
+ FilePath = filePath;
+ RelativePhysicalPath = relativePhysicalPath;
File = file;
}
@@ -30,6 +32,8 @@ namespace Microsoft.AspNetCore.Razor.Language
public override string PhysicalPath => File.FullName;
+ public override string RelativePhysicalPath { get; }
+
public override Stream Read() => new FileStream(PhysicalPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorProjectItem.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorProjectItem.cs
index 67b0e04dfd..cadd00710c 100644
--- a/src/Microsoft.AspNetCore.Razor.Language/RazorProjectItem.cs
+++ b/src/Microsoft.AspNetCore.Razor.Language/RazorProjectItem.cs
@@ -1,6 +1,7 @@
// 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 System.Diagnostics;
using System.IO;
@@ -18,15 +19,23 @@ namespace Microsoft.AspNetCore.Razor.Language
public abstract string BasePath { get; }
///
- /// File path relative to .
+ /// File path relative to . This property uses the project path syntax,
+ /// using / as a path separator and does not follow the operating system's file system
+ /// conventions.
///
public abstract string FilePath { get; }
///
- /// The absolute path to the file, including the file name.
+ /// The absolute physical (file system) path to the file, including the file name.
///
public abstract string PhysicalPath { get; }
+ ///
+ /// The relative physical (file system) path to the file, including the file name. Relative to the
+ /// physical path of the .
+ ///
+ public virtual string RelativePhysicalPath => null;
+
///
/// Gets the file contents as readonly .
///
diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectItemTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectItemTest.cs
index 638d898e0d..a5193f45f9 100644
--- a/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectItemTest.cs
+++ b/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectItemTest.cs
@@ -20,14 +20,15 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileInfo = new FileInfo(Path.Combine(TestFolder, "Home.cshtml"));
// Act
- var projectItem = new FileSystemRazorProjectItem("/Views", "/Home.cshtml", fileInfo);
+ var projectItem = new FileSystemRazorProjectItem("/", "/Home.cshtml", "Home.cshtml", fileInfo);
// Assert
Assert.Equal("/Home.cshtml", projectItem.FilePath);
- Assert.Equal("/Views", projectItem.BasePath);
+ Assert.Equal("/", projectItem.BasePath);
Assert.True(projectItem.Exists);
Assert.Equal("Home.cshtml", projectItem.FileName);
Assert.Equal(fileInfo.FullName, projectItem.PhysicalPath);
+ Assert.Equal("Home.cshtml", projectItem.RelativePhysicalPath);
}
[Fact]
@@ -37,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileInfo = new FileInfo(Path.Combine(TestFolder, "Views", "FileDoesNotExist.cshtml"));
// Act
- var projectItem = new FileSystemRazorProjectItem("/Views", "/FileDoesNotExist.cshtml", fileInfo);
+ var projectItem = new FileSystemRazorProjectItem("/Views", "/FileDoesNotExist.cshtml", Path.Combine("Views", "FileDoesNotExist.cshtml"), fileInfo);
// Assert
Assert.False(projectItem.Exists);
@@ -48,7 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
// Arrange
var fileInfo = new FileInfo(Path.Combine(TestFolder, "Home.cshtml"));
- var projectItem = new FileSystemRazorProjectItem("/", "/Home.cshtml", fileInfo);
+ var projectItem = new FileSystemRazorProjectItem("/", "/Home.cshtml", "Home.cshtml", fileInfo);
// Act
var stream = projectItem.Read();
diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectTest.cs
index 98a22f4fc5..35f8b32117 100644
--- a/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectTest.cs
+++ b/test/Microsoft.AspNetCore.Razor.Language.Test/FileSystemRazorProjectTest.cs
@@ -73,24 +73,31 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileSystemProject = new FileSystemRazorProject(TestFolder);
// Act
- var files = fileSystemProject.EnumerateItems("/");
+ var items = fileSystemProject.EnumerateItems("/");
// Assert
- Assert.Collection(files.OrderBy(f => f.FilePath),
- file =>
+ Assert.Collection(items.OrderBy(f => f.FilePath),
+ item =>
{
- Assert.Equal("/Home.cshtml", file.FilePath);
- Assert.Equal("/", file.BasePath);
+ Assert.Equal("/Home.cshtml", item.FilePath);
+ Assert.Equal("/", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Home.cshtml"), item.PhysicalPath);
+ Assert.Equal("Home.cshtml", item.RelativePhysicalPath);
+
},
- file =>
+ item =>
{
- Assert.Equal("/Views/About/About.cshtml", file.FilePath);
- Assert.Equal("/", file.BasePath);
+ Assert.Equal("/Views/About/About.cshtml", item.FilePath);
+ Assert.Equal("/", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Views", "About", "About.cshtml"), item.PhysicalPath);
+ Assert.Equal(Path.Combine("Views", "About", "About.cshtml"), item.RelativePhysicalPath);
},
- file =>
+ item =>
{
- Assert.Equal("/Views/Home/Index.cshtml", file.FilePath);
- Assert.Equal("/", file.BasePath);
+ Assert.Equal("/Views/Home/Index.cshtml", item.FilePath);
+ Assert.Equal("/", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Views", "Home", "Index.cshtml"), item.PhysicalPath);
+ Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), item.RelativePhysicalPath);
});
}
@@ -101,19 +108,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileSystemProject = new FileSystemRazorProject(TestFolder);
// Act
- var files = fileSystemProject.EnumerateItems("/Views");
+ var items = fileSystemProject.EnumerateItems("/Views");
// Assert
- Assert.Collection(files.OrderBy(f => f.FilePath),
- file =>
+ Assert.Collection(items.OrderBy(f => f.FilePath),
+ item =>
{
- Assert.Equal("/About/About.cshtml", file.FilePath);
- Assert.Equal("/Views", file.BasePath);
+ Assert.Equal("/About/About.cshtml", item.FilePath);
+ Assert.Equal("/Views", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Views", "About", "About.cshtml"), item.PhysicalPath);
+ Assert.Equal(Path.Combine("About", "About.cshtml"), item.RelativePhysicalPath);
},
- file =>
+ item =>
{
- Assert.Equal("/Home/Index.cshtml", file.FilePath);
- Assert.Equal("/Views", file.BasePath);
+ Assert.Equal("/Home/Index.cshtml", item.FilePath);
+ Assert.Equal("/Views", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Views", "Home", "Index.cshtml"), item.PhysicalPath);
+ Assert.Equal(Path.Combine("Home", "Index.cshtml"), item.RelativePhysicalPath);
});
}
@@ -124,25 +135,28 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileSystemProject = new FileSystemRazorProject(TestFolder);
// Act
- var files = fileSystemProject.EnumerateItems("/Does-Not-Exist");
+ var items = fileSystemProject.EnumerateItems("/Does-Not-Exist");
// Assert
- Assert.Empty(files);
+ Assert.Empty(items);
}
[Fact]
public void GetItem_ReturnsFileFromDisk()
{
// Arrange
- var path = "/Views/About/About.cshtml";
+ var filePath = "/Views/About/About.cshtml";
var fileSystemProject = new FileSystemRazorProject(TestFolder);
// Act
- var file = fileSystemProject.GetItem(path);
+ var item = fileSystemProject.GetItem(filePath);
// Assert
- Assert.True(file.Exists);
- Assert.Equal(path, file.FilePath);
+ Assert.True(item.Exists);
+ Assert.Equal(filePath, item.FilePath);
+ Assert.Equal("/", item.BasePath);
+ Assert.Equal(Path.Combine(TestFolder, "Views", "About", "About.cshtml"), item.PhysicalPath);
+ Assert.Equal(Path.Combine("Views", "About", "About.cshtml"), item.RelativePhysicalPath);
}
[Fact]
@@ -153,10 +167,10 @@ namespace Microsoft.AspNetCore.Razor.Language
var fileSystemProject = new FileSystemRazorProject(TestFolder);
// Act
- var file = fileSystemProject.GetItem(path);
+ var item = fileSystemProject.GetItem(path);
// Assert
- Assert.False(file.Exists);
+ Assert.False(item.Exists);
}
private class TestFileSystemRazorProject : FileSystemRazorProject