0

I have a view that creates one main object (Author) and a list of other objects for it (Books). So the created object can return the books by calling author.Books.ToList() for example.

My problem is that I only want users to be able to set certain attributes of the book (name, date etc.). I do not want them to be able to inject the form with javascript and set the Price of a book.

How do I tell the framework that I want to bind author.Books[all].Name (and date), but want to discard author.Books[all].Price? I know I could just manually test it in the controller, but I felt like there is a better solution and I just can't quite put my finger on it.

Some code for context: An inputbox from the View:

<input data-val="true" data-val-required="The CanBeBorrowed field is required." id="books_0__CanBeBorrowed" name="books[0].CanBeBorrowed" type="checkbox" value="true"`>

You can see how adding extra input fields would corrupt the data. The controller:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Date,Books")]Author author {...}

(In my project, I have different classes with the same structure. That is why it looks silly creating all the books when creating the author.)

JC Hammer
  • 49
  • 5

1 Answers1

1

This exactly why we need to use ViewModels,

you can just set in ViewModel

[Editable(false)]
public decimal Price { get; set; }

and also in your

[HttpPost]
[ValidateAntiForgeryToken]
    public ActionResult Create([AuthorViewModel authorVm)
{
      var author = _repository.getById(authorVm.Id);
      //update only the fields of author object that user is allowed to   update.
      author.Name = authorVm.Name;
      author.Date = authorVm.Date;
}

you can read more about ViewModels and how to use them here and here

Community
  • 1
  • 1
pjobs
  • 1,247
  • 12
  • 14
  • Very good point, I completely overlooked this, shows I am still inexperienced. Thank you for your accurate answer. – JC Hammer May 09 '15 at 14:44