এএসপি.নেট এমভিসি শর্তসাপেক্ষ বৈধতা


129

মডেলটিতে শর্তসাপেক্ষ বৈধতা করতে ডেটা টীকাগুলি কীভাবে ব্যবহার করবেন?

উদাহরণস্বরূপ, আসুন আমরা বলি যে আমাদের কাছে নিম্নলিখিত মডেল রয়েছে (ব্যক্তি এবং প্রবীণ):

public class Person
{
    [Required(ErrorMessage = "*")]
    public string Name
    {
        get;
        set;
    }

    public bool IsSenior
    {
        get;
        set;
    }

    public Senior Senior
    {
        get;
        set;
    }
}

public class Senior
{
    [Required(ErrorMessage = "*")]//this should be conditional validation, based on the "IsSenior" value
    public string Description
    {
        get;
        set;
    }
}

এবং নিম্নলিখিত ভিউ:

<%= Html.EditorFor(m => m.Name)%>
<%= Html.ValidationMessageFor(m => m.Name)%>

<%= Html.CheckBoxFor(m => m.IsSenior)%>
<%= Html.ValidationMessageFor(m => m.IsSenior)%>

<%= Html.CheckBoxFor(m => m.Senior.Description)%>
<%= Html.ValidationMessageFor(m => m.Senior.Description)%>

আমি "সিনিয়র" বিবরণ "সম্পত্তি শর্তসাপেক্ষে প্রয়োজনীয় ক্ষেত্র হতে চাই" ইসসিনিয়ার "যথাযথ (সত্য -> প্রয়োজনীয়) নির্বাচনের উপর ভিত্তি করে। ডেটা টীকা সহ এএসপি.নেট এমভিসি 2 এ শর্তযুক্ত বৈধতা কীভাবে প্রয়োগ করা যায়?


1
আমি সম্প্রতি অনুরূপ প্রশ্ন জিজ্ঞাসা করেছি: স্ট্যাকওভারফ্লো
দারিন দিমিত্রোভ

আমি বিভ্রান্ত কোনও Seniorঅবজেক্ট সর্বদা সিনিয়র থাকে, তবে ইসসিনিয়ার কেন সেই ক্ষেত্রে মিথ্যা হতে পারে। Person.IsSeniorমিথ্যা হলে আপনার কেবল 'ব্যক্তি.সিনিয়র' সম্পত্তি নালাগুলির প্রয়োজন হয় না । বা কেন বাস্তবায়ন IsSeniorনিম্নরূপ সম্পত্তি: bool IsSenior { get { return this.Senior != null; } }
স্টিভেন

স্টিভেন: "ইসসেনিয়ার" ভিউতে চেকবক্স ফিল্ডে অনুবাদ করে। যখন ব্যবহারকারী "ইসসিনিয়ার" চেকবক্সটি পরীক্ষা করে তখন "সিনিয়র। বিবরণ" ক্ষেত্রটি বাধ্যতামূলক হয়ে যায়।
পিটার স্টিগনার

দারিন দিমিত্রভ: বেশ সাজান, তবে বেশ নয়। আপনি দেখুন, আপনি কীভাবে অর্জন করবেন যে ত্রুটি বার্তা নির্দিষ্ট ক্ষেত্রের সাথে সংযুক্ত? আপনি যদি অবজেক্ট পর্যায়ে বৈধতা প্রদান করেন তবে আপনি অবজেক্ট পর্যায়ে একটি ত্রুটি পাবেন। সম্পত্তি স্তরে আমার ত্রুটি দরকার।
পিটার স্টিগনার

উত্তর:


150

এমভিসি 3 তে শর্তাধীন বৈধতা বিধি যুক্ত করার আরও অনেক ভাল উপায় আছে; আপনার মডেলটি উত্তরাধিকার সূত্রে প্রাপ্ত IValidatableObjectএবং Validateপদ্ধতিটি প্রয়োগ করুন :

public class Person : IValidatableObject
{
    public string Name { get; set; }
    public bool IsSenior { get; set; }
    public Senior Senior { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
        if (IsSenior && string.IsNullOrEmpty(Senior.Description)) 
            yield return new ValidationResult("Description must be supplied.");
    }
}

এএসপি.নেট এমভিসি 3 (পূর্বরূপ 1) উপস্থাপনে আরও পড়ুন ।


যদি সম্পত্তি "ইনট" প্রকারের হয় তবে এর মান প্রয়োজন, ক্ষেত্রটি পূরণ করুন,
বৈধতা কার্যকর

2
দুর্ভাগ্যক্রমে, মাইক্রোসফ্ট এটিকে ভুল স্তরটিতে ফেলেছে - বৈধতা হ'ল ব্যবসায়িক যুক্তি এবং এই ইন্টারফেসটি সিস্টেমটিতে রয়েছে e ওয়েবে ডিএলএল। এটি ব্যবহার করতে, আপনাকে আপনার ব্যবসায়ের স্তরটিকে উপস্থাপনা প্রযুক্তির উপর নির্ভরশীলতা দিতে হবে।
নাইটওয়েল 888

7
যদি আপনি এটি বাস্তবায়ন আপনাকে যা করতে - পূর্ণ উদাহরণ দেখতে falconwebtech.com/post/...
viperguynaz

4
falconwebtech.com/post/... - এই @viperguynaz কাজ করছে না
Smit প্যাটেলের

1
@ রেলাভলেস আপনার কল করা উচিত ModelState.IsValid- সরাসরি
বৈধতা

63

কন্ট্রোলার দ্বারা থাকা "মডেলস্টেট" অভিধানটি পরিচালনা করে আমি এটি সমাধান করেছি contained মডেলস্টেট অভিধানে বৈধ হওয়া উচিত এমন সমস্ত সদস্যকে অন্তর্ভুক্ত করা হয়েছে।

সমাধান এখানে:

সম্পত্তি স্তরের ত্রুটি বার্তা বার্তা বজায় রাখার জন্য যদি আপনাকে কোনও ক্ষেত্রের উপর ভিত্তি করে শর্তসাপেক্ষ বৈধতা প্রয়োগ করতে হয় (যেমন, যদি এ = সত্য, তবে বি প্রয়োজন হয়) তবে আপনি এটি অর্জন করতে পারেন "মডেলস্টেট" পরিচালনা করে, এগুলি থেকে কেবল অযাচিত বৈধতাগুলি সরিয়ে।

... কিছু ক্লাসে ...

public bool PropertyThatRequiredAnotherFieldToBeFilled
{
  get;
  set;
}

[Required(ErrorMessage = "*")] 
public string DepentedProperty
{
  get;
  set;
}

... ক্লাস অব্যাহত ...

... কিছু নিয়ামক পদক্ষেপে ...

if (!PropertyThatRequiredAnotherFieldToBeFilled)
{
   this.ModelState.Remove("DepentedProperty");
}

...

এটি দিয়ে আমরা শর্তসাপেক্ষ বৈধতা অর্জন করি, অন্য সমস্ত কিছু একই রেখে চলেছি।


হালনাগাদ:

এটি আমার চূড়ান্ত বাস্তবায়ন: আমি মডেলটিতে একটি ইন্টারফেস ব্যবহার করেছি এবং ক্রিয়া বৈশিষ্ট্য যা মডেলটিকে বৈধতা দেয় যা उक्त ইন্টারফেস প্রয়োগ করে। ইন্টারফেসটি বৈধতা (মডেলস্টেটডোরেশন মডেলস্টেট) পদ্ধতি নির্ধারণ করে। ক্রিয়াকলাপের বৈশিষ্ট্যটি কেবল আইভিডিয়েটারসোমথিং-এ ভ্যালিডেট (মডেলস্টেট) কল করে।

আমি এই উত্তরটি জটিল করতে চাইনি, তাই আমি চূড়ান্ত বাস্তবায়নের বিশদটি উল্লেখ করিনি (যা শেষে, উত্পাদন কোডের ক্ষেত্রে)।


17
খারাপ দিকটি হ'ল আপনার বৈধতা যুক্তির একটি অংশ মডেলটিতে এবং অন্য অংশটি নিয়ামক (গুলি) এ অবস্থিত।
ক্রিস্টফ ক্লেস

অবশ্যই এটি প্রয়োজন হয় না। আমি সর্বাধিক প্রাথমিক উদাহরণটি দেখাই। আমি মডেলটিতে ইন্টারফেস এবং ক্রিয়াকলাপের সাথে এটি কার্যকর করেছি যা মডেলকে বৈধ করে যা উল্লিখিত ইন্টারফেস প্রয়োগ করে। ইন্টারফেসটি বৈধতা (মডেলস্টেটডোরিয়াল মডেলস্টেট) পদ্ধতিটি স্থির করে। সুতরাং শেষ পর্যন্ত আপনি মডেল সমস্ত বৈধতা না। যাইহোক, ভাল পয়েন্ট।
পিটার স্টিগনার

এমভিসি দলটি বাক্সের বাইরে আরও ভাল কিছু তৈরি না করা পর্যন্ত আমি মাঝামাঝি সময়ে এই পদ্ধতির সরলতা পছন্দ করি। তবে কী আপনার ক্লায়েন্ট সাইডের বৈধতা সক্ষম করার সমাধান সমাধান করে ??
হারুন

2
অ্যারোন: আমি খুশি যে আপনি সমাধানটি পছন্দ করেছেন, তবে দুর্ভাগ্যক্রমে এই সমাধানটি ক্লায়েন্টের পক্ষের যাচাইকরণের সাথে কাজ করে না (প্রতিটি বৈধকরণের বৈশিষ্ট্যের জন্য এটির জাভাস্ক্রিপ্ট বাস্তবায়ন প্রয়োজন)। আপনি "রিমোট" অ্যাট্রিবিউটটি দিয়ে নিজেকে সহায়তা করতে পারেন, তাই এটির বৈধতা দেওয়ার জন্য কেবলমাত্র আজাক্স কলটি নির্গত হবে।
পিটার স্টিগনার

আপনি কি এই উত্তরটি প্রসারিত করতে সক্ষম? এটি কিছুটা অর্থবহ করে, তবে আমি এটি নিশ্চিত করতে চাই যে আমি এটিতে স্ফটিক। আমি এই সঠিক পরিস্থিতির মুখোমুখি হয়েছি এবং আমি এটি সমাধান করতে চাই।
রিচার্ড বি

36

গতকাল আমারও একই সমস্যা ছিল তবে আমি এটি খুব পরিষ্কার উপায়ে করেছি যা ক্লায়েন্টের পক্ষে এবং সার্ভারের দিকের বৈধতা উভয়ের পক্ষে কাজ করে।

শর্ত: মডেলটিতে অন্যান্য সম্পত্তির মানের উপর ভিত্তি করে, আপনি আরও একটি সম্পত্তি প্রয়োজনীয় করতে চান। কোডটি এখানে

public class RequiredIfAttribute : RequiredAttribute
{
    private String PropertyName { get; set; }
    private Object DesiredValue { get; set; }

    public RequiredIfAttribute(String propertyName, Object desiredvalue)
    {
        PropertyName = propertyName;
        DesiredValue = desiredvalue;
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        Object instance = context.ObjectInstance;
        Type type = instance.GetType();
        Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (proprtyvalue.ToString() == DesiredValue.ToString())
        {
            ValidationResult result = base.IsValid(value, context);
            return result;
        }
        return ValidationResult.Success;
    }
}

এখানে সম্পত্তির নামটি সেই সম্পত্তি যা আপনি নিজের শর্তটি তৈরি করতে চান ডিজায়ারভ্যালিউটি সম্পত্তি সম্পত্তি (বিশেষায়িত) এর নির্দিষ্ট মান যার জন্য আপনার অন্যান্য সম্পত্তি প্রয়োজনীয়তার জন্য বৈধ করতে হবে

বলুন আপনার নিম্নলিখিত আছে

public class User
{
    public UserType UserType { get; set; }

    [RequiredIf("UserType", UserType.Admin, ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(ResourceString))]
    public string Password
    {
        get;
        set;
    }
}

সর্বশেষে তবে কমপক্ষে নয়, আপনার অ্যাট্রিবিউটের জন্য অ্যাডাপ্টারটি রেজিস্টার করুন যাতে এটি ক্লায়েন্টের পাশের বৈধতা করতে পারে (আমি এটিকে Global.asax, অ্যাপ্লিকেশন_স্টার্টে রেখেছি)

 DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute),typeof(RequiredAttributeAdapter));

এটিই ছিল মূল প্রারম্ভিক বিন্দু মিরোপ্রসেসর্ডেভ.ব্লগস্পট.কম
ড্যান হুনেক্স

এসপ নেটওয়্যার এমভিসি 2 তে কি কোনও সমতুল্য সমাধান রয়েছে? যাচাইকরণের ফলাফল, বৈধকরণ কনটেক্সট ক্লাসগুলি এসপ নেটওয়্যার এমভিসি 2 (। নেট ফ্রেমওয়ার্ক 3.5) এ উপলব্ধ নয়
ব্যবহারকার_ এমভিসি

2
লিঙ্কযুক্ত ব্লগ হিসাবে এটি কেবল সার্ভার-সাইডে কাজ করে
পাকম্যান

2
আমি এমভিসি 5 এর সাথে ক্লায়েন্টের পক্ষে এটির কাজটি পরিচালনা করতে সক্ষম হয়েছি, তবে ক্লায়েন্টে এটি পছন্দসইটি ছাঁটাই করে দেওয়াই ডিভাইসডভ্যালু যাই হোক না কেন।
গীতাঙ্গা

1
@ ড্যান হুনেক্স: এমভিসি 4 তে আমি ক্লায়েন্টের পক্ষে সঠিকভাবে কাজ করতে সক্ষম হইনি এবং এটি ডিজায়ারভ্যালু যা-ই হোক না কেন এটি বৈধতা প্রকাশ করে। কোন সাহায্য pls?
জ্যাক

34

আমি এই আশ্চর্যজনক নুগেটটি ব্যবহার করেছি যা গতিময় টীকা এক্সপ্রেসিভঅনোটেশনগুলি করে

আপনি যে যুক্তিটির স্বপ্ন দেখতে পারেন তা যাচাই করতে পারেন:

public string Email { get; set; }
public string Phone { get; set; }
[RequiredIf("Email != null")]
[RequiredIf("Phone != null")]
[AssertThat("AgreeToContact == true")]
public bool? AgreeToContact { get; set; }

3
এক্সপ্রেসিভ অ্যানোটেশন গ্রন্থাগারটি এখানে সমস্ত উত্তরের সবচেয়ে নমনীয় এবং জেনেরিক সমাধান। ভাগ করে নেওয়ার জন্য ধন্যবাদ!
সুধাংশু মিশ্র

2
আমি একটি দৃ day় দিনের জন্য সমাধান সন্ধান করার চেষ্টা করে আমার মাথা ঘুরছি। এক্সপ্রেসিভ অ্যানোটেশনগুলি আমার কাছে এটি ঠিক হয়ে গেছে!
কেভারম্যান

এক্সপ্রেসিভ অ্যানোটেশন লাইব্রেরি দুর্দান্ত!
ডগ নুডসেন

1
এটির ক্লায়েন্ট সাইড সাপোর্টও রয়েছে!
নেটট্রেস

1
.NET কোর এর জন্য কোনও সমর্থন নেই এবং এটি ঘটবে বলে মনে হচ্ছে না।
gosr

18

আপনি মডেলস্টেট থেকে ত্রুটিগুলি সরিয়ে শর্তাধীন বৈধতা অক্ষম করতে পারেন:

ModelState["DependentProperty"].Errors.Clear();


6

বাক্সের বাইরে এখন একটি কাঠামো রয়েছে যা শর্তসাপেক্ষ বৈধতা (অন্যান্য হ্যান্ডি ডেটা টীকাটি যাচাইয়ের মধ্যে) করে: http://foolproof.codeplex.com/

বিশেষত, [আবশ্যকআইফট্রু ("ইসসেনিয়ার")] যাচাইকারীকে একবার দেখুন। আপনি যে সম্পত্তিটি যাচাই করতে চান তার উপর সরাসরি এটি রেখে দেন, তাই আপনি "সিনিয়র" সম্পত্তির সাথে সম্পর্কিত হওয়ার সাথে বৈধতা ত্রুটির পছন্দসই আচরণ পান।

এটি একটি নিউগেট প্যাকেজ হিসাবে উপলব্ধ।


3

আপনার ব্যক্তি পর্যায়ে বৈধতা অর্জন করতে হবে, সিনিয়র স্তরে নয়, বা সিনিয়র এর অবশ্যই তার পিতামাতার সাথে কোনও রেফারেন্স থাকতে হবে। আমার কাছে মনে হচ্ছে আপনার একটি স্ব বৈধতা প্রক্রিয়া দরকার যা ব্যক্তির উপর বৈধতা সংজ্ঞা দেয়, এর কোনও বৈশিষ্ট্যের উপর নয়। আমি নিশ্চিত নই, তবে আমার মনে হয় না যে ডেটাঅ্যানোটেশনগুলি এটিকে বাক্সের বাইরে সমর্থন করে। আপনি Attributeযা নিজের তৈরি করতে পারেন যা থেকে উদ্ভূত তা শ্রেণিবদ্ধ ValidationAttributeস্তরে সজ্জিত হতে পারে এবং পরবর্তীতে একটি কাস্টম ভ্যালিডেটার তৈরি করুন যা সেই শ্রেণী-স্তরের বৈধতা দৌড়ানোর অনুমতি দেয়।

আমি জানি বৈধতা অ্যাপ্লিকেশন ব্লক বাক্সের বাইরে স্ব-যাচাইকরণ সমর্থন করে, তবে ভিএবি-র একটি দুর্দান্ত খাড়া শেখার বক্ররেখা রয়েছে। তবুও, ভ্যাব ব্যবহার করে এখানে একটি উদাহরণ দেওয়া হয়েছে:

[HasSelfValidation]
public class Person
{
    public string Name { get; set; }
    public bool IsSenior { get; set; }
    public Senior Senior { get; set; }

    [SelfValidation]
    public void ValidateRange(ValidationResults results)
    {
        if (this.IsSenior && this.Senior != null && 
            string.IsNullOrEmpty(this.Senior.Description))
        {
            results.AddResult(new ValidationResult(
                "A senior description is required", 
                this, "", "", null));
        }
    }
}

"আপনাকে ব্যক্তি পর্যায়ে বৈধতা দেওয়া দরকার, সিনিয়র লেভেলে নয়" হ্যাঁ এটি একটি বিকল্প, তবে ত্রুটিটি নির্দিষ্ট ক্ষেত্রের সাথে যুক্ত করার দক্ষতাটি আপনি সরিয়ে দিয়েছেন, এটি সিনিয়র অবজেক্টে প্রয়োজনীয়।
পিটার স্টিগনার

3

আমার একই সমস্যা ছিল, [প্রয়োজনীয়] বৈশিষ্ট্যের একটি সংশোধন প্রয়োজন - HTTP অনুরোধের নির্ভরতার ক্ষেত্রে প্রয়োজনীয় ক্ষেত্র তৈরি করুন Dan সমাধান ড্যান হুনেক্স উত্তরের অনুরূপ ছিল, তবে তার সমাধানটি সঠিকভাবে কার্যকর হয়নি (মন্তব্য দেখুন)। আমি আপত্তিজনক বৈধতা ব্যবহার করি না, কেবল মাইক্রোসফ্ট এমভিসিভিলেশন.জেসটি বাক্সের বাইরে। এটা এখানে. আপনার কাস্টম বৈশিষ্ট্য প্রয়োগ করুন:

public class RequiredIfAttribute : RequiredAttribute
{

    public RequiredIfAttribute(/*You can put here pararmeters if You need, as seen in other answers of this topic*/)
    {

    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {

    //You can put your logic here   

        return ValidationResult.Success;//I don't need its server-side so it always valid on server but you can do what you need
    }


}

তারপরে আপনার গ্লোবাল.এক্স্যাক্সে অ্যাডাপ্টার হিসাবে এটি ব্যবহার করার জন্য আপনার কাস্টম সরবরাহকারীর প্রয়োগ করতে হবে

public class RequreIfValidator : DataAnnotationsModelValidator <RequiredIfAttribute>
{

    ControllerContext ccontext;
    public RequreIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
       : base(metadata, context, attribute)
    {
        ccontext = context;// I need only http request
    }

//override it for custom client-side validation 
     public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
     {       
               //here you can customize it as you want
         ModelClientValidationRule rule = new ModelClientValidationRule()
         {
             ErrorMessage = ErrorMessage,
    //and here is what i need on client side - if you want to make field required on client side just make ValidationType "required"    
             ValidationType =(ccontext.HttpContext.Request["extOperation"] == "2") ? "required" : "none";
         };
         return new ModelClientValidationRule[] { rule };
      }
}

এবং আপনার গ্লোবাল.এক্স্যাক্সটিকে একটি লাইন দিয়ে সংশোধন করুন

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute), typeof(RequreIfValidator));

এবং এটি এখানে

[RequiredIf]
public string NomenclatureId { get; set; }

আমার জন্য প্রধান সুবিধাটি হ'ল আমাকে স্ববিরোধী বৈধতার ক্ষেত্রে কাস্টম ক্লায়েন্টের বৈধকরণকারী কোড করতে হবে না। এটি ঠিক [আবশ্যক] হিসাবে কাজ করে তবে কেবল আপনি চান এমন ক্ষেত্রে।


প্রসারিত করার অংশটি DataAnnotationsModelValidatorহ'ল আমার দেখার দরকার ছিল। ধন্যবাদ.
27'16 টিপুন


0

মডেল রাজ্য থেকে শর্তসাপেক্ষে ত্রুটি অপসারণের জন্য সাধারণ ব্যবহার:

  1. নিয়ামক পদক্ষেপের শর্তসাপেক্ষে প্রথম অংশ করুন
  2. মডেলস্টেট থেকে ত্রুটি অপসারণ করতে যুক্তি সম্পাদন করুন
  3. বাকি বিদ্যমান যুক্তি (সাধারণত মডেল স্টেটের বৈধতা, তারপরে সমস্ত কিছু) করুন

উদাহরণ:

public ActionResult MyAction(MyViewModel vm)
{
    // perform conditional test
    // if true, then remove from ModelState (e.g. ModelState.Remove("MyKey")

    // Do typical model state validation, inside following if:
    //     if (!ModelState.IsValid)

    // Do rest of logic (e.g. fetching, saving

আপনার উদাহরণে, সবকিছু যেমন আছে তেমন রাখুন এবং আপনার নিয়ামকের ক্রিয়ায় প্রস্তাবিত যুক্তি যুক্ত করুন। আমি ধরে নিচ্ছি যে আপনার ভিউমোডেলটি কন্ট্রোলার অ্যাকশনে পাস করেছে সেই ব্যক্তির এবং সিনিয়র ব্যক্তির অবজেক্টগুলি ইউআই থেকে তাদের মধ্যে থাকা ডেটা রয়েছে।


0

আমি এমভিসি 5 ব্যবহার করছি তবে আপনি এরকম কিছু চেষ্টা করতে পারেন:

public DateTime JobStart { get; set; }

[AssertThat("StartDate >= JobStart", ErrorMessage = "Time Manager may not begin before job start date")]
[DisplayName("Start Date")]
[Required]
public DateTime? StartDate { get; set; }

আপনার ক্ষেত্রে আপনি "ইসসিনিয়ার == সত্য" এর মতো কিছু বলবেন। তারপরে আপনাকে কেবল আপনার পোস্ট ক্রিয়ায় বৈধতা পরীক্ষা করতে হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.