Soru MVC'deki modelde koşullu doğrulama


Bir kayıt için hem düzenleme hem de ekleme sayfası için kullandığım bir görünüm ve modelim var. İş gereksinimlerinden biri, belirli bir alanın düzenlemede değil, yeni bir alanda yapılması gerektiğidir. Aslen bu özel özellik önce, bu modele sahip olsaydı, modele şöyle bir şey ekledim:

[Required(ErrorMessage = "*")]
[Range(0.0, (double)decimal.MaxValue)]
[DisplayName("Cost")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public decimal ProposedCost { get; set; }

Ekleme formu ise gerekli mülkü kaldırmak veya bir düzenleme formu varsa eklemek istiyorum. Daha iyi bir yaklaşım nedir? Diğer tüm validasyonlar yukarıdaki gibi yapılır. Veya model durumunu değiştirebilir miyim? Düşünceler?

DÜZENLE

Açıklığa kavuşturmam gereken bir şey, henüz yeni bir maliyet eklemelerine izin verilmesidir.


16
2017-07-31 12:35


Menşei




Cevaplar:


MVC3 / .NET4 kullanıyorsanız, kullanabilirsiniz IValidatableObject Özellikle bu tür amaçlar için var.

Alıntı yapmak ScottGu,

... IValidatableObject arayüzü, model seviyesini gerçekleştirmenizi sağlar.   doğrulama ve doğrulama hata mesajlarını vermenizi sağlar   Genel modelin durumuna özel ....

Sen model gibi görüneceksin

public class MyViewModel : IValidatableObject
{
    public long? Id { get; set; }
    public decimal? ProposedCost { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
        if (Id != null && ProposedCost == 0) {
            yield return new ValidationResult("ProposedCost must be provided.");
        }
    }
}

ve sonra kontrolörde

[HttpPost]
public ActionResult Submit(MyViewModel model)
{
    if (!ModelState.IsValid) {
        //failed - report an error, redirect to action etc
    }
    //succeeded - save to database etc
}

Aksi takdirde en temiz çözüm, görünüm modellerini kullanmak olabilir - UpdateViewModel mülkiyet gerekli ve CreateViewModel gerekli değil.


33
2017-07-31 12:52



Bunu denedim, ancak önerilen bir maliyet olmadan hala bir düzenleme kaydı kaydedebiliyordu. Bir kesme noktası koymuş ve Validationresult'a isabet ediyordum. Düşünceler? - Seth
Kontrol ettiğine emin misin ModelState.IsValid? Bir örnek göstermek için cevabı güncelledim. Ayrıca dikkat edin ProposedCost ayarlamamıza izin verirsek, nullable olması gerekir. - andreister
Evet, bunu özledim, iyi yakalama. Eklenen diğer özellikler, otomatik olarak sahne arkasında bir müşteri tarafı kontrolü var. Neyse buna dokunabilir miyim? Bu elbette orijinal sorumun kapsamı dışında. - Seth
Bunu denedim ve yeni bir Doğrulama sonucu verebildim ancak benim "ModelState.IsValid" hala doğruydu ... Emin değilim. - eaglei22
o neden beğenmedi bazı nedenlerle verim kullanıyordu .. bu yüzden sadece IEnumerable <ValidationResult> kadar yeni dilenmiş ve aksi takdirde nesne boş veya döndü hatalar ekledi .. Bu MVC4 kullanarak çalıştı. - eaglei22


MVC Foolproof kütüphanesi var: http://foolproof.codeplex.com/

Örneğin, modelinizde bunun gibi bir şeye sahip olmanız gerekir:

[RequiredIfTrue("Required", ErrorMessage = "*")]
[Range(0.0, (double)decimal.MaxValue)]
[DisplayName("Cost")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public decimal ProposedCost { get; set; }

public bool Required { get; set; }

Daha sonra Required modelin hangi forma göre olduğuna göre.

Formu temsil etmek için formda gizli bir giriş alanına da ihtiyacınız olacaktır. Required Müşteri tarafında doğrulama yapmak istiyorsanız

Umarım yardımcı olur...


4
2017-07-31 12:52





Kullanabilirsiniz RequiredIf doğrulama özniteliği MVC Dayanıklılık Doğrulama projesi. Gereksinim duyduğunuz işlevselliği sağlamak için projelerde kullandım.

Bir alternatif kullanmak RemoteAttribute ve mantığı kendiniz bir yöntemle uygulayın.


3
2017-07-31 12:45



Ben şahsen beğenmiyorum RequiredIf güvenli değil çünkü yazmalısın [RequiredIf("SomeProperty", value, ...)]ve eğer derleyici sizi uyarmazsa SomeProperty yeniden adlandırılır, ancak eski ad özellikte kaldı - andreister
@andreister kullanabilirsiniz [RequiredIf(nameof(SomeProperty), value, ...)] Bu, zaman geçerliliğini derlemenizi sağlar ve yeniden adlandırılmasıyla başa çıkar. SomeProperty - James Culshaw
Çok doğru @JamesCulshaw - en sevdiğim C # 6 özelliklerinden biri, çünkü bu tam senaryoya yardımcı oluyor. - christophano
Evet, yorumum 2013'ten geldi ve şimdi sonunda nameof :) - andreister


Doğrulamayı şu şekilde deneyebilirsiniz:

ModelState.Remove("ProposedCost");

Veya modelinizi şu şekilde genişletirsiniz:

public class NewModeViewModel : EditModeViewModel
{
   public new decimal ProposedCost { get; set; }
}

ve düzenleme görünümüne geçilir.


1
2017-07-31 12:49