views:

43

answers:

2

Hello,

today I've got some interesting observation, that I need to explain. I've got my Person class that is described as above:

public class Person
{
   public int Id { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

now in my MVC2 application I've got PersonController with following edit metod:

public ActionResult Edit(int id)
{
    var permission = _service.GetPerson(id);
    return View(person);
}

[HttpPost]
public ActionResult Edit(Person person)
{
    if (ModelState.IsValid)
    {
        _service.UpdatePerson(permission);
        return RedirectToAction("Index");
    }

    return View(person);
}

Now on my Edit.aspx view I have form that contains only FirstName and LastName, but what suprise me when the post is done in my controller the Person object have an Id setted correctly (which was not part of a form).

Now I guess that it's taken from the rout value of an id parameter, that is send in my action address, but is it save? I mean.. It's nice that I do not have to put hidden field for id, but is there any danger caused by mixing get and post parameters in mvc2?

And one more concern. What if I do put hidden for id. Then it will be sent both ways (get and post), so then.. which id will be used?

+2  A: 

Yes it is taken from the route. It is dangerous because if you rename this property on the Person class your code might break. Also if you change the route the same might happen.

And to answer your second question. Assume the following form:

<form action="/home/edit/5" method="post">
    <input type="text" name="Id" value="1" />
    <input type="submit" value="Go" />
</form>

In this case the Id will be taken from the POST request and not the route.

Darin Dimitrov
okay.. so whats in the situation i descrbed (after edit) on the bottom of my question?
ŁukaszW.pl
@Darin is that really true? Well, the first one is from the route ofcourse but the second one should be from a hidden field because the view he is using is strongly typed for Person (I guess it is). When posting to the edit there is no Id in the route, only in the post values
Oskar Kjellin
No, it's not taken from the route. The Person object gets generated in the first Controller, which is then displayed. The same Person object gets send to the second controller and updated in the database. Renaming the parameter in the GET would only have an effect in the first method.
Femaref
@Oskar, @Femaref, the OP explicitly said that there's no ID parameter in the form, only firstnmame and lastname. Aren't you reading the question carefully? Then he asks how is this id property populated assuming that there's no corresponding field in the form and of course that it comes from the route.
Darin Dimitrov
@Darin but MVC generates a hidden field for him
Oskar Kjellin
@Oskar, What are you talking about? MVC generates nothing unless told so. Assuming such things without even seeing the View is not good. Just try a plain old HTML `form` containing plain old `inputs` without any helpers or something and you will see.
Darin Dimitrov
@Darin but if you have view that is strongly typed it will
Oskar Kjellin
@Oskar, NO it won't. Having a strongly typed view means that the Model property in this page is strongly typed. That's all. It generates nothing. I think you are completely missing the point here.
Darin Dimitrov
@Oskar, @Darin - Darin is right of course. Proof - when I saw sended form in `firebug` there is no id field send by `post`. MVC sends only those parameters that are coming from the post.. For me it was just strange that it puts the root values into my `Person` object too..
ŁukaszW.pl
Okay.. as far Darin told me that it's not good to read id from how can I be sure that it will process post'ed id with highier priority then the id from the route.. Is it always true?
ŁukaszW.pl
Yes it is always true in this version of ASP.NET MVC. It might not be true in future versions, so relying on things like this seems brittle to me.
Darin Dimitrov
I think I might've been mistaken here. After looking through my views it seems like I put my own hidden field there every time... sorry
Oskar Kjellin
@ŁukaszW.pl, this is to say that you should use one of the two ways to populate the Id but avoid having both an input field and a route parameter with the same name.
Darin Dimitrov
Thank you Darin, your answer is great ;)
ŁukaszW.pl
+1  A: 

when mvc default model binder binds objects it looks for its values in many places and matched route is one of those places. if u change ur property name from id to personID it will not get populated from route value and u have to put hidden field in ur form to get it there. to avoid such confusion i always name properties different from route parameters.

Muhammad Adeel Zahid