14

Implementing custom DataAnnotationsModelMetadataProvider in ASP.NET MVC2.

Assuming the object that is being rendered looks like this:

- Contact : IUpdateable
 - Name: string
 - ContactType: (Lead, Prospect, Customer)

and the method below is in the context of Contact.ContactType meaning that:

  • meta.PropertyName == "ContactType"
  • meta.ContainerType == typeof(Contact)
  • meta.Model == ContactType.Lead

(the code under question:)

protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, 
 Type containerType,
 Func<object> modelAccessor, 
 Type modelType, string propertyName) {
 var containerInstance = meta.NotSureWhatGoesHere as IUpdateable;
 meta.IsReadOnly = containerInstance != null && containerInstance.CanBeUpdated(meta.PropertyName);
}

The question: How can I obtain the instance of Contact from the metadata? (replace NotSureWhatGoesHere with the correct one)?

Thanks.

asked Mar 9, 2011 at 3:36

3 Answers 3

11

The dirty way (tested in mvc3):

object target = modelAccessor.Target;
object container = target.GetType().GetField("container").GetValue(target);

It will return the model in model => model.Contact.Name instead of model.Contact. The rest is left as an exercise to the reader ;). This method comes, as all reflection based solutions poking around in non public data, without warranty.

answered Mar 31, 2011 at 14:38

3 Comments

That's an interesting trick! Will give it a shot later. Thanks.
It seems to be more complex than that. It will be necessary to traverse an Expression tree (and compile part of it) and magically find the container based on information I have in meta. Meta does not provide any details about the container instance that can identify the needed container instance (ContainerName and type are not enough to do that as there can many of them).
For others coming along to this solution, it either doesn't work in MVC2 or it's far more complex than this. We ended up going a different route and did not modify the Metadata Provider to gain access to the instance values.
2
answered Mar 9, 2011 at 22:41

3 Comments

Thanks a lot. It sounds very disappointing. Do you know if something has changed from MVC2 to MVC3 in this regard?
@Dmytrii, I haven't looked at this in MVC 3 yet.
It does not look like this has changed in MVC3 or MVC4. The CreateMetadata method is still only passed the Container Type, not the instance.
0

Isn't it what modelAccessor parameter is for?

Try:

var containerInstance = modelAccessor() as IUpdateable;
answered Mar 9, 2011 at 22:34

1 Comment

No, he's in the context of ContactType.Lead. modelAccessor() returns the same thing as meta.Model in this case; the only difference is that your code will fail if modelAccessor is null, but meta.Model returns null.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.