来自自定义模型验证属性的验证消息被锁定到首次加载的语言



我正在使用Umbraco 7.2.4()制作一个多语言网站。Net MVC 4.5)。我在主节点下嵌套了每种语言的页面,具有各自的文化:

  • 主页(语言选择)
    • nl-BE
        某些页面
      • 其他页面
      • 我的表单页
    • fr-BE
        某些页面
      • 其他页面
      • 我的表单页

表单模型用验证属性装饰,我需要为每种语言翻译这些属性。我发现了一个Github项目,Umbraco Validation Attributes,它扩展了装饰属性,从Umbraco字典项中检索验证消息。它可以很好地处理页面内容,但不能处理验证消息。

问题
  • 降落在nl-BE/form
    • 字段标签以荷兰语(nl-BE)显示
  • 提交无效表单
    • 验证消息以荷兰语(nl-BE文化)显示
  • 浏览到fr-BE/格式
    • 字段标签以法语(fr-BE)显示
  • 提交无效表单
    • 预期行为是:验证消息以法语(fr-BE文化)显示
    • 实际行为是:消息仍然以荷兰语显示(data- value -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;
    }
}

所以我终于找到了一个解决方法。为了将我的应用简化为最简单的形式并进行调试,我最终重新创建了"umbracrequired"装饰属性。当ErrorMessage在构造函数中而不是在GetValidationRules方法中设置时,就会出现这个问题。似乎MVC正在缓存构造函数的结果,而不是每次加载表单时再次调用它。为ErrorMessage添加一个动态属性到umbracrequired类也可以。

下面是我的自定义类最后的样子。

[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"
        };
    }
}

最新更新