मुझे लगता है कि आप चाहते हैं कि मॉडलस्टेट आपके मॉडल में किसी भी त्रुटि को इंजेक्ट करने के लिए पारित हो जाए? आईएमएचओ, मॉडलस्टेट जहां रहना चाहिए, और आप इसे सत्यापन त्रुटियां लाते हैं। यहां बताया गया है कि मैं त्रुटियों को उदाहरण के रूप में कैसे संभालता हूं। मैं यह नहीं कह रहा हूं कि यह सबसे अच्छा तरीका है या एकमात्र तरीका है, लेकिन यह एक तरीका है जहां आपकी सत्यापन परत को यह जानने की आवश्यकता नहीं है कि कौन सी या सत्यापन त्रुटियों का उपभोग करता है।
सबसे पहले, मेरे पॉको में, मैं सत्यापन नियमों के लिए System.ComponentModel.DataAnnotations
का उपयोग करता हूं। उदाहरण के लिए, मेरा खाता वर्ग यहां है।
public class Account : CoreObjectBase<Account>
{
public virtual int AccountId { get; set; }
[Required(ErrorMessage = "Email address is required.")]
public virtual string EmailAddress { get; set; }
[Required(ErrorMessage = "A password is required.")]
public virtual string Password { get; set; }
}
क्योंकि मैं अपने आप को सत्यापन आरंभ करने के लिए (MVC अपने आप पर यह कर के बाहर) सक्षम होना चाहते हैं, मैं अपने ही सत्यापनकर्ता को लागू करने के लिए किया था।
public class Validator<T> where T : CoreObjectBase<T>
{
public ValidationResponse Validate(T entity)
{
var validationResults = new List<ValidationResult>();
var context = new ValidationContext(entity, null, null);
var isValid = Validator.TryValidateObject(entity, context, validationResults);
return new ValidationResponse(validationResults.ToArray());
}
}
यहाँ ValidationResult मैं वापस पारित है
[Serializable]
public class ValidationResponse
{
public IList<ValidationResult> Violations { get; private set; }
public IList<ErrorInfo> Errors { get; private set; }
public bool HasViolations
{
get { return Violations.Count > 0; }
}
public ValidationResponse(params ValidationResult[] violations)
{
Violations = new List<ValidationResult>(violations);
var errors = from v in Violations
from n in v.MemberNames
select new ErrorInfo(n, v.ErrorMessage);
Errors = errors.ToList();
}
}
ErrorInfo मेरी त्रुटि
[Serializable]
public class ErrorInfo
{
public string ErrorMessage { get; private set; }
public object Object { get; private set; }
public string PropertyName { get; private set; }
public ErrorInfo(string propertyName, string errorMessage)
: this(propertyName, errorMessage, null)
{
}
public ErrorInfo(string propertyName, string errorMessage, object onObject)
{
PropertyName = propertyName;
ErrorMessage = errorMessage;
Object = onObject;
}
}
आदेश में इस मान्यता लपेट के लिए में के बारे में जानकारी के साथ एक बहुत ही बुनियादी वर्ग है सब अच्छा और साफ मेरे पोको कक्षाओं के साथ, मैं बेस क्लास से प्राप्त करता हूं। इसे सामान्य बनाने के लिए सत्यापन के लिए जहां विरासत वाले बच्चे को बेस क्लास को यह टाइप करना है। यह परिपत्र लगता है, लेकिन यह काम करता है।
[Serializable]
public class CoreObjectBase<T> : IValidatable where T : CoreObjectBase<T>
{
#region IValidatable Members
public virtual bool IsValid
{
get
{
// First, check rules that always apply to this type
var result = new Validator<T>().Validate((T)this);
// return false if any violations occurred
return !result.HasViolations;
}
}
public virtual ValidationResponse ValidationResults
{
get
{
var result = new Validator<T>().Validate((T)this);
return result;
}
}
public virtual void Validate()
{
// First, check rules that always apply to this type
var result = new Validator<T>().Validate((T)this);
// throw error if any violations were detected
if (result.HasViolations)
throw new RulesException(result.Errors);
}
#endregion
}
और अंत में, जैसा कि आप देख सकते हैं, मेरी सत्यापन नियम नियम अपवाद को फेंकता है। यह वर्ग सभी त्रुटियों के लिए एक रैपर है।
[Serializable]
public class RulesException : Exception
{
public IEnumerable<ErrorInfo> Errors { get; private set; }
public RulesException(IEnumerable<ErrorInfo> errors)
{
Errors = errors != null ? errors : new List<ErrorInfo>();
}
public RulesException(string propertyName, string errorMessage) :
this(propertyName, errorMessage, null)
{
}
public RulesException(string propertyName, string errorMessage, object onObject) :
this (new ErrorInfo[] { new ErrorInfo(propertyName, errorMessage, onObject) })
{
}
}
तो, उस के साथ कहा, मेरे नियंत्रक में मेरी मान्यता यह
public ActionResult MyAction()
{
try
{
//call validation here
}
catch (RulesException ex)
{
ModelState.AddModelStateErrors(ex);
}
return View();
}
ModelState.AddModelStateErrors की तरह अधिक (पूर्व) लग रहा है; एक विस्तार विधि है जिसे मैंने लिखा था। यह बहुत ही सरल है।
public static void AddModelStateErrors(this System.Web.Mvc.ModelStateDictionary modelState, RulesException exception)
{
foreach (ErrorInfo info in exception.Errors)
{
modelState.AddModelError(info.PropertyName, info.ErrorMessage);
}
}
इस तरह, मैं अभी भी अपने सेवाओं/खजाने के लिए डि उपयोग करते हैं, और उन्हें एक त्रुटि ऊपर फेंक कि मेरा मॉडल अमान्य है दे सकते हैं। फिर मैंने सामने वाला अंत दिया - चाहे वह एक एमवीसी ऐप, वेब सेवा, या विंडोज ऐप है - तय करें कि उन त्रुटियों के साथ क्या करना है।
मुझे लगता है कि एमवीसी नियंत्रक/मॉडल/मॉडल/सेवाओं/भंडार/आदि में वापस राज्य को इंजेक्शन करना परतों के बीच मूल अलगाव का उल्लंघन है।
क्या आपने जांच की: http://stackoverflow.com/questions/2077055/ioc-on-ivalidationdictionary-with-castle-windsor – bzarah
यह एक बहुत ही समान प्रश्न है: मेरे मामले में, मैं कोशिश भी नहीं करता एक वैधकर्ता को तुरंत चालू करने के लिए - मैं कंटेनर को हल करना चाहता हूं। किसी भी मामले में, आपके द्वारा लिंक किए गए प्रश्न का मेरे लिए कोई जवाब नहीं है। मैं इसे खड़ा करूंगा और कुछ अतिरिक्त अंतर्दृष्टि के लिए आशा करूंगा। – user403830
मैं उम्मीद कर रहा था कि मौजूदा कंट्रोलर कॉन्टेक्स्ट को स्थिर रूप से प्राप्त करने का कोई तरीका था, जैसे कि आप वर्तमान HttpContext को HttpContext.Current के साथ प्राप्त कर सकते हैं। दुर्भाग्य से, मुझे एक नहीं मिला। एक अन्य विचार IProductValidator पर एक अतिरिक्त विधि होगी जो "ModelStateWrapper" स्वीकार करेगा और सत्यापन त्रुटियों को वहां कॉपी करेगा। निर्भरता इंजेक्शन के रूप में उतना अच्छा नहीं है, लेकिन इसे बहुत आसानी से काम करना चाहिए। – PatrickSteele