Guilherme Oderdenge
Guilherme Oderdenge

Reputation: 5011

Send just specified properties from a model to the view

The goal

Send just specified properties from a model to the view.

The scenario

Some time ago, my User model was the following:

public int Id { get; set; }

[Required]
public string Email { get; set; }

[Required]
public string Password { get; set; }

There's more properties to a user than Id, Email and Password, but until then, I wasn't using it because the unique proposal of this model was to authenticate someone on my application.

The time passed and now I have to add a new user into my application. To do this, I enhanced the User's model to this:

public int Id { get; set; }

[Required]
public string Email { get; set; }

[Required]
public string Password { get; set; }

[Required]
public string Firstname { get; set; }

[Required]
public string Lastname { get; set; }

And since then, I can't log in anymore — ModelState.IsValid returns me False instead of True.

I guess that the problem is something obvious: Firstname and Lastname are Required properties, and I'm sending nothing to it.

The problem

Based on the above's scenario, I have to ask: there's a way to use the same model for different proposals? Or, if you want: there's a way to use the same model twice? I mean, I need the same model to create a user and to authenticate a user and I really need to get the value of IsValid property as true like some time ago.

Upvotes: 1

Views: 208

Answers (2)

JTMon
JTMon

Reputation: 3199

(This will not work) Have you tried using the BindAttribute:

public ActionResult Add([Bind(Include = "Id,Email,Password") ]User userModel .....

you can also use it to exclude properties.

I stand corrected, the bind model is excellent for making sure that only certain properties are set on the model being submitted, but they do not help with the ModelState which still includes errors making it invalid. Solutions:

  1. simpler one: Go with separate viewModels for the different actions as suggested by @asymptoticFault
  2. If that is not feasible, or like me you like to torture yourself:), you can have a custom model binder for the User object, and based on the type of action being performed you can only populate certain properties while leaving others unset but with no modelstate errors.
  3. Implement a custom binder like above but this time override the OnModelUpdated method only and in it, based on the action being performed, you can clear the ModelState for the field(s) you don't want set (this can be used in conjunction with the Bind attribute).

Methods 2 and 3 might be an overkill especially method 2, but I felt I should contribute something after leading you down the wrong path with the Bind attribute :)

Upvotes: 2

asymptoticFault
asymptoticFault

Reputation: 4529

You could create a ViewModel that only encapsulates the properties you want to use in the view.

public class UserViewModel
{
    public int Id { get; set; }

    [Required]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

ViewModels are helpful for when your view will not correspond one-to-one with your business/domain object. Which will usually be the case for everything except CRUD views.

Upvotes: 1

Related Questions