Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 618
Jim Avatar asked Sep 25 '11 14:09

Jim


2 Answers

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)
{
    ...
}
like image 190
Darin Dimitrov Avatar answered Nov 16 '22 07:11

Darin Dimitrov


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.

like image 1
Atacan Avatar answered Nov 16 '22 07:11

Atacan