私のコントローラーには、3 つの引数 (primary_key、property、および value) を受け取り、リフレクションを使用して対応するモデルに値を設定するアクションがあります。(主キーで検出)
invlaid の場合はモデルをキャッチできると思っていましたModelState.IsValid
が、true と評価されます。これでdb.SaveChanges();
例外がスローされます。
はModelState
有効です。(明らかに、主キーによって検出されたモデル インスタンスではなく、実際には私の 3 つの入力を参照しています)。
次の行でモデルのエラーをチェックできると思いました...
if (System.Data.Entity.Validation.DbEntityValidationResult.ValidationErrors.Empty)
しかし、「オブジェクト参照がありません」というエラーが表示されます。
それが何を意味するのかわかりません。(C# およびここにある他のすべては初めてです。) 何か助けはありますか?
編集 1 - より多くのコードを表示:
検証
[Column("pilot_disembarked")]
[IsDateAfter(testedPropertyName: "Undocked",
allowEqualDates: true,
ErrorMessage = "End date needs to be after start date")]
public Nullable<System.DateTime> PilotDisembarked { get; set; }
カスタムバリデーション
public sealed class IsDateAfter : ValidationAttribute, IClientValidatable
{
private readonly string testedPropertyName;
private readonly bool allowEqualDates;
public IsDateAfter(string testedPropertyName, bool allowEqualDates = false)
{
this.testedPropertyName = testedPropertyName;
this.allowEqualDates = allowEqualDates;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
}
var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (value == null || !(value is DateTime))
{
return ValidationResult.Success;
}
if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
{
return ValidationResult.Success;
}
// Compare values
if ((DateTime)value >= (DateTime)propertyTestedValue)
{
if (this.allowEqualDates)
{
return ValidationResult.Success;
}
if ((DateTime)value > (DateTime)propertyTestedValue)
{
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
コントローラ アクション
[HttpPost]
public ActionResult JsonEdit(string name, int pk, string value)
{
Voyage voyage = db.Voyages.Find(pk);
var property = voyage.GetType().GetProperty(name);
if (Regex.Match(property.PropertyType.ToString(), "DateTime").Success)
{
try
{
if (Regex.Match(value, @"^\d{4}$").Success)
{
var newValue = DateTime.ParseExact(value, "HHmm", System.Globalization.CultureInfo.InvariantCulture);
property.SetValue(voyage, newValue, null);
}
else if (value.Length == 0)
{
property.SetValue(voyage, null, null);
}
else
{
var newValue = DateTime.ParseExact(value, "yyyy/MM/dd HHmm", System.Globalization.CultureInfo.InvariantCulture);
property.SetValue(voyage, newValue, null);
}
}
catch
{
Response.StatusCode = 400;
return Json("Incorrect Time Entry.");
}
}
else
{
var newValue = Convert.ChangeType(value, property.PropertyType);
property.SetValue(voyage, newValue, null);
}
if (ModelState.IsValid)
{
db.SaveChanges();
Response.StatusCode = 200;
return Json("Success!");
}
else
{
Response.StatusCode = 400;
return Json(ModelState.Keys.SelectMany(key => this.ModelState[key].Errors));
}
}