public partial class TaskScheduling
{
public Guid EvaluationTemplateId { get; set; }
//[Required(ErrorMessage = "TaskScheduling.OwnerUser")]
[Required(ErrorMessage = ResolveErrorMessage())]
public string SenderName { get; set; }
[Required]
public string SenderMail { get; set; }
[Required]
public string Subject { get; set; }
[Required]
public string BodyMessage { get; set; }
private string ResolveErrorMessage()
{
//Code to customize the error message here.
return "test";
}
}
我正在尝试将错误消息绑定到函数,因此我可以自定义将显示的消息类型。 但是当我尝试将错误消息设置为函数ResolveErrorMessage时,编译器会说:访问非静态字段,方法或属性'TaskScheduling.ResolveErrorMessage()'需要对象引用。
因此我尝试将ResolveErrorMessage设置为静态函数。
private static string ResolveErrorMessage()
{
//Code to customize the error message here.
return "test";
}
现在编译器抱怨如下: 属性参数必须是表达式或数组创建表达式的常量表达式。
那么,我正在尝试做甚么可能吗?
答案 0 :(得分:0)
如评论中所述,这是不可能的。需要在编译时知道该值。此外,运行时如何知道何时调用此方法,以及如何在没有任何可用数据的情况下自定义它,例如无效的值。
还有其他方法,但这取决于您想要自定义错误消息的程度。
在最简单的情况下,您只需在消息文本中添加{0}
占位符,以便在何处放置属性名称:
[Required(ErrorMessage = "Please enter {0}!")]
public string SenderName { get; set; }
或者,如果您希望稍后更新错误消息而不使用ErrorMessageResourceType
和ErrorMessageResourceName
属性重新编译代码,则可以引用资源字符串而不是硬编码的消息文本:
[Required(ErrorMessageResourceType = typeof(MyMessageResources), ErrorMessageResourceName = "SenderNameRequiredMessage")]
public string SenderName { get; set; }
如果你做需要逻辑来自定义错误信息,你最好创建一个RequiredAttribute
的子类,并根据需要覆盖属性或方法,以便在那里添加逻辑。 / p>
例如,如果由于某些不明原因您想在错误消息中添加星期几,则可以覆盖FormatErrorMessage()
来执行此操作:
public class DayOfWeekRequiredAttribute : RequiredAttribute
{
public override string FormatErrorMessage(string propertyName)
{
string day = DateTime.Today.DayOfWeek.ToString();
return string.Format(this.ErrorMessage, propertyName, day);
}
}
public partial class TaskScheduling
{
// {0} is property name, {1} is day of week
[DayOfWeekRequired(ErrorMessage = "Hey, it's {1} and {0} is a required field!")]
public string SenderName { get; set; }
}
你可以使它更通用一些并传递一个负责解决错误信息的类型,这样你就不需要很多XXXXRequireAttribute
个类:
// interface representing a class for resolving the error message
public interface IErrorMessageResolver
{
// The attribute will call this method
string ResolveErrorMessage(string propertyName, object value);
}
public class MessageResolverRequiredAttribute : RequiredAttribute
{
// Stores the type responsible for resolving the error message
public Type MessageResolverType { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// call the built-in RequiredAttribute validator
ValidationResult result = base.IsValid(value, validationContext);
// if not valid, attempt to get the custom error message
if (!result.Equals(ValidationResult.Success))
{
if (this.MessageResolverType != null)
{
// create the resolver and check it actually is a resolver
IErrorMessageResolver handler = Activator.CreateInstance(this.MessageResolverType) as IErrorMessageResolver;
if (handler == null)
{
throw new Exception("MessageResolverType is not an IErrorMessageResolver");
}
// get the custom error message, if returns null, don't override the built-in error message
string customError = handler.ResolveErrorMessage(validationContext.MemberName, value);
if (customError != null)
{
result.ErrorMessage = customError;
}
}
}
return result;
}
}
public partial class TaskScheduling
{
[MessageResolverRequired(MessageResolverType = typeof(MyMessageResolver))]
public string SenderName { get; set; }
}
要询问正在验证错误消息的实例,您可以使用与上面的常规自定义逻辑相同的主体,但这将是实现IErrorMessageResolver
所需的失败。您可以使用validationContext.ObjectInstance
属性来掌握此功能。我想说,如果您需要在实例中使用private
数据来创建错误消息,这实际上非常有用。否则它有点奇怪,非SOLID模式。
// interface representing a class for resolving the error message
public interface IErrorMessageResolver
{
// The attribute will call this method
string ResolveErrorMessage(string propertyName, object value);
}
public class MessageResolverRequiredAttribute : RequiredAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult result = base.IsValid(value, validationContext);
if (!result.Equals(ValidationResult.Success))
{
IErrorMessageResolver handler = validationContext.ObjectInstance as IErrorMessageResolver;
if (handler == null)
{
throw new Exception("Not validating an IErrorMessageResolver");
}
string customError = handler.ResolveErrorMessage(validationContext.MemberName, value);
if (customError != null)
{
result.ErrorMessage = customError;
}
}
return result;
}
}
public partial class TaskScheduling
: IErrorMessageResolver
{
[MessageResolverRequired(MessageResolverType = typeof(MyMessageResolver))]
public string SenderName { get; set; }
public string ResolveErrorMessage(string propertyName, object value)
{
if (propertyName == "SenderName")
{
return "You need to set a Sender!";
}
return null;
}
}