Не секрет, что многие предпочитают использовать UTF-8 как кодировку выходных HTML файлов web-приложения. Однако, использование этой кодировки в проекте на ASP.NET MVC может осложняться следующей проблемой: при создании видов (aspx/ascx) в Visual Studio вновь созданные файлы сохраняются в другой кодировке. Это зависит то ли от настроек компьютера то ли от кодировки соответствующих шаблонов. Приходится вручную открывать эти файлы и преобразовывать в UTF-8.

Но хуже всего — если на продакшн-сервер «просочатся» не-utf-8-шаблоны, то соответствующие области сайта будут отображать кракозябры вместо, например, русских букв. Когда над проектом работает большая команда, такая ситуация вполне возможна, потому что кто-нибудь из разработчиков может легко забыть изменить кодировку.

Один из способ не допустить проникновения чужеродной кодировки в продакшн-сервер — создать соответствующий интеграционный тест. Этот тест будет запускаться на CI-сервере каждый раз после сборки и, в случае провала, даст знать разработчикам о проблемных файлах.

Итак, тест должен делать следующее:

  1. Рекурсивно перебирать все файлы в папке Views.
  2. Проверять, кодирован ли каждый файл в UTF-8.
  3. Накапливать информацию обо всех файлах с врождебной кодировкой.

Отдельно следует отметить пункт 2. Известно, что нет универсального способа определения кодировки произвольного файла. Есть только методы, позволяющий предположить, что тот или иной файл сохранён в той или иной кодировке. Для случая UTF-8 эта унылая задача несколько облегчается — библиотека Utf8Checker сделает всё за нас. Utf8Checker по сути состоит из одного единственного файла с таким интерфейсом:

/// <summary>
/// Interface for checking for utf8.
/// </summary>
public interface IUtf8Checker
{
    /// <summary>
    /// Check if file is utf8 encoded.
    /// </summary>
    /// <param name="fileName"></param>
    /// <returns>true if utf8 encoded, otherwise false.</returns>
    bool Check(string fileName);

    /// <summary>
    /// Check if stream is utf8 encoded.
    /// </summary>
    /// <param name="stream"></param>
    /// <returns>true if utf8 encoded, otherwise false.</returns>
    bool IsUtf8(Stream stream);
}

Как видно, выделенный метод делает то, что нам нужно — проверяет, кодирован ли файл в UTF-8.

Итак, получившийся код теста:

[TestFixture]
public class EncodingTests
{
    private const string VIEWS_ROOT_FOLDER = 
        "../../../НАЗВАНИЕ ПРОЕКТА/Views";

    private static readonly IList<string> IgnoreDirectoryNames = 
        new[] {".svn"};                                     4

    private IUtf8Checker _utf8Checker = new Utf8Checker();

    [Test]
    public void TestAllViewsUtf8Encoded()                   5
    {
        var errorFiles = new List<string>();

        CheckFilesUtf8Encoded(VIEWS_ROOT_FOLDER, errorFiles);

        if (errorFiles.Count > 0)
        {
            var messageBuilder = new StringBuilder();
            foreach (var file in errorFiles)
            {
                messageBuilder.AppendLine("File {0} is not UTF-8 encoded!"
                    .FormatWith(file));
            }

            Assert.Fail(messageBuilder.ToString());         6
        }
    }

    private void CheckFilesUtf8Encoded(
        string path, 
        List<string> errorFiles)                            1
    {
        foreach (var file in Directory.GetFiles(path))
        {
            var isUtf8Encoded = _utf8Checker.Check(file);   2
            if (!isUtf8Encoded)
            {
                errorFiles.Add(file);                       3
            }
        }

        foreach (var directory in Directory.GetDirectories(path))
        {
            var directoryName = new DirectoryInfo(directory).Name;
            if (!IgnoreDirectoryNames.Contains(directoryName))
            {
                CheckFilesUtf8Encoded(directory, errorFiles);    
            }
        }
    }
}

Метод CheckFilesUtf8Encoded 1 рекурсивно перебирает все папки и для каждого файла проверяет его кодировку. Если кодировка не UTF-8 2, то путь добавляется в список «ошибочных» файлов 3. Чтобы не проводить проверку внутри папок системы контроля версий (в моём случае это папки .svn) определён список 4 имён, которые игнорируются.

Основной метод теста — TestAllViewsUtf8Encoded 5 накапливает имена фалов с неверной кодировкой, выводит сообщение 6 если такие файлы найдены.

В результате, после выполнения такого теста, в системе CI или просто в логах test-runner можно увидеть список не-utf видов.

Progg it