NullReferenceException และดูคุณสมบัติการนำทางแบบจำลอง

ฉันกำลังดิ้นรนหาวิธีจัดการกับค่าว่างในโมเดลมุมมองของฉัน ค่าเหล่านี้บางส่วนซ้อนกันหรือออบเจ็กต์การนำทางภายในโมเดลของฉัน ฉันจะป้องกันไม่ให้มุมมองของฉันเกิดข้อผิดพลาดในการอ้างอิงที่เป็นโมฆะโดยไม่ต้องใส่ตรรกะเข้าไปในมุมมองได้อย่างไร ดูเหมือนง่ายแต่มันคือจุดสิ้นสุดของวัน

ฉันมีโมเดลมุมมองพร้อมคุณสมบัติการนำทางบางอย่างเช่น:

ViewModel.cs

public class ViewModel
{
  public ViewModel () {}
  public ViewModel (Contact contact, IDemographicService demographicService)
         : this()
  {
    Id = contact.Id;
    Name = contact.Name;
    EthnicityId = contact.EthnicityId;
    if(EthnicityId > 0 || EthnicityId != null)
       Ethnicity = deomographicService.GetEthnicityById((int)contact.EthnicityId);
  }
  public int Id {get;set;}
  public string Name {get;set;}
  public int? EthnicityId {get;set;}
  public Ethnicity Ethnicity {get;set;}
}

ฉันจะข้ามตัวควบคุมเพราะนั่นไม่ใช่จุดสำคัญของคำถามของฉัน (ฉันรู้ว่าตรรกะสามารถอยู่ในคอนโทรลเลอร์ได้ แต่ฉันเลือกที่จะใส่ไว้ใน ViewModel)

MyView.cshtml

@model ViewModel
<ul>
<li>@Model.Name</li>
<li>@Model.Ethnicity.Name</>//This is the null reference.
</ul>

ฉันเดาว่าฉันสามารถกำหนดได้เฉพาะสตริง "EthnicityName" (และถ้า null ส่งคืน null) แทนที่จะเป็นวัตถุทั้งหมด แต่มีกรณีที่ฉันต้องการมากกว่าหนึ่งคุณสมบัติจากวัตถุ Ethnicity สิ่งนี้จะกำจัด Ethnicity ไม่ว่าจะอยู่ในโมเดลมุมมอง ตัวควบคุม หรือมุมมอง สรุปแล้วฉันควรทำอย่างไรกับ null.null? นิ่งงัน. ขอบคุณ.


person trevorc    schedule 05.03.2011    source แหล่งที่มา


คำตอบ (3)


ฉันแทบจะไม่คิดว่ามันเป็นสิ่งที่แย่มากที่จะเพิ่ม "ตรรกะ" เพื่อทำความเข้าใจค่าว่าง ตรรกะดังกล่าวเป็นส่วนหนึ่งของโมเดลออบเจ็กต์ .NET พื้นฐาน มันไม่ใช่ตรรกะทางธุรกิจ

อย่างไรก็ตาม คุณสามารถเพิ่มหนึ่งคุณสมบัติให้กับโมเดลสำหรับแต่ละคุณสมบัติของประเภท Ethnicity ที่คุณต้องการให้มองเห็นได้ในโมเดล:

public Ethnicity Ethnicity {get;set;}
public string EthnicityName {
    get {return Ethnicity == null ? String.Empty : Ethnicity.Name;}
    set {if (Ethnicity != null) {Ethnicity.Name = value;}}
}
public int EthnicityCode {
    get {return Ethnicity == null ? 0 : Ethnicity.Code;}
    set {if (Ethnicity != null) {Ethnicity.Code = value;}}
}

แล้ววิวก็ไม่มีงานทำเลย

โปรดทราบว่าฉันคิดว่าการมอบหมายประเภทนี้ก็โอเค เมื่อเทียบกับการจัดรูปแบบ ฉันจะไม่เพิ่มคุณสมบัติให้กับโมเดลที่มีจุดประสงค์เพื่อการจัดรูปแบบเท่านั้น

person John Saunders    schedule 05.03.2011
comment
ขอบคุณจอห์น คำตอบของคุณสอดคล้องกับสิ่งที่ฉันคิดว่าจะต้องทำ แม้ว่าตัวอย่างของฉันจะค่อนข้างง่าย แต่โปรเจ็กต์ของฉันก็รวมอ็อบเจ็กต์ 'ที่ซ้อนกัน' อื่น ๆ ที่มีคุณสมบัติจำนวนมาก โดยที่การกำหนดคุณสมบัติทุกรายการไม่เป็นไปตามวัตถุประสงค์ของโมเดลมุมมอง ในกรณีประเภทนี้ คำสั่ง else ที่สร้างวัตถุว่างจะเป็น verboten หรือไม่ เช่น else LargeObject = new LargeObject(); วิธีนี้มุมมองของฉันที่มี @Model.LargeObject.Property จะไม่ทำให้เกิดค่าว่าง ฉันเกลียดค่าว่าง แต่ฉันถูกบังคับให้จัดการกับมัน - person trevorc; 05.03.2011
comment
ปล. ฉันหมายถึงตรรกะในมุมมอง - person trevorc; 05.03.2011
comment
@name: ฉันไม่ใช่ผู้เชี่ยวชาญ MVC แม้ว่าฉันจะมีแนวคิดทั่วไปในแง่ของการแยกข้อกังวลก็ตาม ฉันไม่คิดว่านี่ถือเป็นข้อกังวลแยกต่างหาก ฉันจะถามคำถามว่า ทำไม ฉันจึงมีค่าว่างเหล่านั้น - ความหมายคืออะไร พวกเขาเป็นตัวแทนของโมเดลอะไร? - person John Saunders; 07.03.2011

ดูเหมือนว่าเป็นปัญหาการออกแบบคลาส ไม่ใช่ปัญหา View/Model คุณมีคลาสที่ประกาศว่าจะให้ Ethnicity ซึ่งเป็นส่วนหนึ่งของสถานะที่ไม่เปลี่ยนรูปเมื่อเริ่มต้น อย่างไรก็ตาม เมื่อคุณสร้างอ็อบเจ็กต์จริง ๆ คุณไม่ได้รับประกันผู้บริโภคในคลาสนั้น ฉันคิดว่าโซลูชัน @John Saunders ใช้งานได้ แต่ฉันยินดีที่จะสร้างอินสแตนซ์อินสแตนซ์ Default Ethnicity เป็นสมาชิกแบบคงที่ในประเภท Ethnicity แล้วส่งคืนสิ่งนั้น คุณสมบัติ Name ของค่าเริ่มต้นนั้นจะส่งคืนคำตอบที่เหมาะสมสำหรับภาษาสำหรับ "None Supplied" หรืออะไรทำนองนั้น

person Ritch Melton    schedule 05.03.2011
comment
Ritch ฉันเข้าใจสิ่งที่คุณพูดและเป็นสิ่งที่ฉันพิจารณา แต่ความเป็นจริงของโครงการของฉัน (ตัวอย่างของฉันเป็นเรื่องง่ายสำหรับการโพสต์) คือฉันมีกราฟวัตถุขนาดใหญ่ที่น่าเสียดายที่อาจเป็นโมฆะได้ การเรียกร้องค่ารักษาพยาบาลเป็นไปตามผู้เขียนทุนสนับสนุนและตัดสินใจว่าโครงการนำร่องด้านสาธารณสุขของน้องชายของเขาดูดีกว่า - person trevorc; 05.03.2011
comment
การสร้างความแตกต่างระหว่าง null และ Empty เป็นพฤติกรรมของโมเดล - person Ritch Melton; 05.03.2011
comment
แต่จากตัวอย่างของฉัน เชื้อชาติไม่ว่างเปล่า มันเป็นโมฆะ ฉันไม่สามารถควบคุมได้ว่าผู้ใช้ไม่ได้เลือกเชื้อชาติหรือไม่ ดังนั้น Ethnicity.Name == null.null คำตอบของจอห์นข้างต้นช่วยแก้ปัญหานี้ได้ เว้นแต่คุณจะมีวัตถุขนาดใหญ่ที่มีคุณสมบัติมากมาย - person trevorc; 05.03.2011
comment
มันแก้ปัญหาได้ แต่สร้างการพึ่งพาใน ViewModel สำหรับทุกคุณสมบัติในคลาส Ethnicity ลองจินตนาการว่าคุณมีคุณสมบัติ 50 หรือ 100 รายการที่จะส่งต่อในลักษณะนั้น จะเกิดอะไรขึ้นหากคุณเปลี่ยนประเภทของคุณสมบัติอย่างใดอย่างหนึ่ง การมีเพศสัมพันธ์แบบนั้นไม่จำเป็นและทำให้ทุกอย่างเปราะบาง ฉันจะเพิ่มตัวอย่าง แต่คุณดูพอใจกับคำตอบของ @John ดังนั้นฉันจะปล่อยมันไป - person Ritch Melton; 05.03.2011
comment
ฉันเดาว่าฉันอธิบายตัวเองได้ไม่ดีนัก ความคิดเห็นล่าสุดของคุณอธิบายถึงสถานการณ์ที่แท้จริงของฉันอย่างแน่นอน ฉันเห็นด้วย 100% กับสิ่งที่คุณพูดเกี่ยวกับอสังหาริมทรัพย์ 50 หรือ 100 แห่ง ฉันเดาว่าคำถามของฉันคือ: หาก Ethnicity มีคุณสมบัติ 50 รายการที่อาจดูหรือไม่มีการดู (@Model.Ethnicity.Property1 ฯลฯ) ในมุมมอง ถ้าอย่างนั้นคำสั่ง if/else ที่สร้างวัตถุ Ethnicity ที่ว่างเปล่าเพื่อตอบสนองมุมมองจะเป็นแนวทางปฏิบัติที่ไม่ดีหรือไม่ นั่นเป็นทางออกเดียวที่ฉันนึกถึงคำตอบของ sans John และการพึ่งพาที่คุณอธิบาย - person trevorc; 05.03.2011
comment
ไม่ if/else ไม่ใช่แนวปฏิบัติที่ไม่ดี เมื่อสร้าง VM หากการอ่านในกลุ่มชาติพันธุ์เป็นโมฆะ ให้กำหนดคุณสมบัติ Ethnicity ของ VM ให้กับ Ethnicity.Empty เป็นโซลูชันที่ฉันแนะนำ - person Ritch Melton; 05.03.2011

คุณอาจสนใจที่จะใช้อินเทอร์เฟซ IDataErrorInfo บน ViewModel ของคุณ ดังนั้นการใช้ตรรกะการตรวจสอบความถูกต้องที่นั่น แทนที่จะใช้คุณสมบัติ getter/setters โดยตรง

person Nano Taboada    schedule 11.04.2011