views:

113

answers:

5

For some reason, the edit action below get to the edit view form fine, but when I hit submit on my view page to post on the second method below, the companyToEdit structure do not contain the companyID and I get an exception. This is weird since, I have done this before and I get the id field in other instances.

If I put in the view the section of code below:

            <p>
                <label for="CompanyID">CompanyID:</label>
                <%= Html.TextBox("CompanyID", Model.CompanyID) %>
                <%= Html.ValidationMessage("CompanyID", "*") %>
            </p>

Then it will work just fine. But if I take that away, since the CompanyID is a read-only field it stops working. Any ideas?

    //
    // GET: /Company/Edit/5

    public ActionResult Edit(int id)
    {
        var companyToEdit = _repository.GetCompany(id);
        return View(companyToEdit);
    }

    //
    // POST: /Company/Edit/5

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id, Company companyToEdit)
    {
        if (!ModelState.IsValid)
            return View();
        try
        {
            _repository.Update(companyToEdit);
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

EDIT 2: I guess I can do something similar to this, and hide the ID in a hash value like the one below. I think this will be the ultimate solution, where we will get the most secure and the less complexity.

<input id="fkey" name="fkey" type="hidden" value="4a3d337bf38b35e9ff4167cfa878160b">
A: 

Try changing the name of your text box from CompanyID to companyToEdit.CompanyID. Also make sure these fields are enclosed within a form (i.e., using Html.BeginForm).

David Andres
The code works fine when I have CompanyID on the view page, the problem starts when I take that away, since I don't want the users to be touching the ID. Thanks for your fast response.
Geo
If you need the ID, but don't want to expose it to users, then you can always add a hidden input variable via Html.Hidden.
David Andres
Yes, but then any knowledgeable user is able to edit any other row by changing the value of the hidden field. right?
Geo
How are they going to change it? It's not visible to them. They'll have enough information (via View Source) to do a web request completely outside of the page, but that's a different issue altogether.
David Andres
@Geo You use a Guid then that problem is solved. Have you tried removed the (int id) part of Edit? And is the Id field readonly or does it have a setter
Chris S
Even a GUID won't help, because a user could exchange one guid for another by looking at the source of the page, using some tool like FireBug to swap the values of fields, and then post the page. It's very hacky, and I don't believe that there is a way around this other than using server-side caching of the entire set of data. This introduces its own issues, of course.
David Andres
A: 

you must have the id field on the edit form so just put it like this

<%=Html.Hidden("CompanyID",Model.CompanyID) %>
Omu
The OP wants the ID to not be written to the page in any form.
David Andres
A: 

you can store the id in the Session on the Edit (get) method and put it back in the Company object on the Edit (post) method

Omu
What happens if they have multiple tabs editing multiple companies?
mxmissile
I guess he could store a collection of "possible" id's in the session, then validate that on Post.
mxmissile
you can put the id of the session in a html.hidden after that you receive the value from hidden field and get the id from the session
Omu
and of course you can encode the id and put it in a html.hidden, but this is a form of showing the id in source of the page, somebody might click view source, copy the hash value and use it in the future
Omu
A: 

The obvious solution to the ID guessing you have suggested in the comments is to add another field to the Model called Key or similar, and make it a Guid, e.g.

public class User
{
    public int Id {get;set;}
    public Guid Key {get;set;}
}

You can then use this as a hidden field inside your View. You would benefit from making this an indexed column in the database (ideally you would make this the none-clustered primary key, and ditch the int for the Id field).

Then your view:

<%=Html.Hidden("Key",Model.Key) %>

Should automatically fill the parameter of the Controller method when it posts. If it doesn't then there may be a form tag issue.

Chris S
A: 

The variable name should match the textbox object name which is CompanyID or use request,form("CompanyID")

RK