自定义视图模型数据 - 注释错误:属性参数必须是常量表达式,

时间:2013-06-17 21:17:53

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

在我的ASP.NET MVC3项目中,我有一个这样的视图模型,其中我为属性编写了硬编码的错误消息。

public class UserProfileVM
{
  [Required]
  [StringLength(200, ErrorMessage = "Name should be 10 chars")]
  public string Name { set;get;}

 //other properties
}

我想根据用户的偏好设置(语言用户选择)动态加载ErrorMessage属性的值。所以我有函数返回像这样的语言标签

public string GetLabel(string labelCode)
{
  string labelText="Get from somewhere using labelCode";
  //Get User's language preference from Session and return the labelText here
  return labelText;
}

我试图在我的视图模型中使用它

[Required]
[StringLength(200, ErrorMessage = GetLabel("MinCharErr"))]
public string Name { set;get;}

但我无法编译我的代码。我收到的错误就像 属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式

有人能告诉我如何解决这个问题。我需要使用GetLabel方法来获取相关文本。

2 个答案:

答案 0 :(得分:1)

您应该创建自己的StringLength类来实现此目的:

public class CustomStringLength : StringLengthAttribute {
    public CustomStringLength() {
        //Set your error message right here
        base.ErrorMessage = userOptions.GetErrorByLabel(labelCode);
    }
}

显然,这需要连接到您的后端数据,但是,这是如何动态设置错误消息的一般概念。

答案 1 :(得分:0)

  

但我无法编译我的代码。我收到像An这样的错误   attribute参数必须是常量表达式,typeof表达式或   数组创建表达式的属性参数类型

因为您无法自定义ErrorMessageResourceNameErrorMessageResourceType等属性来获取某些动态结果。

您只能通过在Customized类中传递Parameterized Constructor来自定义Length类中的StringLengthAttribute属性。这意味着您只能Override Length String

就像你说你想传递一些密钥来获得相应的Error Message,这是不可能的。

您也可以在资源文件

中编写下面提到的消息
"Maximum allowed length is {0}"

在运行时,您可以通过在自定义类中使用参数化构造函数值(最大字符串长度)替换它来格式化字符串

  

从Session获取用户的语言首选项并返回labelText   这里

您已在Global.asax文件中设置语言。因此,将根据UserLanguage选择您的资源文件。因此,只需指定密钥名称,将根据所选语言从Resource file获取相应的值

如何设置语言?

public sealed class LanguageManager
{
    /// <summary>
    /// Default CultureInfo
    /// </summary>
    public static readonly CultureInfo DefaultCulture = new CultureInfo("en-US");

    /// <summary>
    /// Available CultureInfo that according resources can be found
    /// </summary>
    public static readonly CultureInfo[] AvailableCultures;

    static LanguageManager()
    {
        List<string> availableResources = new List<string>();
        string resourcespath = Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "App_GlobalResources");
        DirectoryInfo dirInfo = new DirectoryInfo(resourcespath);
        foreach (FileInfo fi in dirInfo.GetFiles("*.*.resx", SearchOption.AllDirectories))
        {
            //Take the cultureName from resx filename, will be smt like en-US
            string cultureName = Path.GetFileNameWithoutExtension(fi.Name); //get rid of .resx
            if (cultureName.LastIndexOf(".") == cultureName.Length - 1)
                continue; //doesnt accept format FileName..resx
            cultureName = cultureName.Substring(cultureName.LastIndexOf(".") + 1);
            availableResources.Add(cultureName);
        }

        List<CultureInfo> result = new List<CultureInfo>();
        foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
        {
            //If language file can be found
            if (availableResources.Contains(culture.ToString()))
            {
                result.Add(culture);
            }
        }

        AvailableCultures = result.ToArray();

        CurrentCulture = DefaultCulture;
        if (!result.Contains(DefaultCulture) && result.Count > 0)
        {
            CurrentCulture = result[0];
        }
    }

    /// <summary>
    /// Current selected culture
    /// </summary>
    public static CultureInfo CurrentCulture
    {
        get { return Thread.CurrentThread.CurrentCulture; }
        set
        {
            Thread.CurrentThread.CurrentUICulture = value;
            Thread.CurrentThread.CurrentCulture = value;
        }
    }
}