How to Preserve/Protect Certain Fields in Edit in ASP.NET MVC

In an Edit action in ASP.NET MVC, certain fields can be hidden from user with HiddenFieldFor. However this doesn’t protect the fields (such as ID, data creation date) from being edited.

For example, a model Student has fields Id, Name and Birthday. I like to allow users to update the Name, but not Id nor Birthday.

For an Edit action like this

public ActionResult Edit(Student student)
{
    if (ModelState.IsValid)
    {
        db.Entry(student).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(student);
}

How can I prevent Id and Birthday from being edited? Thanks!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You should use a view model which contains only the properties that you want to be edited:

public class EditStudentViewModel
{
    public string Name { get; set; }
}

and then:
public ActionResult Edit(StudentViewModel student)
{
    ...
}

Another technique which I don’t recommend is to exclude certain properties from binding:
public ActionResult Edit([Bind(Exclude = "Id,Birthday")]Student student)
{
    ...
}

or include:
public ActionResult Edit([Bind(Include = "Name")]Student student)
{
    ...
}

Method 2

I assume you have to have the properties in your Model so that in View you can use them to render useful information e.g. an ActionLink with ID or some readonly Text.

In this case you can define your model with an explicit binding:

[Bind(Include = "Name")]
public class Student
{
    int Id { get; set; }
    int Name { get; set; }
    DateTime Birthday { get; set; }
}

This way when updating your model, if the user submits an extra Id it will not be bound.

Another idea I like is having your model know its bindings per scenario and have them compiler validated:

public class ModelExpression<T>
{
    public string GetExpressionText<TResult>(Expression<Func<T, TResult>> expression)
    {
        return ExpressionHelper.GetExpressionText(expression);
    }
}

public class Student
{
    public static string[] EditBinding = GetEditBinding().ToArray();

    int Id { get; set; }
    int Name { get; set; }
    DateTime Birthday { get; set; }

    static IEnumerable<string> GetEditBinding()
    {
        ModelExpression<Student> modelExpression = new ModelExpression<Student>();
        yield return modelExpression.GetExpressionText(s => s.Name);
    }
}

This way in your Action when calling TryUpdateModel you can pass this information.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x