在我的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属性。我只是不知道如何正确地覆盖它。
答案 0 :(得分:13)
为什么要为您的翻译和消息使用文本文件,.NET内置了翻译选项。您可以使用资源。使用资源的优点是资源是类型安全的,它们被检查为编译时。您的文本文件可能会损坏/丢失。
以下指南可帮助您在Mvc项目中设置资源:
编辑默认汇编语言:
将此语言设置为默认语言。 (对于此示例,我使用English (United States)
)
将资源文件添加到项目中。请将此文件称为Resource.resx
。打开此文件。将访问修饰符更改为Public
并开始添加资源字符串。例如:
为要支持其他资源文件的其他语言添加其他语言,但将其命名为Resource.LANGUAGE.resx
,其中LANGUAGE将替换为其他区域性名称。对于文化名称,您可以查看此网址:http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx
然后使用本地化字符串填充新资源文件。例如:
然后,您可以在模型中使用属性的默认本地化支持:
例如:
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
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()
获取所有错误消息,或使用
@Html.ValidationMessageFor(Function(model) model.Property)
@Html.ValidationMessageFor(m => m.Property)
获取特定的错误消息。
对于display属性,您可以使用:
@Html.DisplayNameFor(Function(model) model.Property)
@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但只使用单个文本文件,则可以使用资源框架使用的相同概念。您需要一个具有可以引用的静态属性的类。
为此,我做了以下事情:
Resources
的类(Resources.vb)。 Resource
resource.xml
,我已将其映射到Resource
Dictionary(Of String, String)
ResourceType
类UserModel
参数
醇>
当然有点清理。可以删除旧资源,并可以从globalization
删除web.config
标记。
现在可以在resource.xml
中找到所有文本作为键值对。要添加另一行,请将其添加到XML并在Resource
类中为其创建属性。
对于此次更新,我更新了我的示例项目:
MvcVBTest.V2.zip
答案 1 :(得分:0)
为什么不使用这样的东西?
<RequiredField(ErrorMessage=GetErrorMessage())>
只需创建一个静态函数,为您获取错误消息。您甚至可以为GetErrorMessage函数获取一个参数,以便确定要返回的消息。