Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.NET MVC 2 DataAnnotations UpdateModel<T> validation

I'm trying to use DataAnnotations to add validation to my models in asp.NET MVC 2 RC2, using TryUpdateModel

        var user = UserManager.Find(id);

        this.TryUpdateModel<IProvisioningObject>(user, form.ToValueProvider());

This updates the model, but the validation is never called. I tried using TryUpdateModel as well (which is the direct type of user), not using the form value provider, using ProvisioningObject directly (which has the validation metadata), to no avail.

Googling for examples only gives me ways to use DataAnnotations by binding through a parameter

public ActionResult Update(User user)

Which I dislike for update scenarios.

Any tips and/or solutions?

EDIT My objects are auto-generated objects from a WCF service.

I made partials to be able to add DataAnnotations. I call TryUpdateModel three times because it apparently doesn't support inheritance, which I think is also my problem with DataAnnotations. I specify the validation attributes for ProvisioningObject, and the binding doesn't look for inherited stuff like that.

[MetadataType(typeof(ProvisioningObjectMetadata))]
public partial class ProvisioningObject : IProvisioningObject
{
    public string DisplayNameInvariant { get { return string.IsNullOrEmpty(this.DisplayName) ? this.Name : this.DisplayName; } }
}


[MetadataType(typeof(UserMetadata))]
public partial class User : IUser
{
}


public class ProvisioningObjectMetadata
{
    [DisplayName("Country")]
    public string CountryIsoCode { get; set; }

    [Required(ErrorMessageResourceType = typeof(Properties.Validation), ErrorMessageResourceName = "DisplayNameIsRequired")]
    [TempValidator]
    public string DisplayName { get; set; }
}


public class UserMetadata
{
    [DisplayName("Username")]
    public string Name { get; set; }
}


// Controller action
    public ActionResult Update(string id, FormCollection form)
    {
        var user = UserManager.Find(id);

        this.TryUpdateModel<IUser>(user.User, form.ToValueProvider());
        this.TryUpdateModel<IPerson>(user.User, form.ToValueProvider());
        this.TryUpdateModel<IProvisioningObject>(user.User, form.ToValueProvider());

        if (ModelState.IsValid) // always true
        {
            return Redirect;
        }
        else
        {
            return View();
        }
    }

If I add the metadata for DisplayName in UserMetadata, it works as expected, but that seems very redundant for nothing. And it would mean I would also have to copy/paste all my inherited interfaces so TryUpdateModel behaves appropriately.

I guess I'm looking for a way that doesn't require me to copy and paste my validation attributes to inherited classes.

like image 775
Christian Droulers Avatar asked Nov 05 '22 16:11

Christian Droulers


1 Answers

New Answer:

"My objects are auto-generated objects from a WCF service."

Autogenerated objects won't have any attributes on them. Are you defining your objects and their attributes on the server side or on the client side?

Old Answer: If your metadata is not on IProvisioningObject then no validation will be called. The MVC2 default model binder only knows how to find "extra" [MetadataType(buddyClass)] validation information.

For update scenarios bind against DTOs and then map the DTOs, if IsValid() to your main model classes.

like image 106
John Farrell Avatar answered Nov 11 '22 16:11

John Farrell