Send parameter to custom validationrule - c#

Is it possible to send a parameter to a custom validationrule?
My validationrule:
public class CustomTypeSelectedRule : IValidationRule
{
public ValidationResult Validate(object input)
{
// Here I need an extra value from the class calling
// the validation rule.
return ValidationResult.Success;
}
}
My property using the validationrule:
[ContractValidation(typeof(ValidationRules.CustomTypeSelectedRule))]
public int CustomType
{
get
{
return this.customType;
}
set
{
this.customType = value;
}
}
Any input is appreciated, thanks!

This might help you -
http://michlg.wordpress.com/2010/01/29/wpf-custom-validationrule-with-an-additional-parameter/

Related

How can I define available values for code completion of a string property in C# in a way that MongoDB.BsonSerializer will understand?

The main purpose is to show intellisense when setting the property. It would be great if I could do it via an attribute like the image below.
The property should remain a string(not enum or struct) so that Mongo's BsonSerializer can serialize it properly. Here is an example of what it might look like:
To help other developers on the team know possible (but not exlusive) values they can use for the Type field Code Completion should display values that can be used as shown below:
(Edited) I was able to solve this by creating my own type
public class SkinType:StringType<SkinType>
{
public SkinType(string value)
{
Value = value;
}
public SkinType()
{
}
public static implicit operator string(SkinType d)
{
return d.Value;
}
public static implicit operator SkinType(string d)
{
return new SkinType(d);
}
public const string StringValue = nameof(StringValue);
public const string Color = nameof(Color);
}
Now I get intellisense for my Type property and Mongo knows how to serialize it.
Here is how I use it:
public class Skin : ServiceMongoIdentity
{
//removed some properties for brevity.
[BsonIgnoreIfDefault]
[BsonDefaultValue(SkinType.StringValue)]
public SkinType Type { get; set; } = SkinType.StringValue;
}
Here is how the StringType base class is defined. I had to make Value public because Generics cannot have constructors with parameters
public abstract class StringType<T> where T :StringType<T>,new()
{
[ReadOnly(true)]
public string Value;
public T FromString(string d)
{
return new T
{
Value = d
};
}
public override bool Equals(object obj)
{
return obj?.ToString() == Value;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value;
}
}

Asp.Net MVC data annotation custom attribute is not working

I need implement a cusotm attribute then using asp.net data annotation to validate a class. Unfortunately, the attribute class is not called at run time. Please help me out. Many thanks. Below is the source code.
using System;
using System.Collections.Generic;
using CaseMgr.Model.Base;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace CaseMgr.Model.BusinessObjects
{
public partial class PatLiverException : BusinessBase<decimal>, IComparable<PatLiverException>, IEquatable<PatLiverException>
{
private LiverExcepDisease _liverExcepDisease = null;
private DateTime _sccApprovalDate = new DateTime();
public PatLiverException() { }
public virtual LiverExcepDisease LiverExcepDisease
{
get { return _liverExcepDisease; }
set { _liverExcepDisease = value; }
}
[SccApprovalDateValidate("SccApprovalDate", "LiverExcepDisease")]
public virtual DateTime SccApprovalDate
{
get { return _sccApprovalDate; }
set { _sccApprovalDate = value; }
}
}
public class SccApprovalDateValidateAttribute : ValidationAttribute
{
public string m_SccApprovalDate { get; private set; }
public string m_LiverExcepDisease { get; private set; }
public SccApprovalDateValidateAttribute(string SccApprovalDate_PropertyName, string LiverExcepDisease_PropertyName)
{
this.m_SccApprovalDate = SccApprovalDate_PropertyName;
this.m_LiverExcepDisease = LiverExcepDisease_PropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
var SccApprovalDate_Property = context.ObjectType.GetProperty(m_SccApprovalDate);
DateTime SccApprovalDate_Value = (DateTime)SccApprovalDate_Property.GetValue(context.ObjectInstance, null);
var LiverExcepDisease_Property = context.ObjectType.GetProperty(m_LiverExcepDisease);
LiverExcepDisease LiverExcepDisease_Value = (LiverExcepDisease)LiverExcepDisease_Property.GetValue(context.ObjectInstance, null);
if (SccApprovalDate_Value != null && SccApprovalDate_Value != DateTime.MinValue && SccApprovalDate_Value != DateTime.MaxValue)
{
return LiverExcepDisease_Value.Id == 10 ? ValidationResult.Success : new ValidationResult("When other, SccApprovalDate can not be null.");
}
else
{
return ValidationResult.Success;
}
}
}
}
If you are going to use the validation attribute on a class you need:
[AttributeUsage(AttributeTargets.Class)]
public class Sccxxxxxxxxx : ValidationAttribute
https://msdn.microsoft.com/en-us/library/tw5zxet9.aspx?f=255&MSPPError=-2147217396
Take a look at this post: ASP.NET MVC: Custom Validation by DataAnnotation
Also, if you put a breakpoint inside SccApprovalDateValidateAttribute.ValidationResult() does it get hit?
Your code looks okay, except I cannot see where you call or use the property,SccApprovalDate, because your validation attribute declared on the property will only be invoked if the property is called or used by the run-time. Can you post how you use the property SccApprovalDate?

An unhandled exception of type 'System.StackOverflowException.Cannot evaluate expression because the current thread is in a stack overflow state

public class ConnectionElement : ConfigurationElement
{
[ConfigurationProperty("uri", DefaultValue = "/")]
public String Uri
{
get
{ return(String)this. Uri; }
set
{ this.Uri = value; }
}
}
It is throwing error stating An unhandled exception of type System.StackOverflowException. Please help
Both your getter and your setter are calling themselves. Remember that properties are just groups of methods, effectively. Your class really looks like this, but with a bit of extra metadata:
public class ConnectionElement : ConfigurationElement
{
public string GetUri()
{
return (string) GetUri();
}
public void SetUri(string value)
{
SetUri(value);
}
}
Now can you see why it's failing?
It's not clear why you're casting in the getter, but it looks like an automatically implemented property might do:
[ConfigurationProperty("uri", DefaultValue = "/")]
public string Uri { get; set; }
EDIT: If, as noted in comments, you're really trying to use the indexer, you need to do that instead of calling your property recursively:
public class ConnectionElement : ConfigurationElement
{
[ConfigurationProperty("uri", DefaultValue = "/")]
public string Uri
{
get { return (string) this["uri"]; }
set { this["uri"] = value; }
}
}
You are calling the getter from within the getter. Likewise for the setter. Just make it an automatically implemented property:
public string Uri { get; set; }
or define a field and read/write that.
Actually, since this is part of a custom configuration section, you probably need something more like
public class ConnectionElement : ConfigurationElement
{
[ConfigurationProperty("uri", DefaultValue = "/")]
public String Uri
{
get { return (String)this["uri"]; }
set { this["uri"] = value; }
}
}

ErrorProvider - Input string was not in a recognized format C#

I'm currently work with Entity Framework 5.0 and WinForms. What I'd like to do is set-up validation on my POCO classes so that when I databind them to form fields I'd like to display UI validation errors via an ErrorProvider. I have set up a base "ValidationEntity" class that implements the IDataErrorInfo interface with some simple validation methods for my child classes to call. For the most part, validating the field length, range, etc.. seem to be working fine displaying the errors to the user via the ErrorProvider.
However, I seem to have ran into an issue with the "ValidateRequiredField" method. If I have a class that has a non-nullable integer field and the user happens to remove this value on the form the ErrorProvider does show a message to the end-user, but the message is "Input string was not in a recognized format". Now I assume this is because the form, being bound to an integer field, is attempting to convert the empty text into an integer and a conversion error is occurring prior to the value being sent to the POCO class property. My question is, what would the best approach to solve this be?
I'm guessing that I may have to implement the Validating methods of the TextBox controls inside the form, catch the empty/null entry, and set the appropriate error message on the error provider. However, I was hoping on a way to let the class handle the empty/null value and set the error inside the POCO class so that it propagates to the UI. Originally I had thought of creating a custom TypeConverter (e.g. RequiredIntTypeConverter) but ran into issues since I'm inheriting from the ValidationEntity class and couldn't think of a good way of adding to the errors.
Below is a sample from the ValidationEntity class as well as a snippet from the Company class.
ValidationEntity.cs
public class ValidationEntity : IDataErrorInfo
{
private readonly Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();
string IDataErrorInfo.Error
{
get { return string.Empty; }
}
string IDataErrorInfo.this[string propertyName]
{
get
{
return (!errors.ContainsKey(propertyName) ? null : String.Join(Environment.NewLine, errors[propertyName]));
}
}
public void AddError(string propertyName, string error, bool isWarning)
{
if (!errors.ContainsKey(propertyName))
{
errors[propertyName] = new List<string>();
}
if (!errors[propertyName].Contains(error))
{
if (isWarning)
{
errors[propertyName].Add(error);
}
else
{
errors[propertyName].Insert(0, error);
}
}
}
public void RemoveError(string propertyName, string error)
{
if (errors.ContainsKey(propertyName) &&
errors[propertyName].Contains(error))
{
errors[propertyName].Remove(error);
if (errors[propertyName].Count == 0)
{
errors.Remove(propertyName);
}
}
}
public void ValidateFieldLength(string propertyName, string value, int maxLength)
{
string errorMessage = string.Format("Text entered exceeds max length of {0} characters", maxLength);
if (value != null)
{
if (value.Length > maxLength)
{
if (!errors.ContainsKey(propertyName))
{
AddError(propertyName, errorMessage, false);
}
}
else
{
RemoveError(propertyName, errorMessage);
}
}
else
{
RemoveError(propertyName, errorMessage);
}
}
public void ValidateRequiredField(string propertyName, string value)
{
string errorMessage = string.Format("{0} is required.", propertyName);
if (string.IsNullOrWhiteSpace(value))
{
AddError(propertyName, errorMessage, false);
}
else
{
RemoveError(propertyName, errorMessage);
}
}
}
Company.cs
public class Company : ValidationEntity
{
private int companyID;
private string companyName;
public int CompanyID
{
get { return this.companyID; }
set
{
OnCompanyIdChanging(value.ToString());
this.companyID = value;
}
}
public string CompanyName
{
get { return this.companyName; }
set
{
OnCompanyNameChanging(value);
this.companyName = value;
}
}
private void OnCompanyIdChanging(string value)
{
ValidateRequiredField("CompanyID", value);
}
private void OnCompanyNameChanging(string value)
{
ValidateRequiredField("CompanyName", value);
ValidateFieldLength("CompanyName", value, 30);
}
}
Thank you for your assistance.
After doing some more research on this and testing out code samples I was able to find a solution to this particular item. A custom TypeConverter was needed for a non-nullable integer conversion. I was able to locate information here
and ended up with the following TypeConverter for testing a "Required Integer":
public class RequiredIntConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
[System.Diagnostics.DebuggerNonUserCode]
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
throw new ApplicationException("This field requires an integer value and cannot be blank.");
}
int result = 0;
if (!int.TryParse(value.ToString(), out result))
{
throw new ApplicationException("The value could not be parsed as a valid integer data type.");
}
else
{
return result;
}
}
}
When I initially tested the code from the link above my debugger kept breaking when I attempted to throw the ApplicationException. Thinking this was an error in my code I was confused on how to use the TypeConverter. However, I found the following post which describes how to suppress the debugger from breaking on a method.
I'm still a bit unsure on why it breaks on this ApplicationException and how the ErrorProvider knows to display the underlying exception. If anyone could point me to some additional resources on this it would be greatly appreciated.
Have a great day.

overriding properties

I am inheriting from a class that has this property :
public bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
I am trying to override this in the derived class, but it doesn't recognise isAuthorized. Can someone help me with my syntax?
public override bool isAuthorized()
{
}
This is the error I get :
cannot override because 'CDBase.isAuthorized' is not a function
EDIT : So if I want the override to always set isAuthorized to true, I would use this syntax?
private bool _Authorized = false;
public override bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = true; }
}
its a property, you used as method isAuthorized()
() - used for methods
you have to do in your derived class
public override bool isAuthorized
{
}
To set your value always to true you can simply write this code:
public override bool isAuthorized
{
get { return true; }
}
Same as when you want your method to be overridable, the property also has to be declared virtual in the base class:
public virtual bool isAuthorized ...
Also you cannot override a propeprty with a method. You can only override the getters and setters in the derived class:
public override bool isAuthorized
{
get { return base.isAuthorized; }
set { base.isAuthorized = value; }
}
The original class should have a virtual, but I suspect you might also have an issue with the fact that you are trying to override a base class property with a derived class method.
If your derived class method looked like this:
public override bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
Then you would need this in your base class:
public virtual bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
Can you maybe desrive more what you are trying to achieve?
public virtual bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
public override bool isAuthorized
{
...
}
In base class mark the property as virtual which you want to be overridden and in derive class use override keyword for the property that needs to be overriden.
this
class A
{
public virtual string prop { get; set; }
}
class B : A
{
public override string prop
{
get
{
return "overridden";
}
set
{
base.prop = value;
}
}
}
Hi I think you must declare this as Virtual in able to override
Like:
public virtual bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
Regars,
In base class you can mark it as virtual, and you can override.
Actually, use reflector we can see the properties are methods, too!
About your error and syntax :
Simply dont use the '()' . You are using property as method.
About how to do it :
There are two ways to implement it in base class. 'new' and 'override'. But their implementations varies regarding to base class.
http://msdn2.microsoft.com/en-us/library/435f1dw2.aspx
The new modifier instructs the compiler to use your implementation instead of the base class implementation. Any code that is not referencing your class but the base class will use the base class implementation.
public bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
public new bool isAuthorized
{ //someth }
http://msdn2.microsoft.com/en-us/library/ebca9ah3.aspx
The override modifier may be used on virtual methods and must be used on abstract methods. This indicates for the compiler to use the last defined implementation of a method. Even if the method is called on a reference to the base class it will use the implementation overriding it.
public virtual bool isAuthorized
{
get { return _Authorized; }
set { _Authorized = value; }
}
public override bool isAuthorized
{ //someth }

Categories