سؤال

لدي كيان طبقة مجال قياسية:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

التي لديها نوع من سمات التحقق من الصحة المطبقة:

public class Product
{
    public int Id { get; set; }

    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

كما ترون ، لقد صنعت هذه السمات تمامًا. ما هو إطار التحقق من الصحة (التحقق من NHibernate ، DataAntations ، التحقق من الصحة ، مصلحة القلعة ، وما إلى ذلك) المستخدمة هنا ليست مهمة.

في طبقة موكلي ، لدي أيضًا إعداد قياسي حيث لا أستخدم كيانات المجال بأنفسهم ، ولكن بدلاً من ذلك قم بتخطيطها إلى عرض النماذج (المعروفة أيضًا باسم DTO) التي تستخدمها طبقة العرض الخاصة بي:

public class ProductViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

دعنا نقول بعد ذلك أنني أريد أن يكون موكلي/عرضه قادرًا على إجراء بعض عمليات التحقق من مستوى الممتلكات الأساسية.

الطريقة الوحيدة التي أراها يمكنني القيام بذلك هي تكرار تعريفات التحقق من الصحة في كائن ViewModel:

public class ProductViewModel
{
    public int Id { get; set; }

    // validation attributes copied from Domain entity
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    // validation attributes copied from Domain entity
    [NotLessThan0]
    public decimal Price { get; set;}
}

من الواضح أن هذا ليس مرضيًا ، حيث لقد تكررت الآن من منطق الأعمال المتكرر (التحقق من صحة مستوى الممتلكات) في طبقة ViewModel (DTO).

إذن ما الذي يمكن فعله؟

على افتراض أنني أستخدم أداة أتمتة مثل Automapper لرسم خريطة كيانات النطاق الخاصة بي إلى DTOs ViewModel ، ألا يكون من الرائع أيضًا نقل منطق التحقق من الصحة إلى الخصائص المعينة إلى ViewModel أيضًا؟

الأسئلة هي:

1) هل هذه فكرة جيدة؟

2) إذا كان الأمر كذلك ، فهل يمكن القيام به؟ إذا لم يكن كذلك ، فما هي البدائل ، إن وجدت؟

أشكرك مقدما على المعلومات!

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم شيئًا يدعم DataAntations ، فيجب أن تكون قادرًا على استخدام فئة بيانات التعريف لاحتواء سمات التحقق من الصحة الخاصة بك:

public class ProductMetadata 
{
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

وأضفه في MetaDatatyPeatRive على كل من Contity و DTO:

[MetadataType(typeof(ProductMetadata))]
public class Product

و

[MetadataType(typeof(ProductMetadata))]
public class ProductViewModel

لن ينجح هذا خارج المربع مع جميع المصارقين - قد تحتاج إلى توسيع إطار التحقق من الصحة الخاص بك للاختيار لتنفيذ نهج مماثل.

نصائح أخرى

الغرض من التحقق من الصحة هو التأكد من أن البيانات الواردة في تطبيقك تلبي معايير معينة ، مع وضع ذلك في الاعتبار ، فإن المكان الوحيد الذي يجعل من المنطقي التحقق من قيود الممتلكات ، مثل تلك التي حددتها هنا ، في النقطة التي تقبل فيها البيانات من ملف مصدر غير موثوق به (أي المستخدم).

يمكنك استخدام شيء مثل "نمط المال" لرفع التحقق من الصحة في نظام نوع المجال الخاص بك واستخدام أنواع المجال هذه في نموذج العرض حيث يكون من المنطقي. إذا كان لديك التحقق من صحة أكثر تعقيدًا (أي أنك تعبر عن قواعد العمل التي تتطلب معرفة أكبر من تلك المعبر عنها في خاصية واحدة) ، فهذه تنتمي إلى طرق في نموذج المجال الذي يطبق التغييرات.

باختصار ، ضع سمات التحقق من صحة البيانات على نماذج العرض الخاصة بك واتركها من نماذج المجال الخاصة بك.

اتضح أن السيارات قد تكون قادرة على القيام بذلك من أجلنا تلقائيًا ، وهو أفضل سيناريو للحالة.

مستخدمي السيارات: نقل صحة سمات ViewModel؟
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302؟lnk=gst&q=validation#db4e7f6c93a77302

لم أتجول في تجربة الحلول المقترحة هناك ، لكنني أعتزم قريبًا.

لماذا لا تستخدم واجهة للتعبير عن نيتك؟ على سبيل المثال:

public interface IProductValidationAttributes {
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    string Name { get; set; }

    [NotLessThan0]
    decimal Price { get; set;}
}

إذا كنت تستخدم كيانات المجال المكتوبة باليد ، فلماذا لا تضع كيانات المجال الخاصة بك في تجميعها الخاص واستخدام نفس التجميع على العميل والخادم. يمكنك إعادة استخدام نفس عمليات التحقق.

لقد كنت أفكر في هذا أيضًا لفترة من الوقت الآن. أنا أفهم تمامًا رد براد. ومع ذلك ، لنفترض أنني أرغب في استخدام إطار عمل آخر مناسب للتعليق على كل من كيانات المجال ونماذج عرض.

الحل الوحيد الذي يمكنني التوصل إليه على الورق الذي لا يزال يعمل مع السمات هو إنشاء سمة أخرى "النقاط" إلى خاصية كيان المجال الذي تعكسه في نموذج العرض الخاص بك. هذا مثال:

// In UI as a view model.
public class UserRegistration {
  [ValidationDependency<Person>(x => x.FirstName)]
  public string FirstName { get; set; }

  [ValidationDependency<Person>(x => x.LastName)]
  public string LastName { get; set; }

  [ValidationDependency<Membership>(x => x.Username)]
  public string Username { get; set; }

  [ValidationDependency<Membership>(x => x.Password)]
  public string Password { get; set; }
}

يمكن تمديد إطار عمل مثل XVAL للتعامل مع هذه السمة الجديدة وتشغيل سمات التحقق من الصحة على خاصية فئة التبعية ، ولكن مع قيمة خاصية نموذج العرض الخاص بك. أنا فقط لم يكن لدي وقت لتجسيد هذا أكثر.

أي أفكار؟

بادئ ذي بدء ، لا توجد فكرة عن كيان المجال "القياسي". بالنسبة لي ، لا يوجد لدى كيان المجال القياسي أي مستقلين للبدء. إذا اتبعت هذا النهج ، فيمكنك الحصول على واجهة برمجة تطبيقات أكثر فائدة ، فهذا ينقل شيئًا عن مجالك. لذلك ، يمكنك الحصول على خدمة تطبيق تقوم بمعالجة DTO الخاصة بك ، ويقوم بإنشاء أوامر يمكنك تنفيذها مباشرة ضد كائنات المجال الخاصة بك ، مثل setContactInfo و ChangePric المستخدم. لا يزال بإمكانك ترك سماتك على خصائص DTO للتحقق من صحة مستوى السمة/الخاصية البسيطة. لأي شيء آخر ، استشر المجال الخاص بك. وحتى إذا كان هذا هو تطبيق CRUD ، فإنني أتجنب تعريض كيانات المجال الخاصة بي لطبقة العرض.

عدم اعطاء رأي: أعلم أن هذه مناقشة قديمة ، لكنها كانت الأقرب إلى ما كنت أبحث عنه: الحفاظ على جفاف من خلال إعادة استخدام سمات التحقق من الصحة. آمل ألا يكون هذا بعيدًا عن السؤال الأصلي.

في وضعي ، أردت أن أجعل رسائل الخطأ متوفرة في .NET Views وفي ViewModels الأخرى. كياناتنا لديها القليل من المنطق التجاري وتستهدف بشكل أساسي تخزين البيانات. بدلاً من ذلك ، لدينا عرض ViewModel كبير مع التحقق من الصحة ومنطق العمل هل أرغب في إعادة استخدام رسائل الخطأ. نظرًا لأن المستخدمين يتم إدراكهم فقط برسائل الخطأ ، أجد أن هذا مناسب لأن هذا أمر مهم للحفاظ عليه بسهولة.

لم أتمكن من العثور على طريقة ممكنة لإزالة المنطق من موزود ViewModels الجزئية ، لكنني وجدت طريقة لنقل نفس الخاطئ ، بحيث يمكن الحفاظ عليها من نقطة واحدة. نظرًا لأن الأخطاء مرتبطة بالمنظر ، يمكن أن تكون جزءًا من ViewModel. مقدار ثابتتعتبر S أعضاء ثابتين ، لذا تحديد رسائل الخطأ كسلسلة عامة مقدار ثابتالنمل ، يمكننا الوصول إليها خارج الفصل.

public class LargeViewModel
{
    public const string TopicIdsErrorMessage = "My error message";

    [Required(ErrorMessage = TopicIdsErrorMessage)]
    [MinimumCount(1, ErrorMessage = TopicIdsErrorMessage)]
    [WithValidIndex(ErrorMessage = TopicIdsErrorMessage)]
    public List<int> TopicIds { get; set; }
}

public class PartialViewModel
{
    [Required(ErrorMessage = LargeViewModel.TopicIdsErrorMessage]
    public List<int> TopicIds { get; set; }
}

في مشروعنا ، كنا نستخدم HTML المخصص لقوائم القائمة المنسدلة ، بحيث لا يمكننا استخدام @html.editorfor المساعد في الحلاقة ، وبالتالي لم نتمكن من استخدام التحقق من الصحة غير المزعجة. مع توفر رسالة الخطأ ، يمكننا الآن تطبيق السمات اللازمة:

    @(Html.Kendo().DropDownList()
        .Name("TopicIds")
        .HtmlAttributes(new {
            @class = "form-control",
            data_val = "true",
            data_val_required = SupervisionViewModel.TopicIdsErrorMessage
        })
    )

تحذير: قد تحتاج إلى إعادة ترجمة جميع المشاريع ذات الصلة التي تعتمد على قيم const...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top