public void CreateRedirectPages(SiteConfigurationElement configuration, string oldUrl, string newUrl)
        {
            if (configuration == null || !configuration.Enabled)
            {
                return;
            }

            if (!Directory.Exists(configuration.OutputPath + oldUrl))
            {
                // Directory doesn't exist, nothing to remove :)
                return;
            }

            if (!File.Exists(configuration.OutputPath + oldUrl + "index.html"))
            {
                // File doesn't exist, nothing to remove :)
                return;
            }

            try
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(configuration.OutputPath + oldUrl);
                var           fileInfos     = directoryInfo.GetFiles("index.html", SearchOption.AllDirectories);

                foreach (FileInfo info in fileInfos)
                {
                    var tempPath = info.FullName;
                    // c:\websites\A\
                    tempPath = "/" + tempPath.Replace(configuration.OutputPath, "").Replace("\\", "/");
                    // /old/
                    tempPath = tempPath.Replace(oldUrl, "");

                    // index.html
                    tempPath = tempPath.Replace("index.html", "");

                    // /new/
                    tempPath = newUrl + tempPath;

                    // Create redirect html file
                    var redirectHtml = $"<!doctype html><html><head><meta charset=\"utf-8\"><meta http-equiv=\"refresh\" content=\"0; URL='{tempPath}'\" /></head><body><a href=\"{tempPath}\">{tempPath}</a></body></html>";
                    File.WriteAllText(info.FullName, redirectHtml);

                    AfterIOWrite?.Invoke(this, new StaticWebIOEvent {
                        FilePath = info.FullName, Data = Encoding.UTF8.GetBytes(redirectHtml)
                    });
                }
            }
            catch (Exception)
            {
                // something was wrong, but this is just extra cleaning so ignore it
                return;
            }
        }
        protected void WriteFile(string filepath, byte[] data, bool?useTemporaryAttribute)
        {
            filepath = EnsureFileSystemValid(filepath);
            var directory = Path.GetDirectoryName(filepath);

            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            if (!useTemporaryAttribute.HasValue)
            {
                using (FileStream fs = File.Open(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                {
                    fs.Write(data, 0, data.Length);
                    fs.SetLength(data.Length);
                }
            }
            else if (useTemporaryAttribute.Value)
            {
                using (FileStream fs = File.Open(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                {
                    File.SetAttributes(filepath, FileAttributes.Normal);
                    fs.Write(data, 0, data.Length);
                    fs.SetLength(data.Length);
                }
            }
            else
            {
                using (FileStream fs = File.Open(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                {
                    File.SetAttributes(filepath, FileAttributes.Temporary);
                    fs.Write(data, 0, data.Length);
                    fs.SetLength(data.Length);
                }
            }

            AfterIOWrite?.Invoke(this, new StaticWebIOEvent {
                FilePath = filepath, Data = data
            });
        }