Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
namespace System.Web.WebPages.Deployment
{
internal static class AppDomainHelper
{
public static IDictionary<string, IEnumerable<string>> GetBinAssemblyReferences(string appPath, string configPath)
{
string binDirectory = Path.Combine(appPath, "bin");
if (!Directory.Exists(binDirectory))
{
return null;
}
AppDomain appDomain = null;
try
{
var appDomainSetup = new AppDomainSetup
{
ApplicationBase = appPath,
ConfigurationFile = configPath,
PrivateBinPath = binDirectory,
};
appDomain = AppDomain.CreateDomain(typeof(AppDomainHelper).Namespace, AppDomain.CurrentDomain.Evidence, appDomainSetup);
var type = typeof(RemoteAssemblyLoader);
var instance = (RemoteAssemblyLoader)appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
return Directory.EnumerateFiles(binDirectory, "*.dll")
.ToDictionary(assemblyPath => assemblyPath,
assemblyPath => instance.GetReferences(assemblyPath));
}
finally
{
if (appDomain != null)
{
AppDomain.Unload(appDomain);
}
}
}
private sealed class RemoteAssemblyLoader : MarshalByRefObject
{
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Method needs to be instance level for cross domain invocation"),
SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom",
Justification = "We want to load this specific assembly.")]
public IEnumerable<string> GetReferences(string assemblyPath)
{
var assembly = Assembly.LoadFrom(assemblyPath);
return assembly.GetReferencedAssemblies()
.Select(asmName => Assembly.Load(asmName.FullName).FullName)
.Concat(new[] { assembly.FullName })
.ToArray();
}
}
}
}

View File

@ -0,0 +1,184 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using Microsoft.Internal.Web.Utils;
using Microsoft.Web.Infrastructure;
namespace System.Web.WebPages.Deployment
{
internal static class AssemblyUtils
{
// Copied from AssemblyRefs.cs
private const string SharedLibPublicKey = "31bf3856ad364e35";
internal static readonly AssemblyName ThisAssemblyName = new AssemblyName(typeof(AssemblyUtils).Assembly.FullName);
private static readonly Version WebPagesV1Version = new Version(1, 0, 0, 0);
private static readonly string _binFileName = Path.GetFileName(ThisAssemblyName.Name) + ".dll";
// Special case MWI because it does not share the same assembly version as the rest of WebPages.
private static readonly Version _mwiVersion = new AssemblyName(typeof(InfrastructureHelper).Assembly.FullName).Version;
private static readonly AssemblyName _mwiAssemblyName = GetFullName("Microsoft.Web.Infrastructure", _mwiVersion);
private static readonly AssemblyName[] _version1AssemblyList = new[]
{
_mwiAssemblyName,
GetFullName("System.Web.Razor", WebPagesV1Version),
GetFullName("System.Web.Helpers", WebPagesV1Version),
GetFullName("System.Web.WebPages", WebPagesV1Version),
GetFullName("System.Web.WebPages.Administration", WebPagesV1Version),
GetFullName("System.Web.WebPages.Razor", WebPagesV1Version),
GetFullName("WebMatrix.Data", WebPagesV1Version),
GetFullName("WebMatrix.WebData", WebPagesV1Version)
};
private static readonly AssemblyName[] _versionCurrentAssemblyList = new[]
{
_mwiAssemblyName,
GetFullName("System.Web.Razor", ThisAssemblyName.Version),
GetFullName("System.Web.Helpers", ThisAssemblyName.Version),
GetFullName("System.Web.WebPages", ThisAssemblyName.Version),
GetFullName("System.Web.WebPages.Administration", ThisAssemblyName.Version),
GetFullName("System.Web.WebPages.Razor", ThisAssemblyName.Version),
GetFullName("WebMatrix.Data", ThisAssemblyName.Version),
GetFullName("WebMatrix.WebData", ThisAssemblyName.Version)
};
internal static Version GetMaxWebPagesVersion()
{
return GetMaxWebPagesVersion(GetLoadedAssemblies());
}
internal static Version GetMaxWebPagesVersion(IEnumerable<AssemblyName> loadedAssemblies)
{
return GetWebPagesAssemblies(loadedAssemblies).Max(c => c.Version);
}
internal static bool IsVersionAvailable(Version version)
{
return IsVersionAvailable(GetLoadedAssemblies(), version);
}
internal static bool IsVersionAvailable(IEnumerable<AssemblyName> loadedAssemblies, Version version)
{
return GetWebPagesAssemblies(loadedAssemblies).Any(c => c.Version == version);
}
private static IEnumerable<AssemblyName> GetWebPagesAssemblies(IEnumerable<AssemblyName> loadedAssemblies)
{
return (from otherName in loadedAssemblies
where NamesMatch(ThisAssemblyName, otherName, matchVersion: false)
select otherName);
}
/// <summary>
/// Returns the version of a System.Web.WebPages.Deployment.dll if it is present in the bin and matches the name and
/// public key token of the current assembly.
/// </summary>
/// <returns>Version from bin if present, null otherwise.</returns>
internal static Version GetVersionFromBin(string binDirectory, IFileSystem fileSystem, Func<string, AssemblyName> getAssemblyNameThunk = null)
{
// If a version of the assembly is present both in the bin and the GAC, the GAC would win.
// To work around this, we'll look for a physical file on disk with the same name as the current assembly and load it to determine the version.
// Determine if the Deployment assembly is present in the bin
var assemblyInBin = Path.Combine(binDirectory, _binFileName);
if (fileSystem.FileExists(assemblyInBin))
{
try
{
getAssemblyNameThunk = getAssemblyNameThunk ?? AssemblyName.GetAssemblyName;
AssemblyName assemblyName = getAssemblyNameThunk(assemblyInBin);
if (NamesMatch(ThisAssemblyName, assemblyName, matchVersion: false))
{
return assemblyName.Version;
}
}
catch (BadImageFormatException)
{
// Do nothing.
}
catch (SecurityException)
{
// Do nothing
}
catch (FileLoadException)
{
// Do nothing.
}
}
return null;
}
internal static bool NamesMatch(AssemblyName left, AssemblyName right, bool matchVersion)
{
return Equals(left.Name, right.Name) &&
Equals(left.CultureInfo, right.CultureInfo) &&
Enumerable.SequenceEqual(left.GetPublicKeyToken(), right.GetPublicKeyToken()) &&
(!matchVersion || Equals(left.Version, right.Version));
}
internal static IEnumerable<AssemblyName> GetLoadedAssemblies()
{
return AppDomain.CurrentDomain.GetAssemblies()
.Select(GetAssemblyName)
.ToList();
}
internal static IEnumerable<AssemblyName> GetAssembliesForVersion(Version version)
{
if (version == WebPagesV1Version)
{
return _version1AssemblyList;
}
return _versionCurrentAssemblyList;
}
private static AssemblyName GetAssemblyName(Assembly assembly)
{
return new AssemblyName(assembly.FullName);
}
private static AssemblyName GetFullName(string name, Version version, string publicKeyToken)
{
return new AssemblyName(String.Format(CultureInfo.InvariantCulture,
"{0}, Version={1}, Culture=neutral, PublicKeyToken={2}",
name, version, publicKeyToken));
}
internal static AssemblyName GetFullName(string name, Version version)
{
return GetFullName(name, version, SharedLibPublicKey);
}
public static IDictionary<string, Version> GetAssembliesMatchingOtherVersions(IDictionary<string, IEnumerable<string>> references)
{
var webPagesAssemblies = AssemblyUtils.GetAssembliesForVersion(AssemblyUtils.ThisAssemblyName.Version);
if (webPagesAssemblies == null || !webPagesAssemblies.Any())
{
return new Dictionary<string, Version>(0);
}
var matchingVersions = from item in references
let matchedVersion = GetMatchingVersion(webPagesAssemblies, item.Value)
where matchedVersion != null
select new KeyValuePair<string, Version>(item.Key, matchedVersion);
return matchingVersions.ToDictionary(k => k.Key, k => k.Value);
}
private static Version GetMatchingVersion(IEnumerable<AssemblyName> webPagesAssemblies, IEnumerable<string> references)
{
// Return assemblies that match in name but not in version.
var matchingVersions = from webPagesAssembly in webPagesAssemblies
from referenceName in references
let referencedAssembly = new AssemblyName(referenceName)
where AssemblyUtils.NamesMatch(webPagesAssembly, referencedAssembly, matchVersion: false) && webPagesAssembly.Version != referencedAssembly.Version
select referencedAssembly.Version;
return matchingVersions.FirstOrDefault();
}
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.IO;
using System.Web.Compilation;
namespace System.Web.WebPages.Deployment
{
internal sealed class BuildManagerWrapper : IBuildManager
{
/// <summary>
/// Reads a special cached file from %WindDir%\Microsoft.NET\Framework\vx.x\ASP.NET Temporary Files\&lt;x&gt;\&lt;y&gt;\UserCache that is
/// available across AppDomain recycles.
/// </summary>
public Stream ReadCachedFile(string path)
{
return BuildManager.ReadCachedFile(path);
}
/// <summary>
/// Creates or opens a special cached file that is created under %WindDir%\Microsoft.NET\Framework\vx.x\ASP.NET Temporary Files\&lt;x&gt;\&lt;y&gt;\UserCache that is
/// available across AppDomain recycles.
/// </summary>
public Stream CreateCachedFile(string path)
{
return BuildManager.CreateCachedFile(path);
}
}
}

View File

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
namespace Microsoft.Internal.Web.Utils
{
internal interface IFileSystem
{
bool FileExists(string path);
Stream ReadFile(string path);
Stream OpenFile(string path);
IEnumerable<string> EnumerateFiles(string root);
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
namespace Microsoft.Internal.Web.Utils
{
internal sealed class PhysicalFileSystem : IFileSystem
{
public bool FileExists(string path)
{
return File.Exists(path);
}
public Stream ReadFile(string path)
{
return File.OpenRead(path);
}
public Stream OpenFile(string path)
{
string directory = Path.GetDirectoryName(path);
EnsureDirectory(directory);
return File.OpenWrite(path);
}
public IEnumerable<string> EnumerateFiles(string path)
{
return Directory.EnumerateFiles(path);
}
private static void EnsureDirectory(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Web.WebPages.Deployment", Justification = "Namespace is present to match assembly name")]

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.IO;
namespace System.Web.WebPages.Deployment
{
internal interface IBuildManager
{
Stream CreateCachedFile(string fileName);
Stream ReadCachedFile(string fileName);
}
}

View File

@ -0,0 +1,274 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Web.Caching;
using System.Web.Compilation;
using System.Web.Configuration;
using System.Web.WebPages.Deployment.Resources;
using Microsoft.Internal.Web.Utils;
using Microsoft.Web.Infrastructure;
namespace System.Web.WebPages.Deployment
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static class PreApplicationStartCode
{
/// <summary>
/// Key used to indicate to tooling that the compile exception we throw to refresh the app domain originated from us so that they can deal with it correctly.
/// </summary>
private const string ToolingIndicatorKey = "WebPages.VersionChange";
// NOTE: Do not add public fields, methods, or other members to this class.
// This class does not show up in Intellisense so members on it will not be
// discoverable by users. Place new members on more appropriate classes that
// relate to the public API (for example, a LoginUrl property should go on a
// membership-related class).
private static readonly IFileSystem _physicalFileSystem = new PhysicalFileSystem();
private static bool _startWasCalled;
public static void Start()
{
// Even though ASP.NET will only call each PreAppStart once, we sometimes internally call one PreAppStart from
// another PreAppStart to ensure that things get initialized in the right order. ASP.NET does not guarantee the
// order so we have to guard against multiple calls.
// All Start calls are made on same thread, so no lock needed here.
if (_startWasCalled)
{
return;
}
_startWasCalled = true;
StartCore();
}
internal static bool StartCore()
{
var buildManager = new BuildManagerWrapper();
NameValueCollection appSettings = WebConfigurationManager.AppSettings;
Action<Version> loadWebPages = LoadWebPages;
Action registerForChangeNotification = RegisterForChangeNotifications;
IEnumerable<AssemblyName> loadedAssemblies = AssemblyUtils.GetLoadedAssemblies();
return StartCore(_physicalFileSystem, HttpRuntime.AppDomainAppPath, HttpRuntime.BinDirectory, appSettings, loadedAssemblies,
buildManager, loadWebPages, registerForChangeNotification);
}
// Adds Parameter for unit tests
internal static bool StartCore(IFileSystem fileSystem, string appDomainAppPath, string binDirectory, NameValueCollection appSettings, IEnumerable<AssemblyName> loadedAssemblies,
IBuildManager buildManager, Action<Version> loadWebPages, Action registerForChangeNotification, Func<string, AssemblyName> getAssemblyNameThunk = null)
{
if (WebPagesDeployment.IsExplicitlyDisabled(appSettings))
{
// If WebPages is explicitly disabled, exit.
Debug.WriteLine("WebPages Bootstrapper v{0}: not loading WebPages since it is disabled", AssemblyUtils.ThisAssemblyName.Version);
return false;
}
Version maxWebPagesVersion = AssemblyUtils.GetMaxWebPagesVersion(loadedAssemblies);
Debug.Assert(maxWebPagesVersion != null, "Function must return some max value.");
if (AssemblyUtils.ThisAssemblyName.Version != maxWebPagesVersion)
{
// Always let the highest version determine what needs to be done. This would make future proofing simpler.
Debug.WriteLine("WebPages Bootstrapper v{0}: Higher version v{1} is available.", AssemblyUtils.ThisAssemblyName.Version, maxWebPagesVersion);
return false;
}
var webPagesEnabled = WebPagesDeployment.IsEnabled(fileSystem, appDomainAppPath, appSettings);
Version binVersion = AssemblyUtils.GetVersionFromBin(binDirectory, fileSystem, getAssemblyNameThunk);
Version version = WebPagesDeployment.GetVersionInternal(appSettings, binVersion, defaultVersion: maxWebPagesVersion);
// Asserts to ensure unit tests are set up correctly. So essentially, we're unit testing the unit tests.
Debug.Assert(version != null, "GetVersion always returns a version");
Debug.Assert(binVersion == null || binVersion <= maxWebPagesVersion, "binVersion cannot be higher than max version");
if ((binVersion != null) && (binVersion != version))
{
// Determine if there's a version conflict. A conflict could occur if there's a version specified in the bin which is different from the version specified in the
// config that is different.
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ConfigurationResources.WebPagesVersionConflict, version, binVersion));
}
else if (binVersion != null)
{
// The rest of the code is only meant to be executed if we are executing from the GAC.
// If a version is bin deployed, we don't need to do anything special to bootstrap.
return false;
}
else if (!webPagesEnabled)
{
Debug.WriteLine("WebPages Bootstrapper v{0}: WebPages not enabled, registering for change notifications", AssemblyUtils.ThisAssemblyName.Version);
// Register for change notifications under the application root
registerForChangeNotification();
return false;
}
else if (!AssemblyUtils.IsVersionAvailable(loadedAssemblies, version))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ConfigurationResources.WebPagesVersionNotFound, version, AssemblyUtils.ThisAssemblyName.Version));
}
Debug.WriteLine("WebPages Bootstrapper v{0}: loading version {1}, loading WebPages", AssemblyUtils.ThisAssemblyName.Version, version);
// If the version the application was compiled earlier was different, invalidate compilation results by adding a file to the bin.
InvalidateCompilationResultsIfVersionChanged(buildManager, fileSystem, binDirectory, version);
loadWebPages(version);
return true;
}
/// <summary>
/// WebPages stores the version to be compiled against in AppSettings as &gt;add key="webpages:version" value="1.0" /&lt;.
/// Changing values AppSettings does not cause recompilation therefore we could run into a state where we have files compiled against v1 but the application is
/// currently v2.
/// </summary>
private static void InvalidateCompilationResultsIfVersionChanged(IBuildManager buildManager, IFileSystem fileSystem, string binDirectory, Version currentVersion)
{
Version previousVersion = WebPagesDeployment.GetPreviousRuntimeVersion(buildManager);
// Persist the current version number in BuildManager's cached file
WebPagesDeployment.PersistRuntimeVersion(buildManager, currentVersion);
if (previousVersion == null)
{
// Do nothing.
}
else if (previousVersion != currentVersion)
{
// If the previous runtime version is different, perturb the bin directory so that it forces recompilation.
WebPagesDeployment.ForceRecompile(fileSystem, binDirectory);
var httpCompileException = new HttpCompileException(ConfigurationResources.WebPagesVersionChanges);
// Indicator for tooling
httpCompileException.Data[ToolingIndicatorKey] = true;
throw httpCompileException;
}
}
// Copied from xsp\System\Web\Compilation\BuildManager.cs
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Copied from System.Web.dll")]
internal static ICollection<MethodInfo> GetPreStartInitMethodsFromAssemblyCollection(IEnumerable<Assembly> assemblies)
{
List<MethodInfo> methods = new List<MethodInfo>();
foreach (Assembly assembly in assemblies)
{
PreApplicationStartMethodAttribute[] attributes = null;
try
{
attributes = (PreApplicationStartMethodAttribute[])assembly.GetCustomAttributes(typeof(PreApplicationStartMethodAttribute), inherit: true);
}
catch
{
// GetCustomAttributes invokes the constructors of the attributes, so it is possible that they might throw unexpected exceptions.
// (Dev10 bug 831981)
}
if (attributes != null && attributes.Length != 0)
{
Debug.Assert(attributes.Length == 1);
PreApplicationStartMethodAttribute attribute = attributes[0];
Debug.Assert(attribute != null);
MethodInfo method = null;
// Ensure the Type on the attribute is in the same assembly as the attribute itself
if (attribute.Type != null && !String.IsNullOrEmpty(attribute.MethodName) && attribute.Type.Assembly == assembly)
{
method = FindPreStartInitMethod(attribute.Type, attribute.MethodName);
}
if (method != null)
{
methods.Add(method);
}
// No-op if the attribute is invalid
/*
else {
throw new HttpException(SR.GetString(SR.Invalid_PreApplicationStartMethodAttribute_value,
assembly.FullName,
(attribute.Type != null ? attribute.Type.FullName : String.Empty),
attribute.MethodName));
}
*/
}
}
return methods;
}
// Copied from xsp\System\Web\Compilation\BuildManager.cs
internal static MethodInfo FindPreStartInitMethod(Type type, string methodName)
{
Debug.Assert(type != null);
Debug.Assert(!String.IsNullOrEmpty(methodName));
MethodInfo method = null;
if (type.IsPublic)
{
// Verify that type is public to avoid allowing internal code execution. This implementation will not match
// nested public types.
method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase,
binder: null,
types: Type.EmptyTypes,
modifiers: null);
}
return method;
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The cache disposes of the dependency")]
private static void RegisterForChangeNotifications()
{
string physicalPath = HttpRuntime.AppDomainAppPath;
CacheDependency cacheDependency = new CacheDependency(physicalPath, DateTime.UtcNow);
var key = WebPagesDeployment.CacheKeyPrefix + physicalPath;
HttpRuntime.Cache.Insert(key, physicalPath, cacheDependency,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(OnChanged));
}
private static void OnChanged(string key, object value, CacheItemRemovedReason reason)
{
// Only handle case when the dependency has changed.
if (reason != CacheItemRemovedReason.DependencyChanged)
{
return;
}
// Scan the app root for a webpages file
if (WebPagesDeployment.AppRootContainsWebPagesFile(_physicalFileSystem, HttpRuntime.AppDomainAppPath))
{
// Unload the app domain so we register plan9 when the app restarts
InfrastructureHelper.UnloadAppDomain();
}
else
{
// We need to re-register since the item was removed from the cache
RegisterForChangeNotifications();
}
}
private static void LoadWebPages(Version version)
{
IEnumerable<AssemblyName> assemblyList = AssemblyUtils.GetAssembliesForVersion(version);
var assemblies = assemblyList.Select(LoadAssembly);
foreach (var asm in assemblies)
{
BuildManager.AddReferencedAssembly(asm);
}
foreach (var m in GetPreStartInitMethodsFromAssemblyCollection(assemblies))
{
m.Invoke(null, null);
}
}
private static Assembly LoadAssembly(AssemblyName name)
{
return Assembly.Load(name);
}
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.WebPages.Deployment;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Web.WebPages.Deployment")]
[assembly: AssemblyDescription("")]
[assembly: InternalsVisibleTo("System.Web.WebPages.Deployment.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")]

View File

@ -0,0 +1,108 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Web.WebPages.Deployment.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ConfigurationResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ConfigurationResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Web.WebPages.Deployment.Resources.ConfigurationResources", typeof(ConfigurationResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The &quot;InstallPath&quot; name was not found in the Web Pages registry key &quot;{0}&quot;..
/// </summary>
internal static string InstallPathNotFound {
get {
return ResourceManager.GetString("InstallPathNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The Web Pages registry key &quot;{0}&quot; does not exist..
/// </summary>
internal static string WebPagesRegistryKeyDoesNotExist {
get {
return ResourceManager.GetString("WebPagesRegistryKeyDoesNotExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Changes were detected in the Web Pages runtime version that require your application to be recompiled. Refresh your browser window to continue..
/// </summary>
internal static string WebPagesVersionChanges {
get {
return ResourceManager.GetString("WebPagesVersionChanges", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Conflicting versions of ASP.NET Web Pages detected: specified version is &quot;{0}&quot;, but the version in bin is &quot;{1}&quot;. To continue, remove files from the application&apos;s bin directory or remove the version specification in web.config..
/// </summary>
internal static string WebPagesVersionConflict {
get {
return ResourceManager.GetString("WebPagesVersionConflict", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Specified Web Pages version &quot;{0}&quot; could not be found. Update your web.config to specify a different version. Current version: &quot;{1}&quot;..
/// </summary>
internal static string WebPagesVersionNotFound {
get {
return ResourceManager.GetString("WebPagesVersionNotFound", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InstallPathNotFound" xml:space="preserve">
<value>The "InstallPath" name was not found in the Web Pages registry key "{0}".</value>
</data>
<data name="WebPagesRegistryKeyDoesNotExist" xml:space="preserve">
<value>The Web Pages registry key "{0}" does not exist.</value>
</data>
<data name="WebPagesVersionChanges" xml:space="preserve">
<value>Changes were detected in the Web Pages runtime version that require your application to be recompiled. Refresh your browser window to continue.</value>
</data>
<data name="WebPagesVersionConflict" xml:space="preserve">
<value>Conflicting versions of ASP.NET Web Pages detected: specified version is "{0}", but the version in bin is "{1}". To continue, remove files from the application's bin directory or remove the version specification in web.config.</value>
</data>
<data name="WebPagesVersionNotFound" xml:space="preserve">
<value>Specified Web Pages version "{0}" could not be found. Update your web.config to specify a different version. Current version: "{1}".</value>
</data>
</root>

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<CodeAnalysis Condition=" '$(CodeAnalysis)' == '' ">false</CodeAnalysis>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{22BABB60-8F02-4027-AFFC-ACF069954536}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>System.Web.WebPages.Deployment</RootNamespace>
<AssemblyName>System.Web.WebPages.Deployment</AssemblyName>
<FileAlignment>512</FileAlignment>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;ASPNETWEBPAGES</DefineConstants>
<CodeAnalysisRuleSet>..\Strict.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\Release\</OutputPath>
<DefineConstants>TRACE;ASPNETWEBPAGES</DefineConstants>
<CodeAnalysisRuleSet>..\Strict.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>$(CodeAnalysis)</RunCodeAnalysis>
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeCoverage|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\bin\CodeCoverage\</OutputPath>
<DefineConstants>TRACE;DEBUG;CODE_COVERAGE;ASPNETWEBPAGES</DefineConstants>
<DebugType>full</DebugType>
<CodeAnalysisRuleSet>..\Strict.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\CommonResources.Designer.cs">
<Link>Common\CommonResources.Designer.cs</Link>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>CommonResources.resx</DependentUpon>
</Compile>
<Compile Include="..\ExceptionHelper.cs">
<Link>Common\ExceptionHelper.cs</Link>
</Compile>
<Compile Include="..\GlobalSuppressions.cs">
<Link>Common\GlobalSuppressions.cs</Link>
</Compile>
<Compile Include="..\TransparentCommonAssemblyInfo.cs">
<Link>Properties\TransparentCommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AppDomainHelper.cs" />
<Compile Include="AssemblyUtils.cs" />
<Compile Include="BuildManagerWrapper.cs" />
<Compile Include="Common\IFileSystem.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Common\PhysicalFileSystem.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="IBuildManager.cs" />
<Compile Include="Resources\ConfigurationResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>ConfigurationResources.resx</DependentUpon>
</Compile>
<Compile Include="WebPagesDeployment.cs" />
<Compile Include="PreApplicationStartCode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\CommonResources.resx">
<Link>Common\CommonResources.resx</Link>
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>CommonResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Resources\ConfigurationResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ConfigurationResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<CodeAnalysisDictionary Include="..\CodeAnalysisDictionary.xml" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,386 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.WebPages.Deployment.Resources;
using Microsoft.Internal.Web.Utils;
using Microsoft.Win32;
namespace System.Web.WebPages.Deployment
{
public static class WebPagesDeployment
{
private const string AppSettingsVersionKey = "webpages:Version";
private const string AppSettingsEnabledKey = "webpages:Enabled";
/// <summary>
/// File name for a temporary file that we drop in bin to force recompilation.
/// </summary>
private const string ForceRecompilationFile = "WebPagesRecompilation.deleteme";
private const string WebPagesRegistryKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET Web Pages\v{0}.{1}";
internal static readonly string CacheKeyPrefix = "__System.Web.WebPages.Deployment__";
private static readonly string[] _webPagesExtensions = new[] { ".cshtml", ".vbhtml" };
private static readonly object _installPathNotFound = new object();
private static readonly IFileSystem _fileSystem = new PhysicalFileSystem();
/// <param name="path">Physical or virtual path to a directory where we need to determine the version of WebPages to be used.</param>
/// <remarks>
/// In a non-hosted scenario, this method would only look at a web.config that is present at the current path. Any config settings at an
/// ancestor directory would not be considered.
/// </remarks>
public static Version GetVersionWithoutEnabledCheck(string path)
{
if (String.IsNullOrEmpty(path))
{
throw ExceptionHelper.CreateArgumentNullOrEmptyException("path");
}
var binDirectory = GetBinDirectory(path);
var binVersion = AssemblyUtils.GetVersionFromBin(binDirectory, _fileSystem);
var maxVersion = AssemblyUtils.GetMaxWebPagesVersion();
return GetVersionInternal(GetAppSettings(path), binVersion, maxVersion);
}
[Obsolete("This method is obsolete and is meant for legacy code. Use GetVersionWithoutEnabled instead.")]
public static Version GetVersion(string path)
{
return GetObsoleteVersionInternal(path, GetAppSettings(path), new PhysicalFileSystem(), AssemblyUtils.GetMaxWebPagesVersion);
}
/// <remarks>
/// This is meant to test an obsolete method. Don't use this!
/// </remarks>
internal static Version GetObsoleteVersionInternal(string path, NameValueCollection configuration, IFileSystem fileSystem, Func<Version> getMaxWebPagesVersion)
{
if (String.IsNullOrEmpty(path))
{
throw ExceptionHelper.CreateArgumentNullOrEmptyException("path");
}
var binDirectory = GetBinDirectory(path);
var binVersion = AssemblyUtils.GetVersionFromBin(binDirectory, _fileSystem);
var version = GetVersionInternal(configuration, binVersion, defaultVersion: null);
if (version != null)
{
// If a webpages version is available in config or bin, return it.
return version;
}
else if (AppRootContainsWebPagesFile(fileSystem, path))
{
// If the path points to a WebPages site, return the highest version.
return getMaxWebPagesVersion();
}
return null;
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This operation might be expensive since it has to reflect over Assembly names.")]
public static Version GetMaxVersion()
{
return AssemblyUtils.GetMaxWebPagesVersion();
}
/// <summary>
/// Determines if Asp.Net Web Pages is enabled.
/// Web Pages is enabled if there's a webPages:Enabled key in AppSettings is set to "true" or if there's a cshtml file in the current path
/// and the key is not present.
/// </summary>
/// <param name="path">The path at which to determine if web pages is enabled.</param>
/// <remarks>
/// In a non-hosted scenario, this method would only look at a web.config that is present at the current path. Any config settings at an
/// ancestor directory would not be considered.
/// </remarks>
public static bool IsEnabled(string path)
{
if (String.IsNullOrEmpty(path))
{
throw ExceptionHelper.CreateArgumentNullOrEmptyException("path");
}
return IsEnabled(_fileSystem, path, GetAppSettings(path));
}
/// <remarks>
/// In a non-hosted scenario, this method would only look at a web.config that is present at the current path. Any config settings at an
/// ancestor directory would not be considered.
/// </remarks>
public static bool IsExplicitlyDisabled(string path)
{
if (String.IsNullOrEmpty(path))
{
throw ExceptionHelper.CreateArgumentNullOrEmptyException("path");
}
return IsExplicitlyDisabled(GetAppSettings(path));
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static IDictionary<string, Version> GetIncompatibleDependencies(string appPath)
{
if (String.IsNullOrEmpty(appPath))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "appPath");
}
var configFilePath = Path.Combine(appPath, "web.config");
var assemblyReferences = AppDomainHelper.GetBinAssemblyReferences(appPath, configFilePath);
return AssemblyUtils.GetAssembliesMatchingOtherVersions(assemblyReferences);
}
internal static bool IsExplicitlyDisabled(NameValueCollection appSettings)
{
bool? enabled = GetEnabled(appSettings);
return enabled.HasValue && enabled.Value == false;
}
internal static bool IsEnabled(IFileSystem fileSystem, string path, NameValueCollection appSettings)
{
bool? enabled = GetEnabled(appSettings);
if (!enabled.HasValue)
{
return AppRootContainsWebPagesFile(fileSystem, path);
}
return enabled.Value;
}
/// <summary>
/// Returns the value for webPages:Enabled AppSetting value in web.config.
/// </summary>
private static bool? GetEnabled(NameValueCollection appSettings)
{
string enabledSetting = appSettings.Get(AppSettingsEnabledKey);
if (String.IsNullOrEmpty(enabledSetting))
{
return null;
}
else
{
return Boolean.Parse(enabledSetting);
}
}
/// <summary>
/// Returns the version of WebPages to be used for a specified path.
/// </summary>
/// <remarks>
/// This method would always returns a value regardless of web pages is explicitly disabled (via config) or implicitly disabled (by virtue of not having a cshtml file) at
/// the specified path.
/// </remarks>
internal static Version GetVersionInternal(NameValueCollection appSettings, Version binVersion, Version defaultVersion)
{
// Return version values with the following precedence:
// 1) Version in config
// 2) Version in bin
// 3) defaultVersion.
return GetVersionFromConfig(appSettings) ?? binVersion ?? defaultVersion;
}
/// <summary>
/// Gets full path to a folder that contains ASP.NET WebPages assemblies for a given version. Used by
/// WebMatrix and Visual Studio so they know what to copy to an app's Bin folder or deploy to a hoster.
/// </summary>
public static string GetAssemblyPath(Version version)
{
if (version == null)
{
throw new ArgumentNullException("version");
}
string webPagesRegistryKey = String.Format(CultureInfo.InvariantCulture, WebPagesRegistryKey, version.Major, version.Minor);
object installPath = Registry.GetValue(webPagesRegistryKey, "InstallPath", _installPathNotFound);
if (installPath == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
ConfigurationResources.WebPagesRegistryKeyDoesNotExist, webPagesRegistryKey));
}
else if (installPath == _installPathNotFound)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
ConfigurationResources.InstallPathNotFound, webPagesRegistryKey));
}
return Path.Combine((string)installPath, "Assemblies");
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This operation might be expensive since it has to reflect over Assembly names.")]
public static IEnumerable<AssemblyName> GetWebPagesAssemblies()
{
return AssemblyUtils.GetAssembliesForVersion(AssemblyUtils.ThisAssemblyName.Version);
}
private static NameValueCollection GetAppSettings(string path)
{
if (path.StartsWith("~/", StringComparison.Ordinal))
{
// Path is virtual, assume we're hosted
return (NameValueCollection)WebConfigurationManager.GetSection("appSettings", path);
}
else
{
// Path is physical, map it to an application
WebConfigurationFileMap fileMap = new WebConfigurationFileMap();
fileMap.VirtualDirectories.Add("/", new VirtualDirectoryMapping(path, true));
var config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
var appSettingsSection = config.AppSettings;
var appSettings = new NameValueCollection();
foreach (KeyValueConfigurationElement element in appSettingsSection.Settings)
{
appSettings.Add(element.Key, element.Value);
}
return appSettings;
}
}
internal static Version GetVersionFromConfig(NameValueCollection appSettings)
{
string version = appSettings.Get(AppSettingsVersionKey);
// Version will be null if the config section is registered but not present in app web.config.
if (!String.IsNullOrEmpty(version))
{
// Build and Revision are optional in config but required by Fusion, so we set them to 0 if unspecified in config.
// Valid in config: "1.0", "1.0.0", "1.0.0.0"
var fullVersion = new Version(version);
if (fullVersion.Build == -1 || fullVersion.Revision == -1)
{
fullVersion = new Version(fullVersion.Major, fullVersion.Minor,
fullVersion.Build == -1 ? 0 : fullVersion.Build,
fullVersion.Revision == -1 ? 0 : fullVersion.Revision);
}
return fullVersion;
}
return null;
}
internal static bool AppRootContainsWebPagesFile(IFileSystem fileSystem, string path)
{
var files = fileSystem.EnumerateFiles(path);
return files.Any(IsWebPagesFile);
}
private static bool IsWebPagesFile(string file)
{
var extension = Path.GetExtension(file);
return _webPagesExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// HttpRuntime.BinDirectory is unavailable in design time and throws if we try to access it. To workaround this, if we aren't hosted,
/// we will assume that the path that was passed to us is the application root.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private static string GetBinDirectory(string path)
{
if (HostingEnvironment.IsHosted)
{
return HttpRuntime.BinDirectory;
}
return Path.Combine(path, "bin");
}
/// <summary>
/// Reads a previously persisted version number from build manager's cached directory.
/// </summary>
/// <returns>Null if a previous version number does not exist or is not a valid version number, read version number otherwise.</returns>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We never want to throw an exception from this method.")]
internal static Version GetPreviousRuntimeVersion(IBuildManager buildManagerFileSystem)
{
string fileName = GetCachedFileName();
try
{
Stream stream = buildManagerFileSystem.ReadCachedFile(fileName);
if (stream == null)
{
return null;
}
using (StreamReader reader = new StreamReader(stream))
{
string text = reader.ReadLine();
Version version;
if (Version.TryParse(text, out version))
{
return version;
}
}
}
catch
{
}
return null;
}
/// <summary>
/// Persists the version number in a file under the build manager's cached directory.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We never want to throw an exception from this method.")]
internal static void PersistRuntimeVersion(IBuildManager buildManager, Version version)
{
string fileName = GetCachedFileName();
try
{
Stream stream = buildManager.CreateCachedFile(fileName);
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(version.ToString());
}
}
catch
{
}
}
/// <summary>
/// Forces recompilation of the application by dropping a file under bin.
/// </summary>
/// <param name="fileSystem">File system instance used to write a file to bin directory.</param>
/// <param name="binDirectory">Path to bin directory of the application</param>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We never want to throw an exception from this method.")]
internal static void ForceRecompile(IFileSystem fileSystem, string binDirectory)
{
var fileToWrite = Path.Combine(binDirectory, ForceRecompilationFile);
try
{
// Note: We should use BuildManager::ForceRecompile once that method makes it into System.Web.
using (var writer = new StreamWriter(fileSystem.OpenFile(fileToWrite)))
{
writer.WriteLine();
}
}
catch
{
}
}
/// <summary>
/// Name of the the temporary file used by BuildManager.CreateCachedFile / BuildManager.ReadCachedFile where we cache WebPages's version number.
/// </summary>
/// <returns></returns>
private static string GetCachedFileName()
{
return typeof(WebPagesDeployment).Namespace;
}
private static string RemoveTrailingSlash(string path)
{
if (!String.IsNullOrEmpty(path))
{
path = path.TrimEnd(Path.DirectorySeparatorChar);
}
return path;
}
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
</packages>