How do I get a Strongly typed MVC view to post back the instance of the model it's passed?

724 Views Asked by At

So, I'm trying to take a view I wrote to create an instance of a model and use it to edit an existing instance from the database.

So, it's pretty simple to just pass in the existing instance by ID

public ActionResult Index(int id)
{
    return View(EntityContext.Policies.Where(x => x.ID == id).First());
}

The problem I'm having is that when the form posts:

@using (Html.BeginForm("Index", "Save", FormMethod.Post, new { @id = "form" }))
{
    <fieldset>
        ...
        @Html.TextBox("property")
        @Html.TextBoxFor("otherProperty")
        ...
        <input id="submit" type="submit" value="Save" />
    </fieldset>
}

The controller that it posts to :

public class SaveController : Controller
{
    VectorDaemonContext vdContext = new VectorDaemonContext();
    //
    // POST: /Save/
    [HttpPost]
    public ActionResult Index(Policy policy, string property, int otherProperty)        {
        //Stuff to do with the policy
    }
}

The controller gets a Policy object, but it only has the fields set in it that I've shown on the view and allowed to be edited

What I'd like to do is have the view post the instance it gets from the original controller. Is this something I can do simply?

The simplest way I know of to do this would be to make a hidden field on the view for the ID of the Policy, then hit the database to pull back the original instance. I'm already having to hit the database more than I'd like to because of some domain specific stuff, so if I can avoid this, I'd like to.

3

There are 3 best solutions below

0
Erik Funkenbusch On BEST ANSWER

Correction:

The simplest safest way I know of to do this would be to make a hidden field on the view for the ID of the Policy, then hit the database to pull back the original instance.

If you send the record in its entirety to the client, and then allow that client to post it back, you are giving total control over that record to the client even if you don't "allow" them to edit fields. Because a sneaky client can bypass your app and directly post any data they want and alter those fields. So, this is dangerous and insecure to do. Even if you trust your clients, it's just not a good idea.

The safe thing to do is only take the fields you want them to enter, and apply them to a record you retrieve from the database server-side. This way, only the data you allow them to update gets changed.

However, if you're bound and determined, the way to do this is to create hidden fields for all the variables you do not wish to have the users see or edit. If you want them to see the fields, but not edit, you could use textboxes and make the fields read-only (again, the user could bypass this, so it's not any real security). Or just display the data and use a hidden input.

A web browser will only post data that exists in form controls that are no disabled inside a form element. (or data you send in an ajax request). So any data you want posted back to the server must exist in controls.

0
beautifulcoder On

I would stick it in a hidden field. And yes, you can simply do it.

@Html.HiddenFor(m => m.ID)

I'm just taking a wild guess you have an ID defined in the model. But you can change it to whatever you want.

0
wvisaacs On

You have a several options, some of which you already know:

  1. Pass the id, and re-retrieve from the database
  2. Store the object in the model, hide its values in hidden fields, and pass it back whole
  3. Cache the object somehow, either in the session or another available caching mechanism (Storing an object in the session isn't really a good idea).

Because of the HTTP being stateless, your controller doesn't retain information on which model was sent to what client.