// 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.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace Microsoft.AspNetCore.Mvc.Razor { /// /// Contains methods to locate _ViewStart.cshtml and _ViewImports.cshtml /// public static class ViewHierarchyUtility { private const string ViewStartFileName = "_ViewStart.cshtml"; /// /// File name of _ViewImports.cshtml file /// public static readonly string ViewImportsFileName = "_ViewImports.cshtml"; /// /// Gets the view start locations that are applicable to the specified path. /// /// The application relative path of the file to locate /// _ViewStarts for. /// A sequence of paths that represent potential view start locations. /// /// This method returns paths starting from the directory of and /// moves upwards until it hits the application root. /// e.g. /// /Views/Home/View.cshtml -> [ /Views/Home/_ViewStart.cshtml, /Views/_ViewStart.cshtml, /_ViewStart.cshtml ] /// public static IEnumerable GetViewStartLocations(string applicationRelativePath) { return GetHierarchicalPath(applicationRelativePath, ViewStartFileName); } /// /// Gets the locations for _ViewImportss that are applicable to the specified path. /// /// The application relative path of the file to locate /// _ViewImportss for. /// A sequence of paths that represent potential _ViewImports locations. /// /// This method returns paths starting from the directory of and /// moves upwards until it hits the application root. /// e.g. /// /Views/Home/View.cshtml -> [ /Views/Home/_ViewImports.cshtml, /Views/_ViewImports.cshtml, /// /_ViewImports.cshtml ] /// public static IEnumerable GetViewImportsLocations(string applicationRelativePath) { return GetHierarchicalPath(applicationRelativePath, ViewImportsFileName); } private static IEnumerable GetHierarchicalPath(string relativePath, string fileName) { if (string.IsNullOrEmpty(relativePath)) { return Enumerable.Empty(); } if (relativePath.StartsWith("~/", StringComparison.Ordinal)) { relativePath = relativePath.Substring(2); } if (relativePath.StartsWith("/", StringComparison.Ordinal)) { relativePath = relativePath.Substring(1); } if (string.Equals(Path.GetFileName(relativePath), fileName, StringComparison.OrdinalIgnoreCase)) { // If the specified path is for the file hierarchy being constructed, then the first file that applies // to it is in a parent directory. relativePath = Path.GetDirectoryName(relativePath); if (string.IsNullOrEmpty(relativePath)) { return Enumerable.Empty(); } } var builder = new StringBuilder(relativePath); builder.Replace('\\', '/'); if (builder.Length > 0 && builder[0] != '/') { builder.Insert(0, '/'); } var locations = new List(); for (var index = builder.Length - 1; index >= 0; index--) { if (builder[index] == '/') { builder.Length = index + 1; builder.Append(fileName); locations.Add(builder.ToString()); } } return locations; } } }