ModelState.IsValid ложно, но должно быть истинным - PullRequest
0 голосов
/ 08 мая 2020

У меня есть приложение ASP. NET MVC с обновлением AJAX. Операции CRUD для каждого объекта работают правильно, за исключением создания «Квитанции». Проблема возникает, когда контроллер нажимает ModelState.IsValid, что переводится в false, хотя на самом деле это должно быть истиной. Я много раз отлаживал все шаг за шагом, и это всегда ложно, когда должно быть правдой.

Я использую Entity Framework для управления сущностями, и это код, который был сгенерирован из базы данных SQL сервера :

public partial class Receipt
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Receipt()
    {
        this.Receipts1 = new HashSet<Receipt>();
        this.Seminars = new HashSet<Seminar>();
    }

    public int Id { get; set; }
    public System.DateTime IssueDate { get; set; }
    public Nullable<System.DateTime> DeliveryDate { get; set; }
    public Nullable<System.DateTime> PaymentDue { get; set; }
    public Nullable<short> CompanyId { get; set; }
    public Nullable<int> Number { get; set; }
    public Nullable<int> ClosedReceiptId { get; set; }
    public Nullable<decimal> ReturnedAmount { get; set; }
    public Nullable<short> ReturnTypeId { get; set; }

    public virtual Company Company { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Receipt> Receipts1 { get; set; }
    public virtual Receipt Receipt1 { get; set; }
    public virtual ReturnType ReturnType { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Seminar> Seminars { get; set; }
}

Сверху у меня есть ReceiptMetadata для аннотаций и [Required] полей:

[MetadataType(typeof(ReceiptMetadata))]
public partial class Receipt
{
}

public class ReceiptMetadata
{
    [Required]
    public int Number { get; set; }

    [Required]
    [DisplayName("Issue Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:G}")]
    public DateTime IssueDate { get; set; }

    [Required]
    [DisplayName("Payment Due")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd.MM.yyyy}")]
    public DateTime? PaymentDue { get; set; }

    [DisplayName("Return amount")]
    [DisplayFormat(DataFormatString = "{0:c}")]
    public Nullable<decimal> ReturnedAmount { get; set; }
}

И моя функция Create в контроллере выглядит следующим образом:

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Create([Bind(Include = "Id,IssueDate,DeliveryDate,PaymentDue,CompanyId,Number")]Receipt receipt, int? seminarId)
{
    if (seminarId == null)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return Json(new { Message = "ID is required" });
    }

    Seminar seminar = db.Seminars.Find(seminarId);

    if (seminar == null)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return Json(new { Message = "Seminar doesn't exist" });
    }

    int receiptNumber = db.Receipts.Where(r => r.CompanyId == receipt.CompanyId && r.ClosedReceiptId == null && r.IssueDate.Year == DateTime.Now.Year).Count() + 1;
    receipt.Number = receiptNumber;
    receipt.IssueDate = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.Now, TimeZoneInfo.Local.Id, "Central European Standard Time");

    if (ModelState.IsValid)
    {
        try
        {
            db.Receipts.Add(receipt);
            db.SaveChanges();

            seminar.ReceiptId = receipt.Id;
            db.Entry(seminar).State = EntityState.Modified;

            db.SaveChanges();

            GeneratePDF(receipt.Id, receipt.ReceiptNumber, receipt.CompanyId.ToString());
            return Json(new { receipt.Id, receipt.PDFLink, Action = "Create", Message = "Receipt successfully added! -> " }, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return Json(new { Message = ex.Message });
        }
    }

    Response.StatusCode = (int)HttpStatusCode.BadRequest;
    IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
    List<string> errorMessages = new List<string>();

    foreach (ModelError error in allErrors)
    {
        errorMessages.Add(error.ErrorMessage);
    }

    return Json(new { Message = errorMessages });
}

Я получаю сообщение об ошибке:

Поле Number является обязательным.

когда явно поле Number заполнено:

receipt.Number = receiptNumber;

на несколько строк до IsValid.

Может кто-нибудь поможет?

РЕДАКТИРОВАТЬ : это снимок экрана от отладки, ключи состояния модели полностью неверны:

Debugging image

1 Ответ

2 голосов
/ 08 мая 2020

ModelState уже оценен (и недействителен) при вводе вашего действия, установка свойства «Number» не приведет к повторной оценке модели. После установки свойства вам, возможно, придется вручную удалить его из ошибок модели, написав это:

ModelState.Remove("Number");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...