Creating Custom Validator - Problems

Topics: Building and extending application blocks, Validation Application Block
Aug 10, 2007 at 1:09 AM
Greetings!

I am attempting to create a custom validator. I used the code from http://cs.jaxdug.com/blogs/davidstrommer/archive/2007/04/01/1795.aspx as an example.

Everything builds properly and so forth, but I cannot seem to actually use the validator itself. I have spent hours googling around trying to figure out what is wrong, and have had no success. Currently, I have added a new rule set to the string type, and under that rule set I have added a "Custom Validator" to "Self". In the type for custom validator, I put in the full type name of my custom validator that I wrote. When I attempt to execute it, it returns an error saying:

"The type 'com.cybernetcorp.development.irvine.model.util.datavalidation.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' cannot be resolved. Please verify the spelling is correct or that the full type name is provided."

I have followed the quickstart's example of creating the custom validator class and the configuration file entry. I have made them as identical as possible. I even tried copy pasting the custom validator, that I know works, from the quickstart into my project and setting up the config file the same way.. I get the same error for the quickstart example that I copied over. Obviously it is a problem with either my config file or my project, but I can not figure out what it is.

Any assistance would be extremely appreciated. I am about ready to scream.

Thanks everyone!

-Sastira

Aug 10, 2007 at 2:44 AM
Hi,

Is assembly "com.cybernetcorp.development.irvine.model.util.datavalidation" deployed with your application?
Try loading the type from your app using Type.GetType(string) just before using the validation; if it fails you know there is a problem finding your assembly.

Are you using the config tool to add your validator?

Regards,
Fernando
Aug 10, 2007 at 4:41 AM
Hi!

First off, thanks for your response, fsimonazzi!

As for your questions:
The assembly seems to be deployed just fine. I tried what you said with GetType and it found the type just fine.

I used the config tool to add the validator, yes. Here is the xml of my custom validator entry:

<validation>
<type assemblyName="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name="System.String">
<ruleset name="VerifySpaces">
<validator messageTemplate="" messageTemplateResourceName=""
messageTemplateResourceType="" tag="" type="com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidators, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Custom Validator" />
</ruleset>
</type>
</validation>

Thank you, again!

-Sastira
Aug 10, 2007 at 3:25 PM
Hi,

Can you post the stack trace for the exception you're getting?
I presume the quick start does work in your machine; does it?

Fernando
Aug 10, 2007 at 9:23 PM
Howdy!

First off, yes, your assumption was correct: the quickstart works just fine.

Here is the stack trace you requested:

at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.AssemblyQualifiedTypeNameConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at System.ComponentModel.TypeConverter.ConvertFrom(Object value)
at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.NameTypeConfigurationElement.get_Type()
at Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.CustomValidatorData.DoCreateValidator(Type targetType)
at Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidatorData.DoCreateValidator(Type targetType, Type ownerType, MemberValueAccessBuilder memberValueAccessBuilder)
at Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidatorData.Microsoft.Practices.EnterpriseLibrary.Validation.IValidatorDescriptor.CreateValidator(Type targetType, Type ownerType, MemberValueAccessBuilder memberValueAccessBuilder)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidatorBuilderBase.CreateValidatorForValidatedElement(IValidatedElement validatedElement, CompositeValidatorBuilderCreator validatorBuilderCreator)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidatorBuilderBase.CollectValidatorsForType(IValidatedType validatedType, List`1 validators)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidatorBuilderBase.CreateValidator(IValidatedType validatedType)
at Microsoft.Practices.EnterpriseLibrary.Validation.ConfigurationValidatorBuilder.CreateValidator(Type type, ValidatedTypeReference typeReference, String ruleset)
at Microsoft.Practices.EnterpriseLibrary.Validation.ConfigurationValidatorBuilder.CreateValidator(Type type, String ruleset)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidationFactory.InnerCreateValidatorFromConfiguration(Type targetType, String ruleset, IConfigurationSource configurationSource)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidationFactory.CreateValidatorT(String ruleset, IConfigurationSource configurationSource, Boolean cacheValidator)
at Microsoft.Practices.EnterpriseLibrary.Validation.ValidationFactory.CreateValidatorT(String ruleset)
at Microsoft.Practices.EnterpriseLibrary.Validation.Validation.ValidateT(Ttarget, String ruleset)
at com.cybernetcorp.development.irvine.model.util.datavalidation.DataValidation.ValidateSpaces(String item) in C:\MyProjects\Irvine\Development\Versions\v1.1.1.1-Dev\src\Irvine\ApplicationTier\Model\util\DataValidation.cs:line 31

Thanks again for all your assistance!

-Sastira
Aug 10, 2007 at 9:36 PM
Hi,

It's very odd that this fails and Type.GetType() invocation you added doesn't as they execute the exact same code...
I suggest you try by:
  • Executing Type.GetType("'com.cybernetcorp.development.irvine.model.util.datavalidation.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); in your application. It should throw, or something is very wrong.
  • Build your application with the library source code (if you're using the binaries) and debug the call to AssemblyQualifiedTypeNameConverter.ConvertFrom to make sure the appropriate parameter is being used.

Regards,
Fernando
Aug 11, 2007 at 9:57 PM
Another thing I would suggest is using the fuslogvw.exe tool to try to figure out why the type load is failing. The tool is very useful but pretty quirky, so if you haven't used it before you may want to search for some pointers on the internet.

While it doesn't sound like you're doing anything obviously wrong, errors like this are pretty well always caused by deployment or configuration issues, so it probably isn't anything to do with the validation block.

Tom
Aug 11, 2007 at 10:37 PM
Hello again!

More info:

The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidators, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); fails.
The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidators"); fails.
The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces"); succeeds.

All three of those strings in the config file fail.

It looks like I'm not deploying something correctly? I'll take a look at fuslogvw.exe and see what I can do while I wait for a response.

Thank you very much for all your assistance! You guys are the best!

-Sastira

Aug 11, 2007 at 10:58 PM
This would seem to confirm that it is not being deployed correctly. However, I am not sure how to fix it. I'll google around, but I would also appreciate any suggestions you might have!

      • Assembly Binder Log Entry (8/11/2007 @ 3:50:19 PM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
Running under executable C:\MyProjects\Irvine\Development\Versions\v1.1.1.1-Dev\src\Irvine\ApplicationTier\Model\bin\Debug\Model.exe
--- A detailed error log follows.

=== Pre-bind state information ===
LOG: User = XXXXXX\Administrator
LOG: DisplayName = com.cybernetcorp.development.irvine.model.util.datavalidators, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = Model.exe
Calling assembly : Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProjects\Irvine\Development\Versions\v1.1.1.1-Dev\src\Irvine\ApplicationTier\Model\bin\Debug\Model.exe.config
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug/com.cybernetcorp.development.irvine.model.util.datavalidators.DLL.
LOG: Attempting download of new URL file:///C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug/com.cybernetcorp.development.irvine.model.util.datavalidators/com.cybernetcorp.development.irvine.model.util.datavalidators.DLL.
LOG: Attempting download of new URL file:///C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug/com.cybernetcorp.development.irvine.model.util.datavalidators.EXE.
LOG: Attempting download of new URL file:///C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug/com.cybernetcorp.development.irvine.model.util.datavalidators/com.cybernetcorp.development.irvine.model.util.datavalidators.EXE.
LOG: All probing URLs attempted and failed.


Thanks!

-Sastira
Aug 13, 2007 at 3:25 PM
Hi,

What is the name of the assembly where class com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces resides? Is it available at C:/MyProjects/Irvine/Development/Versions/v1.1.1.1-Dev/src/Irvine/ApplicationTier/Model/bin/Debug?

You say:

The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidators, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); fails.
The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, com.cybernetcorp.development.irvine.model.util.datavalidators"); fails.
The call: Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces"); succeeds.


This is consistent with class com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces belonging to an assembly that is notcom.cybernetcorp.development.irvine.model.util.datavalidators. However you mention that the original configuration file was built by using the configuration tool, so at some point the class did belong to that assembly, and to find the class with Type.GetType the class has to be somewhere.. Have you been doing some refactoring there?

Print the result of doing Type.GetType("com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces").AssemblyQualifiedName; that should tell you where is it loading the class from.

Fernando
Aug 13, 2007 at 6:00 PM
Hi!

Well, I must say, you are my hero! All your patient guidance and suggestions have finall led me to a working program!

Unfortnately, I don't know why it is working! If you could be so kind as to tell me why it works so I can really understand and learn, I would be so very appreciative!

Anyway, I used AssemblyQualifiedName and it returned the string:

com.cybernetcorp.development.irvine.model.util.datavalidators.VerifySpaces, Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

I popped that string into my config file for the heck of it, and it worked! I have absolutely no idea what "Model" is, nor why it is in that place in the string. I was told by another programmer that the second bit of that string was the namespace under which the type resides. What is it and how do I view/change it? Can I?

Also, after it was able to find the type and attempt to instantiate it, it threw an exception saying there was no constructor. Luckily I searched these forums and found that you had answered the same question for someone else. I just needed a NameValueCollection parameter in my constructor. :)

Thank you, again, so much, for your assistance! I wish I could do something to repay you for this!

-Sastira
Aug 13, 2007 at 6:39 PM
Hi,

The "Model" is the name of the assembly. If you're developing it, you'll find this value set on its project's properties.

Fernando
Aug 13, 2007 at 7:24 PM
Hi!

Well dang it! I wish I'd known that sooner.

Thanks again for all your help!

-Sastira