How to get interpolated message in NHibernate.Validator - asp.net-mvc-2

I'm trying to integrate NHibernate.Validator with ASP.NET MVC client side validations, and the only problem I found is that I simply can't convert the non-interpolated message to a human-readable one. I thought this would be an easy task, but turned out to be the hardest part of the client-side validation. The main problem is that because it's not server-side, I actually only need the validation attributes that are being used, and I don't actually have an instance or anything else at hand.
Here are some excerpts from what I've been already trying:
// Get the the default Message Interpolator from the Engine
IMessageInterpolator interp = _engine.Interpolator;
if (interp == null)
{
// It is null?? Oh, try to create a new one
interp = new NHibernate.Validator.Interpolator.DefaultMessageInterpolator();
}
// We need an instance of the object that needs to be validated, se we have to create one
object instance = Activator.CreateInstance(Metadata.ContainerType);
// we enumerate all attributes of the property. For example we have found a PatternAttribute
var a = attr as PatternAttribute;
// it seems that the default message interpolator doesn't work, unless initialized
if (interp is NHibernate.Validator.Interpolator.DefaultMessageInterpolator)
{
(interp as NHibernate.Validator.Interpolator.DefaultMessageInterpolator).Initialize(a);
}
// but even after it is initialized the following will throw a NullReferenceException, although all of the parameters are specified, and they are not null (except for the properties of the instance, which are all null, but this can't be changed)
var message = interp.Interpolate(new InterpolationInfo(Metadata.ContainerType, instance, PropertyName, a, interp, a.Message));
I know that the above is a fairly complex code for a seemingly simple question, but I'm still stuck without solution. Is there any way to get the interpolated string out of NHValidator?

Ok, so I know this is an old question, but I stumbled across this when trying to do the same thing, and it helped me get started - so I thought I would provide an answer.
I think the code in the question was on the right track but there are a couple of problems. The interpolator was not completely initialised with the ResourceManager and Culture details, and it doesn't seem to allow for the fact that you can only have one DefaultMessageInterpolator per validation attribute. Also, you don't need an instance of the object you are validating to get an interpolated message.
In the code in the question, where you are initialising the interpolator with the attribute value, you also need to initialise the interpolator with details of the ResourceManager to be used.
This can be done using the overloaded Initialize method on DefaultMessageInterpolator which has the following signature:
public void Initialize(ResourceManager messageBundle,
ResourceManager defaultMessageBundle,
CultureInfo culture)
The first parameter is a user-defined ResourceManager in case you want to use your own resource file for error messages, you can pass a null if you just want to use the default ResouceManager, the second parameter is the default ResourceManager - you can pass
new ResourceManager(
NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
Assembly.GetExecutingAssembly());
for this, the last parameter is the culture to use, (NHibernate.Validator comes with resource files with validation messages in several languages) - if you pass a null in to this it will just use CultureInfo.CurrentCulture
Lastly, you can only have one DefaultMessageInterpolator per attribute, so you will need to create a new DefaultMessageInterpolator for each validation attribute. You could make use of the DefaultMessageInterpolatorAggregator to handle this, or just roll your own.
I hope this helps someone.

Thanks for your help all--I'd upvote if I could. I just wanted to add that in addition to the first Initialize call on the DefaultMessageInterpolator that Stank illustrates, I also had to make a second different Initialize call to fully initialize it (I was getting some Null Reference Exceptions using only the first call). My code is as follows:
string interpolatedMessage = "";
DefaultMessageInterpolator interpolator = new DefaultMessageInterpolator();
interpolator.Initialize(null,
new ResourceManager(
NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
Assembly.Load("NHibernate.Validator")),
CultureInfo.CurrentCulture);
interpolator.Initialize(attribute as Attribute);
if (attribute is IValidator && attribute is IRuleArgs)
{
IValidator validator = attribute as IValidator;
IRuleArgs ruleArgs = attribute as IRuleArgs;
InterpolationInfo interpolationInfo = new InterpolationInfo(
validatableType,
null,
propertyName,
validator,
interpolator,
ruleArgs.Message);
interpolatedMessage = interpolator.Interpolate(interpolationInfo);
}

Related

Registering a type with both EnableClassInterceptors and WithParameter

I'm having an issue with Autofac where it seems like EnableClassInterceptors is interfering with my ability to use .WithParameter(...). When the constructor is being called on Service using the code below, someString is not being populated. Notes:
I've tried using ResolvedParameter instead, it does not help (note: my Resolved parameter still includes the name of the parameter when I tried that)
If I remove EnableClassInterceptors and InterceptedBy, the parameter does get populated properly. This, however, isn't a valid solution as I need the interceptors.
Re-ordering WithParameter, EnableClassInterceptors, and InterceptedBy does not help.
Looking at Type Interceptors, specifically the "Class Interceptors and UsingConstructor" section, on docs.autofac.org, it mentions that using EnableClassInterceptors will cause ConstructUsing to fail. I think something similar might be happening with my scenario below.
Snippet of my registration code looks like this:
var builder = new ContainerBuilder();
builder.RegisterType<Dependency>.As<IDependency>.InstancePerLifetimeScope();
builder.RegisterType<Service>()
.As<IService>()
.WithParameter(new NamedParameter("someString", "TEST"))
.EnableClassInterceptors()
.InterceptedBy(typeof(LogExceptionsInterceptor));
Service's constructor looks something like this:
public class Service : IService
{
public Service(IDependency dependency, string someString)
{
if(dependency == null)
throw ArgumentNullException(nameof(dependency));
if(someString == null)
//**throws here**
throw ArgumentNullException(nameof(someString));
}
}
[Guess] What I'm thinking is happening is that when EnableClassInterceptors is called, a proxy class is generated with a constructor that works on top of the existing one, but the parameter names do not copy over into the proxy class/constructor.
Is this a problem? Is there a way to form the registration that allows both WithParameter and EnableClassInterceptors to be used together? Is it a bug in Autofac?
Your guess is correct: the generated proxy class does not keep the constructor parameter names.
Currently there is no way to influence this in DynamicProxy so this is not a bug of Autofac (although this edge case currently not documented on the Autofac documentation website).
This is how your original Service class's parameters look like:
typeof(Service).GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[2]}
[0]: {ConsoleApplication10.IDependency dependency}
[1]: {System.String someString}
But the generated proxy does not keep the names:
GetType().GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[3]}
[0]: {Castle.DynamicProxy.IInterceptor[] }
[1]: {ConsoleApplication10.IDependency }
[2]: {System.String }
So you have two not very robust options to workaround this limitation with WithParameter:
use the TypedParamter with string as the type:
.WithParameter(new TypedParameter(typeof(string), "TEST"))
However if you have multiple paramters with the same type this won't work
use the PositionalParameter in this case you need to add 1 if the type is proxied
.WithParameter(new PositionalParameter(2, "TEST"))
Another options would be to don't use a primitive string type but create a wrapper e.g. MyServiceParameter or create another service which can provide these string configuration values to your other services.

Yii Framework; How to check if a model attribute has a SPECIFIC validator?

I am making a custom ActiveForm method, but it requires the model to have a certain custom validator attached the the attribute that is being passed through (otherwise who knows what will happen!?)
My question is simply... is there a way to run this check in the code that is reliable?
I don't want to add the validator at runtime. That would create confusion and possibly let someone use this type of field where it ought not be used.
So I want to say something like:
if( model NOT HAVE validationMethod ON property)
throw Exception;
I'm also not sure why you want to do this, but in addition to viewing the rules array you can do:
$model->getValidators($attribute)
to check which validators are active for a particular attribute (or all attributes, if the arg is null. (I'm assuming $attribute = property in your example.)
This will return all the validator objects that are active for the current scenario and you can check if a predefined or custom class exists. It also gets you a bit more info than just the rules array (i.e., the properties of the validator class).

MEF: metadata seem to override interface when using GetExports

I'm building a MEF-based plugin-centric WPF application and I'm facing an issue with GetExports, maybe it's just my ignorance but I find an odd behaviour. I have a number of exported parts, all derived from 2 different interfaces (let's name them A and B), but all marked with the same metadata attribute X. So I have code like:
[Export(typeof(A))]
[TheXAttributeHere...]
public class SomePart1 : A { ... }
for each part, and the same for classes implementing B:
[Export(typeof(B))]
[TheXAttributeHere...]
public class SomePart2 : B { ... }
Now, when I try getting all the parts implementing A and decorated by attribute X with some values, MEF returns not only the A-implementing parts, but ALSO the B-implementing parts. So, when I expect to deal with A-objects I get a B, whence a cast exception.
In the real world, interfaces are named IItemPartEditorViewModel and IItemPartEditorView, while their common attribute is named ItemPartEditorAttribute and exposes a PartType string property on which I do some filtering. My code to get parts is thus like e.g.:
var p = (from l in container.GetExports<IItemPartEditorViewModel, IItemPartEditorMetadata>()
where l.Metadata.PartType == sPartType
select l).FirstOrDefault();
When looking for IItemPartEditorViewModel whose PartType is equal to some value, I get the IItemPartEditorView instead of IItemPartEditorViewModel implementing object. If I comment out the attribute in the IItemPartEditorView object instead, I correctly get the IItemPartEditorViewModel implementing object.
Update the suggested "templated" method was used, but I mistyped it here as I forgot to change lessthan and greaterthan into entities. Anyway, reviewing the code I noticed that in the attribute I had "ViewModel" instead or "View" for the interface type, so this was the problem. Shame on me, sorry for bothering :)!
I think I'd need to see more of the code to know for sure what's going on. However, I'd suggest you call GetExports like this:
// Get exports of type A
container.GetExports<A>();
// Get exports of type B
container.GetExports<B>();
Then do your filtering on the list returned. This will probably fix the cast issues you are having. I'd also be interested in seeing the code for the custom metadata attribute. If it derives from ExportAttribute for example, that might be part of the problem.

What is the "Func<object> modelAccessor" parameter for in MVC's DataAnnotationsModelMetadataProvider?

It's one of the parameters supplied to the CreateMetadata method (which you override if extending metadata support).
ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor, <<--THIS ONE
Type modelType,
string propertyName)
I had assumed that it allowed you to access the model object itself (e.g. for setting metadata based on model values), however when I try to use it to cast to my model object I just get null.
Entity ent = (Entity)modelAccessor(); // = Null
If I've missunderstood, can anyone explain what it's purpose is? Or alternatively, how to properly use it?
Thanks
We originally had that as "object model", rather than "Func modelAccessor". We had to change it late in MVC 2's ship cycle.
The purpose is to delay retrieving the actual value of the model until such point as you know you're going to need it (that is, until you call ModelMetadata.Model).
The problem it solves is actually a rather esoteric one related to model binding against a LINQ to SQL class that has a foreign key reference in it. The problem is, if you've retrieved the child object which is represented by a foreign key relationship (which usually means a delay load of that object), then you're no longer allowed to choose a new child object by setting the foreign key ID property. It's very common to model bind the foreign key ID (and not the whole foreign key entity) when model binding, but if we'd retrieved the foreign key entity object (for the purposes of populating the ModelMetadata class) then that binding would no longer be legal, and actually throw an exception. Since ModelMetadata is used for both directions of models -- inbound, via model binding, and outbound, via HTML generation -- we needed to introduce the layer of indirection to protect your ability to use it in both scenarios without disrupting LINQ to SQL's rules.
The modelAccessor parameter does not point to an instance of the object, but rather it is a function that will access some attribute of your object. The Func "encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter." For example, if we have following class:
public class Bar(){
[DisplayName("I am Foo.")]
public string Foo{get;}
}
When the CreateMetaData is called, it will be to create meta data for the Foo property and the modelAccessor will be a function that returns the value of Foo.
I did a little digging and found a way to get to the instance of the object, but it requires using reflection. You can do the following to get the Bar class in my example:
if (modelAccessor != null)
{
//Use reflection to get the private field that holds the Bar object.
FieldInfo container = modelAccessor.Target.GetType().GetField("container");
//Invoke field on the modelAccessor target to get the instance of the Bar object.
Bar myObject = (Bar)container.GetValue(modelAccessor.Target);
}
I've only run this against a simple test case, so your mileage may vary, but hopefully this will help clarify what is going on.

Entity Framework Validation & usage

I'm aware there is an AssociationChanged event, however, this event fires after the association is made. There is no AssociationChanging event. So, if I want to throw an exception for some validation reason, how do I do this and get back to my original value?
Also, I would like to default values for my entity based on information from other entities but do this only when I know the entitiy is instanced for insertion into the database. How do I tell the difference between that and the object getting instanced because it is about to be populated based on existing data? Am I supposed to know? Is that considiered business logic that should be outside of my entity business logic?
If that's the case, then should I be designing controller classes to wrap all these entities? My concern is that if I deliver back an entity, I want the client to get access to the properties, but I want to retain tight control over validations on how they are set, defaulted, etc. Every example I've seen references context, which is outside of my enity partial class validation, right?
BTW, I looked at the EFPocoAdapter and for the life of me cannot determine how to populate lists of from within my POCO class... anyone know how I get to the context from a EFPoco Class?
This is in reply to a comment I left. Hopefully this answers your question, Shimmy. Just comment, and I will shorten it or remove it if it doesn't answer your question.
You will need both INotifyPropertyChanging and INotifyPropertyChanged interfaces to be implemented on your class (unless it is something like an entity framework object, which I believe implements these internally).
And before you set a value to this property, you will need to raise NotifyPropertyChanging.PropertyChanging event, using the name of the property in PropertyChangingEventArgs constructor.
And after you set this value you need to raise NofityPropertyChanged.PropertyChanged event, again using the name of the property this is being raised in PropertyChangedEventArgs constructor.
Then you have to handle the PropertyChanging and PropertyChanged events. In the PropertyChanging event, you need to cache the value. In the PropertyChanged event, you can compare and throw an exception.
To get the property from PropertyChanging/PropertyChanged event args, you need to use relfection.
// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it checks if e.PropertyName already exists.
propertyDict.Add(e.PropertyName, propertyValue);
} // End PropertyChanging() Event
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it makes sure e.PropertyName exists.
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
// No longer needed.
propertyDict.Remove(e.PropertyName);
if (/* some condition */)
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
} // End try
} // End if
} // End PropertyChanging() Event
Notice how I am using PreventRecursion, which is a boolean I forgot to add above these methods? When you reset the property back to its previous value, these events will be recalled.
tl;dr
Now you could derive a single event which inherits from INotifyPropertyChanged, but uses an argument which holds an Object representing the previous value as well as the Property Name. And that would reduce the number of events being fired down to one, have similar functionality, and have backwards compatibility with INotifyPropertyChanged.
But if you want to handle anything before the property gets set (say the property does an irreversible change or you need to setup other properties before setting that variable, otherwise an exception will be thrown) you won't be able to do that.
Overall, this method is a very old way of doing things. I would take Poker Villian's answer and have invalid data able to be entered. But disallow saving to a database.
Entity Framework has some excellent code towards validation. You add validation to your properties via attributes. And then it takes care of the work of processing those attributes. Then you can make a property called IsValid, which calls Entity Framework specific validation. It also distinguishes both field errors (like typing in the wrong characters or having a string too long), and class errors (like having missing data or conflicting keys).
Then you can bind IsValid to controls validation, and they will display a red bubble while invalid data is entered. Or you could just implement IsValid validation yourself. But If IsValid is false, SaveChanges event would need to cancel saving.
btw. The code provided will not compile and is pseudocode only (mixing vb and c#). But I believe it is much more descriptive than c# alone--showing exactly what is being handled.
Concerning your first question, I would simply implement the changes to the associations as business logic. For example, if you add a Teacher class with multiple Student, do not add students like
aTeacher.Students.Add(new Student)
instead, create a AddStudent method
public Student AddNewStudent(string name, string studentID)
{
Student s = new Student( name, studentID);
s.Teacher = this; // changes the association
return s;
}
That way you have full control on when associations are changed. Of course that what prevents another programmer from adding a student directly? On the Student side, you can set the Teacher setter to private (and change the constructor to accept a teacher or similar). On the teacher side, how to make the Students collection non-insertable? I'm not certain... maybe transforming it in a custom collection that doesn't accept inserts.
Concerning the second part of your question, you could probably use the OnVarNameChanging events. If the EntityState is 'New' then you can apply your logic that fetches the real values.
There is also an event that fires when you save changes (OnSavingChanges?) that you could use to determine which objects are new and set some values.
But maybe the simplest solution is to always set the defaults in the constructor and they will get overwritten if the data is loaded from the DB.
Good luck
Create a factory that produces instances for you depending on your need like:
getStudent(String studentName, long studentId, Teacher teacher) {
return new Student(studentName, studentId);
}
getStudentForDBInseration(String studentName, long studentId, Teacher teacher) {
Student student = getStudent(studentName, studentId);
student = teacher;
//some entity frameworks need the student to be in the teachers student list
//so you might need to add the student to the teachers student list
teacher.addStudent(student);
}
It's a serious lack not having an AssociationChanging (that inherits from CancelEventArgs) event.
It bothers me also very much, therefore I reported this to Microsoft Connect Please vote here!
And BTW, I also think this is also stupid that the PropertyChangingEventArgs doesn't inherit CancelEventArgs, since cancelling with an exception is not always the elegant solution, besides, throwing exceptions cost more performance than calling the OnPropertyChangingEvent then check for the returned e.Cancel, so does it cost less than raising the PropertyChangingEvent, which you anyway call them both.
Also an exception can be thrown at the handler anyway instead of marking e.Cancel as true, for those who insist to go the Exception way. Vote Here.
To maybe answer part of your question or expound on ADB's answer you can user ObjectStateManager.GetObjectStateEntry to find the state of the entities and write your custom default logic.
SaveChanges is the method on the context that you can use, or SavingChanges is the event that occurs before SaveChanges is called.
You can override SaveChanges and only call base.SaveChanges if you don't want to abort the change
There is also a ObjectMaterialized event for the context.
Between the two you can stick all your validation and creation code in one location, which may be appropriate if they are complex and include values of other objects etc..