tags:

views:

38

answers:

3
+1  Q: 

mvc modelbinding

hi,

I have an Edit action/view for my User object, but only want a few fields to be editable.

I've set up the view to bind to the User object, and am using Html.EditorFor() for the few fields that I want to be editable.

I noticed in my User object on Post:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditUser(Mynamespace.User user)
{ }

that only the fields that I provided .EditorFor() controls for actually have any data.
I tried using Html.Hidden(Model.ID) for one of the fields that i didn't want to be editable, but it is null in the new User object created from model binding.

So, my question- How do I bind where only a couple of the fields should be editable?

Thanks!

+1  A: 

Are you using the strongly-type helper for the hidden field or is it exactly like you've typed. If you've got it exactly as typed, then the name of the hidden field is the value of the id, not the name of the property on the model (ID). You might want to change it to:

<%= Html.Hidden( "ID" ) %>

or (if using strongly-typed helpers)

<%= Html.HiddenFor( m => m.ID ) %>
tvanfosson
keep in mind that this technique can easily allow someone to edit a different record that was rendered. This might be okay in your application, but it's quite dangerous on public apps.
Ben Scheirman
Yes. You need to have security to make sure that the logged in user is enabled to make modifications to the particular record in question. I use a custom attribute on the update method to check if the current user is in a proper role or is the owner of the data being updated.
tvanfosson
It will not let me use ( m => m.ID ) with a html.Hidden helper. (this is how I am accessing the model data for the EditorFor() fields, however. Do you know why that is?
jj
Sorry -- need to use HiddenFor to get the strongly-typed version. I'm still using MVC 1.0...
tvanfosson
+1  A: 

It sounds like you probably want to start thinking about using a View Model that is specific to the form/input that you're dealing with. But in the short term, ....

You could bind to a FormCollection parameter instead and copy the values manually, OR...

you can use the TryUpdateModel method to populate this existing user object with the new data.

Here's the documentation for TryUpdateModel: http://msdn.microsoft.com/en-us/library/dd470756.aspx

It's still possible for malicious users to send phony form-values that map to real properties on your model, so to protect against this (like an employee changing his salary property with a simple form hack) you can introduce an interface that contains the white list properties that you allow.

Here's an example:

public interface IUserEditableFields
{
   string Username {get;set;}
   string Email {get;set;} 
}

//... in the controller action

if(TryUpdateModel<IUserEditableFields>(user)) {
   //validation passed
   //only Username and Email were editable
}

This is a good resource on how to do this: http://css.dzone.com/news/aspnet-mvc-think-before-you-bi

Ben Scheirman
+1  A: 

Ben's answer is largely correct, in that a ViewModel might be more appropriate, and short of that, TryUpdateModel can be used. However, I add that in that case, rather than requiring the domain object to implement a new interface, you use the overload TryUpdateModel<T>(T, string[]), which allows you to whitelist the updateable properties in a string array by name.

gWiz