シナリオ
注文の送料を検証するカスタムルールがあります。
public class OrderValidator : BaseValidator<Order>
{
private string CustomInfo { get; set; }
public OrderValidator()
{
//here I call the custom validation method and I try to add the CustomInfo string in the message
RuleFor(order => order.ShippingCost).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Must(
(order, shippingCost) => CheckOrderShippingCost(order, shippingCost)
).WithMessage("{PropertyName} not set or not correct: {PropertyValue}." + (String.IsNullOrEmpty(CustomInfo) ? "" : " " + CustomInfo));
}
//this is the custom validation method
private bool CheckOrderShippingCost(Order o, decimal shippingCost)
{
bool res = false;
try
{
/*
* check the actual shippingCost and set the res value
*/
}
catch (Exception ex)
{
CustomInfo = ex.ToString();
res = false;
}
return res;
}
}
例外の場合は、例外情報をCustomInfoプライベートメンバーに保存し、検証メッセージに追加します。
次に、バリデーターを実行します。
OrderValidator oVal = new OrderValidator();
oVal.Results = oVal.Validate(order);
if (!oVal.Results.IsValid)
oVal.Results.Errors.ForEach(delegate(ValidationFailure error) {
Console.WriteLine(error.ErrorMessage);
});
問題
例外の場合、CustomInfoがex.ToString()値に適切に設定されていれば、すべてが正しく機能します。ただし、最終的にコンソールに表示されるエラーメッセージには、CustomInfoは表示されず、メッセージの最初の部分のみが表示されます。
"Shipping Cost not set or not correct: 5.9"
質問
カスタムメッセージにCustomInfo文字列が含まれていないのはなぜですか?別の方法でカスタムメッセージに例外情報を追加することは可能ですか?
あなたはむしろ使用する必要があります
.WithMessage("{PropertyName} not set or not correct: {PropertyValue}. {0}", order => order.CustomInfo);
これには、バリデータークラスではなく、OrderクラスのレベルでCustomInfoが必要になります。
[〜#〜]編集[〜#〜]
あなたが使用することができます:
public static class OrderExtensions
{
private static IDictionary<Order,string> customErrorMessages;
public static void SetError(this Order order, string message) {
if (customErrorMessages == null) {
customErrorMessages = new Dictionary<Order,string>();
}
if (customErrorMessages.ContainsKey(order)) {
customErrorMessages[order] = message;
return;
}
customErrorMessages.Add(order, message);
}
public static string GetError(this Order order) {
if (customErrorMessages == null || !customErrorMessages.ContainsKey(order)) {
return string.Empty;
}
return customErrorMessages[order];
}
}
バリデーターにいくつかの小さな変更を加えます
public class OrderValidator : BaseValidator<Order>
{
public OrderValidator()
{
//here I call the custom validation method and I try to add the CustomInfo string in the message
RuleFor(order => order.ShippingCost).Cascade(CascadeMode.StopOnFirstFailure).NotNull().Must(
(order, shippingCost) => CheckOrderShippingCost(order, shippingCost)
).WithMessage("{PropertyName} not set or not correct: {PropertyValue}. {0}", order => order.GetError()));
}
//this is the custom validation method
private bool CheckOrderShippingCost(Order o, decimal shippingCost)
{
bool res = false;
try
{
/*
* check the actual shippingCost and set the res value
*/
}
catch (Exception ex)
{
order.SetError(ex.ToString());
res = false;
}
return res;
}
}