Переопределить ресурс из стандартной сборки в ASP.NET - PullRequest
5 голосов
/ 29 марта 2010

Я хочу переопределить строку из System.ComponentModel.DataAnnotations для проекта ASP.NET. Нужно ли делать сателлитную сборку, возиться с нестандартными задачами сборки, al.exe и т. Д.? Даже если да, я не мог найти, как преобразовать .resx в .resources, чтобы скормить его в al.exe. А если нет, куда поставить .resx. и как его назвать?

UPD: чтобы было понятно: я хотел использовать пользовательскую строку ресурса вместо одной из ресурса по умолчанию из сборки. Я не хотел вносить изменения в каждом месте, где используется эта строка. В конце концов, ресурсы существуют только для их переопределения.

Ответы [ 4 ]

4 голосов
/ 05 апреля 2010

У Phil Haack есть отличная статья Локализация ASP.Net MVC Validation , которая специально поможет вам переопределить ваши строки.Эта статья относится к DataAnnotations больше, чем ASP.net MVC.Таким образом, это поможет, однако, вы используете DataAnnotattions .

Ниже я перечислил самые простые шаги для добавления локализованных ресурсов в Visual Studio.

  1. Откройте Project Properties диалоговое окно.
  2. Выберите вкладку Resources.
  3. Нажмите, чтобы создать новый файл ресурсов по умолчанию .
  4. Это создаст два файла в вашей папке Properties.
    • Resources.resx
    • Resources.Designer.cs
  5. Когда Ресурсы.Resx открылся, измените его Access Modifier на Public.
  6. Добавьте свои строки.

Чтобы добавить дополнительные файлы ресурсов для определенных культур , вам потребуется.

  1. Щелкните правой кнопкой мыши на Project в Solution Explorer.
  2. Выберите Добавить -> Новый элемент -> Ресурс Файл.
  3. Назовите его Resources.en-us.resx.(замените 'en-us' соответствующим кодом)
  4. Нажмите кнопку Добавить
  5. Перетащите его в папку Properties.
  6. Откройте Resources.en-us.resx и измените его Access Modifier на Public.
  7. Добавьте свои строки.
  8. Повторите для каждой культуры, которая вам нужнаsupport.

Во время сборки VS преобразует файлы .resx в .resource и создает классы-оболочки для вас.Затем вы можете получить доступ через пространство имен YourAssembly.Properties.Resources.

С помощью оператора using.

using YourAssembly.Properties;

Вы можете украсить такими атрибутами:

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "MyStringName")]

Примечание. Я использовал папку Properties для согласованности.Чтобы использовать App_GlobalResources, переместите туда свои файлы .resx и измените оператор using, чтобы он соответствовал имени каталога.Например:

using YourAssembly.App_GlobalResources;

Редактировать: ближе всего к ресурсам со строго типизированным именем можно сделать что-то вроде этого:

public class ResourceNames
{
    public const string EmailRequired = "EmailRequired";
}

Затем вы можете украситьАтрибуты, подобные этому.

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = ResourceNames.EmailRequired)]

Чтобы включить автоматическое обнаружение культуры клиента, добавьте globalizationsection в файл web.config .

<configuration>
    <system.web>
        <globalization enableClientBasedCulture="true" culture="auto:en-us" uiCulture="auto:en-us"/>
    </system.web>
<configuration>

Здесь я включил клиентскую культуру и установил culture и uiculture на " auto " со значением по умолчанию:" ru-ru ".


Создание отдельных спутниковых сборок:

MSDN Создание спутниковых сборок статьятакже поможет.Если вы новичок в спутниковых сборках, обязательно прочитайте Упаковка и развертывание ресурсов .

При создании спутниковых сборок в прошлом я нашел полезным использовать VSстроить события.Вот шаги, которые я бы предпринял.

  1. Создайте отдельный Class Library проект в моем решении.
  2. Создайте или добавьте мой .resx файлов в этот проект.
  3. Добавьте Post-Build Event в диалоговое окно Project Properties.(Как показано ниже)

Пример сценария VS пост-сборки:

set RESGEN="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\resgen.exe"
set LINKER="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\al.exe"
set ASSEMBLY=$(TargetName)
set SOURCEDIR=$(ProjectDir)
Set OUTDIR=$(TargetDir)

REM Build Default Culture Resources (en)
%RESGEN% %SOURCEDIR%en\%ASSEMBLY%.en.resx  %SOURCEDIR%en\%ASSEMBLY%.resources

REM Embed Default Culture
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%%ASSEMBLY%.resources.dll
REM Embed English Culture
IF NOT EXIST %OUTDIR%en\ MKDIR $%OUTDIR%en\
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%en\%ASSEMBLY%.resources.dll


REM These are just a byproduct of using the project build event to run the resource build script
IF EXIST %OUTDIR%%ASSEMBLY%.dll DEL %OUTDIR%%ASSEMBLY%.dll
IF EXIST %OUTDIR%%ASSEMBLY%.pdb DEL %OUTDIR%%ASSEMBLY%.pdb

Если вы предпочитаете не использовать ResGen.exe для преобразования ваших .resx файлов вы можете сделать что-то вроде этого.

using System;
using System.Collections;
using System.IO;
using System.Resources;

namespace ResXConverter
{
    public class ResxToResource
    {
        public void Convert(string resxPath, string resourcePath)
        {
            using (ResXResourceReader resxReader = new ResXResourceReader(resxPath))
            using (IResourceWriter resWriter = new ResourceWriter(
                    new FileStream(resourcePath, FileMode.Create, FileAccess.Write)))
            {
                foreach (DictionaryEntry entry in resxReader)
                {
                    resWriter.AddResource(entry.Key.ToString(), entry.Value);
                }
                resWriter.Generate();
                resWriter.Close();
            }
        }
    }
}

Одним из потенциальных недостатков такого преобразования является необходимость ссылкиSystem.Windows.Forms.dll.Вам по-прежнему нужно будет использовать Сборочный компоновщик .

Редактировать: как wRAR напомнил нам, если вы подписываете свои сборки, ваши ключи должны совпадать с .

2 голосов
/ 07 апреля 2010

Хотя это странно, особенно для людей, знакомых с технологиями локализации с открытым исходным кодом, нельзя создать сателлитную сборку для какой-либо сборки системы или даже сторонней сборки со знаком:

Если ваша основная сборка использует сильный Называя, спутниковые сборки должны быть подписан тем же секретным ключом, что и основная сборка. Если пара открытый / закрытый ключ не совпадает между основным и спутниковым сборок, ваших ресурсов не будет загружен.

Возможно ли то же самое автоматически, но без спутниковой сборки, неизвестно, хотя я сомневаюсь в этом.

1 голос
/ 03 апреля 2010

Предполагая, что вы хотите переопределить строки сообщений об ошибках по умолчанию в атрибутах проверки, вы можете сделать это, установив свойства ErrorMessageResourceName и ErrorMessageResourceType следующим образом:

[Required(ErrorMessageResourceName = "Required_Username", ErrorMessageResourceType = typeof(MyResourceFile)]
public string Username { get; set; }

Вы можете создать файл ресурсов MyResourceFile.resx, содержащий Required_Username с нужным сообщением об ошибке.

Надеюсь, это поможет.

0 голосов
/ 06 октября 2017

Если на сервере не установлены языковые пакеты .NET, то независимо от того, на что установлен CurrentUICulture, вы всегда будете получать английский в сообщениях проверки DataAnnotations. Этот эпический взлом работает на нас.

  • Перейти на страницу загрузки «Microsoft .NET Framework 4.6.1 Language Pack» https://www.microsoft.com/en-us/download/details.aspx?id=49977
  • Выберите язык и скачайте
  • Извлечение NDP461-KB3102436-x86-x64-AllOS- {LANG} .exe с 7-Zip
  • Извлечение CAB-файла x64-Windows10.0-KB3102502-x64.cab с 7-Zip
  • Найдите "msil_system.componentmod..notations.resources _...."
  • ... в котором вы найдете "system.componentmodel.dataannotations.resources.dll"
  • Откройте файл .resources.dll с помощью ILSpy, найдите «Ресурсы» и нажмите кнопку «Сохранить» над таблицей строк, чтобы сохранить как System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources. {LANGUAGE} .resources
  • Добавить в свой проект, скажем, "Ресурсы"
  • Убедитесь, что свойство Build Action файлов ресурсов установлено на «Embedded Resource»

Затем в методе PreStart вашего проекта вы перезаписываете приватное статическое поле System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resourceMan (сообщившее, что это был хак) теми, которые есть в вашем проекте.

using System;
using System.Linq;
using System.Reflection;
using System.Resources;

[assembly: WebActivator.PreApplicationStartMethod(typeof(ResourceManagerUtil), nameof(ResourceManagerUtil.PreStart))]

class ResourceManagerUtil
{
    public static void PreStart()
    {
        initDataAnnotationsResourceManager();
    }

    /// <summary>
    /// If the server doesn't have .NET language packs installed then no matter what CurrentUICulture is set to, you'll always get English in 
    /// DataAnnotations validation messages. Here we override DataAnnotationsResources to use a ResourceManager that uses language .resources 
    /// files embedded in this assembly.
    /// </summary>
    static void initDataAnnotationsResourceManager()
    {
        var embeddedResourceNamespace = "<YourProjectDefaultNamespace>.<FolderYouSavedResourcesFilesIn>";
        var dataAnnotationsResourcesName = "System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources";
        var thisAssembly = typeof(ResourceManagerUtil).Assembly;
        var dataAnnotationsAssembly = typeof(System.ComponentModel.DataAnnotations.ValidationAttribute).Assembly;

        var resourceManager = new ResourceManager(embeddedResourceNamespace + "." + dataAnnotationsResourcesName, thisAssembly);

        // Set internal field `DataAnnotationsResources.resourceMan`
        var dataAnnotationsResourcesType = dataAnnotationsAssembly.GetType(dataAnnotationsResourcesName);
        var resmanProp = dataAnnotationsResourcesType.GetField("resourceMan", BindingFlags.NonPublic | BindingFlags.Static);
        resmanProp.SetValue(null, resourceManager);
    }
}
...