来自自定义模型验证属性的验证消息将锁定到第一个加载的语言

时间:2015-10-16 07:03:15

标签: asp.net-mvc-4 internationalization umbraco7 asp.net-mvc-validation

我正在使用Umbraco 7.2.4(.NET MVC 4.5)开发多语言网站。我有每种语言的页面嵌套在具有自己文化的主节点下:

  • 主页(语言选择)
    • NL-BE
      • 一些页面
      • 其他一些页面
      • 我的表单页
    • FR-BE
      • 一些页面
      • 其他一些页面
      • 我的表单页

表单模型使用我需要为每种语言翻译的验证属性进行修饰。我找到了一个Github项目Umbraco Validation Attributes,它扩展了装饰属性以从Umbraco字典项中检索验证消息。它适用于页面内容,但不适用于验证消息。

问题

  • 登陆nl-BE /表格
    • 字段标签以荷兰语(nl-BE)
    • 显示
  • 提交无效表格
    • 验证消息以荷兰语(nl-BE文化)
    • 显示
  • 浏览到fr-BE /表格
    • 字段标签以法语(fr-BE)显示
  • 提交无效表格
    • 预期的行为是:验证信息以法语(fr-BE文化)显示
    • 实际行为是:消息仍显示在荷兰语中(data-val-required属性在页面源中以荷兰语显示)

迄今为止的调查

这不是浏览器缓存问题,它可以在不同的浏览器中重现,甚至是单独的计算机:第一次生成表单的人将锁定验证消息文化。更改验证消息语言的唯一方法是回收应用程序池。

我怀疑Umbraco验证助手课程是这里的问题但是我没有想法,所以任何见解都会受到赞赏。

源代码

模型

public class MyFormViewModel : RenderModel
{
    public class PersonalDetails
    {
        [UmbracoDisplayName("FORMS_FIRST_NAME")]
        [UmbracoRequired("FORMS_FIELD_REQUIRED_ERROR")]
        public String FirstName { get; set; }
    }
}

查看

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
var model = new MyFormViewModel();
using (Html.BeginUmbracoForm<MyFormController>("SubmitMyForm", null, new {id = "my-form"}))
{ 
            <h3>@LanguageHelper.GetDictionaryItem("FORMS_HEADER_PERSONAL_DETAILS")</h3>
        <div class="field-wrapper">
            @Html.LabelFor(m => model.PersonalDetails.FirstName)
            <div class="input-wrapper">
                @Html.TextBoxFor(m => model.PersonalDetails.FirstName)
                @Html.ValidationMessageFor(m => model.PersonalDetails.FirstName)
            </div>
        </div>

注意:我也使用了原生的MVC Html.BeginForm方法,结果相同。

控制器

public ActionResult SubmitFranchiseApplication(FranchiseFormViewModel viewModel)
    {
        if (!ModelState.IsValid)
        {
            TempData["Message"] = LanguageHelper.GetDictionaryItem("FORMS_VALIDATION_FAILED_MESSAGE");
            foreach (ModelState modelState in ViewData.ModelState.Values)
            {
                foreach (ModelError error in modelState.Errors)
                {
                    TempData["Message"] += "<br/>" + error.ErrorMessage;
                }
            }

            return RedirectToCurrentUmbracoPage();
        }
    }

LanguageHelper

public class LanguageHelper
{
    public static string CurrentCulture
    {
        get
        {
            return UmbracoContext.Current.PublishedContentRequest.Culture.ToString();
            // I also tried using the thread culture
            return System.Threading.Thread.CurrentThread.CurrentCulture.ToString(); 
        }
    }
    public static string GetDictionaryItem(string key)
    {
        var value = library.GetDictionaryItem(key);
        return string.IsNullOrEmpty(value) ? key : value;
    }
}

1 个答案:

答案 0 :(得分:0)

所以我终于找到了解决方法。为了将我的应用程序简化为最简单的形式并进行调试,我最终重新创建了&#34; UmbracoRequired&#34;装饰属性。在构造函数中设置ErrorMessage而不是在GetValidationRules方法中设置时出现问题。看起来MVC正在缓存构造函数的结果,而不是每次加载表单时再次调用它。为ErrorMessage添加动态属性到UmbracoRequired类也可以。

以下是我的自定义类最终的样子。

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
    AllowMultiple = false)]
internal class LocalisedRequiredAttribute : RequiredAttribute, IClientValidatable
{
    private string _dictionaryKey;
    public LocalisedRequiredAttribute(string dictionaryKey)
    {
        _dictionaryKey = dictionaryKey;            
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
       ModelMetadata metadata, ControllerContext context)
    {
        ErrorMessage = LanguageHelper.GetDictionaryItem(_dictionaryKey); // this needs to be set here in order to refresh the translation every time
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage, // if you invoke the LanguageHelper here, the result gets cached and you're locked to the current language
            ValidationType = "required"
        };
    }
}