MVC - 更改比较属性错误消息

时间:2012-11-19 11:44:32

标签: asp.net-mvc vb.net

在我的MVC应用程序中,我能够从文本文件中获取错误消息,而不是使用默认错误消息。这完全适用于Required属性(Serverside和Clientside)。

我现在需要对比较属性做同样的事情,但我无法弄清楚如何覆盖Compare属性。

作为参考,这就是我使用Required属性的方式(我希望使用类似的代码来使用比较属性)...

Public Class RequiredFieldAttribute
    Inherits ValidationAttribute
    Implements IClientValidatable

    Private innerAttribute As New RequiredAttribute()
    Private errormessagecontrolid As String

    Public Sub New(ErrorMessageControlID As String)

        Me.errormessagecontrolid = ErrorMessageControlID

    End Sub

    Protected Overrides Function IsValid(value As Object, validationContext As ValidationContext) As ValidationResult

        If Not innerAttribute.IsValid(value) Then
            Return New ValidationResult(ErrorMsgs.Text(Me.errormessagecontrolid))
        End If

        Return ValidationResult.Success

    End Function

    Public Function GetClientValidationRules(metadata As ModelMetadata, context As ControllerContext) As IEnumerable(Of ModelClientValidationRule) Implements IClientValidatable.GetClientValidationRules

        Dim result = New List(Of ModelClientValidationRule)

        Dim rule = New ModelClientValidationRule() With {.ErrorMessage = ErrorMsgs.Text(Me.errormessagecontrolid), .ValidationType = "required"}

        result.Add(rule)

        Return result

    End Function

End Class

在上面,ErrorMsgs.Text是从文本文件中撤消消息的函数。反对我的模型,然后应用这样的东西......

<RequiredField("AccountDetailsPostcodeError")>
Public Property PostCode As String

系统然后在Text文件中查找名为AccountDetailsPostcodeError的条目。

如何使用Compare属性实现相同的功能。目前我有一个像这样的硬编码错误消息...

    <Compare("WebPassword", ErrorMessage:="The password and confirmation do not match.")>
    Public Property ConfirmWebPassword As String

编辑:下面建议的修补程序可能在C#中有效,但在VB.NET中不起作用,因此我需要覆盖Compare属性。我只是不知道如何正确地覆盖它。

2 个答案:

答案 0 :(得分:13)

为什么要为您的翻译和消息使用文本文件,.NET内置了翻译选项。您可以使用资源。使用资源的优点是资源是类型安全的,它们被检查为编译时。您的文本文件可能会损坏/丢失。

以下指南可帮助您在Mvc项目中设置资源:

第一步

编辑默认汇编语言:

  • (C#)属性&gt;装配信息&gt;中性语言
  • (VB)我的项目&gt;装配信息&gt;中性语言

将此语言设置为默认语言。 (对于此示例,我使用English (United States)

第二步

将资源文件添加到项目中。请将此文件称为Resource.resx。打开此文件。将访问修饰符更改为Public并开始添加资源字符串。例如: Default English resources

第三步

为要支持其他资源文件的其他语言添加其他语言,但将其命名为Resource.LANGUAGE.resx,其中LANGUAGE将替换为其他区域性名称。对于文化名称,您可以查看此网址:http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx

然后使用本地化字符串填充新资源文件。例如: English Resources

第四步

然后,您可以在模型中使用属性的默认本地化支持:

例如:

VB:

Imports System.ComponentModel.DataAnnotations
Public Class UserModel
    <Display(Name:="UserNameField", ResourceType:=GetType(My.Resources.Resource))>
    <Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredUsername", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
    Public Property UserName As String

    <Display(Name:="PasswordField", ResourceType:=GetType(My.Resources.Resource))>
    <MinLength(6, ErrorMessageResourceName:="PasswordLengthError", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
    <Compare("PasswordAgain", ErrorMessageResourceName:="CompareError", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
    <Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredPassword", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
    Public Property Password As String

    <Display(Name:="PasswordAgainField", ResourceType:=GetType(My.Resources.Resource))>
    <Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredPasswordAgain", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
    Public Property PasswordAgain As String
End Class

C#

using System.ComponentModel.DataAnnotations;
public class UserModel
{
    [Display(Name = "UserNameField", ResourceType = typeof(My.Resources.Resource))]
    [Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredUsername", ErrorMessageResourceType = typeof(My.Resources.Resource))]
    public string UserName;

    [Display(Name = "PasswordField", ResourceType = typeof(My.Resources.Resource))]
    [MinLength(6, ErrorMessageResourceName = "PasswordLengthError", ErrorMessageResourceType = typeof(My.Resources.Resource))]
    [Compare("PasswordAgain", ErrorMessageResourceName = "CompareError", ErrorMessageResourceType = typeof(My.Resources.Resource))]
    [Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredPassword", ErrorMessageResourceType = typeof(My.Resources.Resource))]
    public string Password;

    [Display(Name = "PasswordAgainField", ResourceType = typeof(My.Resources.Resource))]
    [Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredPasswordAgain", ErrorMessageResourceType = typeof(My.Resources.Resource))]
    public string PasswordAgain;
}

对于本地化,属性需要知道静态属性的名称以及从哪里获取属性的静态类的类型(如上所示)。

第五步

然后在您的视图中使用@Html.ValidationSummary()获取所有错误消息,或使用

  • VB @Html.ValidationMessageFor(Function(model) model.Property)
  • C# @Html.ValidationMessageFor(m => m.Property)

获取特定的错误消息。

对于display属性,您可以使用:

  • VB @Html.DisplayNameFor(Function(model) model.Property)
  • C# @Html.DisplayNameFor(m => m.Property)

更改语言

最后但并非最不重要的是,您可以通过编辑Web.config并更改全球化标记来更改应用的语言,而不是第1步中定义的中性语言:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <globalization uiCulture="nl" />
  </system.web>
</configuration>

如果您想更改代码中的语言,则应编辑System.Threading.Thread.CurrentThread.CurrentUICulture以获取有关此信息的信息,我建议谷歌或其他问题。


示例项目

对于这个问题,我很快做了一个示例项目来提供准确的答案。项目可以在这里找到:
MvcVBTest.V1.zip


更新

如果您不想使用Resources但只使用单个文本文件,则可以使用资源框架使用的相同概念。您需要一个具有可以引用的静态属性的类。

为此,我做了以下事情:

  1. 我创建了一个名为Resources的类(Resources.vb)。
  2. 在本课程中,我添加了一个名为Resource
  3. 的子类
  4. 在这个类的静态构造函数中,我打开resource.xml,我已将其映射到Resource
  5. 数组
  6. 然后将此数组转换为Dictionary(Of String, String)
  7. 我为xml中的每个项目创建了一个静态get属性。并从词典中返回了正确的项目
  8. 我更改了ResourceType
  9. 中的UserModel参数

    当然有点清理。可以删除旧资源,并可以从globalization删除web.config标记。

    现在可以在resource.xml中找到所有文本作为键值对。要添加另一行,请将其添加到XML并在Resource类中为其创建属性。

    示例项目

    对于此次更新,我更新了我的示例项目:
    MvcVBTest.V2.zip

答案 1 :(得分:0)

为什么不使用这样的东西?

<RequiredField(ErrorMessage=GetErrorMessage())>

只需创建一个静态函数,为您获取错误消息。您甚至可以为GetErrorMessage函数获取一个参数,以便确定要返回的消息。