locked
Strange behavior on MVC RRS feed

  • Question

  • User-2108432106 posted

    Hello,
    I was faced with a functioning of MVC which seems very strange and I'd like to know if it is a bug or a normal behavior.
    Here is what I did:

    - Creation of a new MVC 5.1.1 with VS 2013 Update 1 (Version 12.0.30110.00)
    - Update of all packages NuGets
    - Creating a class named TestModel in folder Model

    public class TestModel
    {
       public int Id {get; set}
    }



    - Creating an action named Test in the Home Controller

    [HttpGet]
    public ActionResult Test(int? id)
    {
       return View();
    }



    * Note that I don't pass any parameters to the view.

    -Creating a razor view named Test in the folder Views/Home

    @model WebApplication1.Models.TestModel
    @Html.TextBoxFor(m=>m.Id)



    Now i'm calling the url : /Home/Test/55 that should return a page with the standard _Layout and an EMPTY textbox.

    Only here, in performing this test we note that the textbox displays 55...

    By what miracle the "id" parameter passed in the GET ended up in the context of the TextBoxFor?

    One more, if I add @Model.Id in the view, I'm an exception saying that the model is null (which is the expected behavior).

    Until now I had always believed that the parameter of the lambda expression (here "m") was a representation of the @Model of the view, but this test invalidate this hypothesis.

    This behavior seems to me be a serious security problem, because the GET parameter takes precedence over the model!,
    example: if I add this:

    public ActionResult Test(int? id)
    {
       return View (new TestModel {Id = 10});
    }



    and I change the view like this:

    @model WebApplication1.Models.TestModel
    @Model.Id @Html.TextBoxFor (m => m.Id)



    here I have the number 10 (coming from @Model.Id) followed by a textbox with the value... 55!

    The textbox has taken the value passed with the GET (so unsecure) rather than that I provide explicitly!
    Another inconsistency, if I wrote in the view this:

    @Html.TextBoxFor (m => Model.Id)



    now the textbox will set... 55 once again!

    For short, is this a bug or not?

    Thanks for your responses

    Note: after any other test I have found that this problem also exists on MVC 4

    Thursday, March 6, 2014 11:27 AM

Answers

  • User-2007877324 posted

    This behaviour is by design :)

    As you know MVC is built on conventions and this may fall into that. Your model and the input parameter has the same name "id", you are getting this issue.

    When populating the textbox, MVC checks whether there is a value in the Request stream. If there is a value use it. The idea behind is to give preference to what user entered or provided. For example if user entered 20 in your text box and click submit button, when the page reloads you want to show 20 to the user and not the default value. Treat it something like viewstate in asp.net webforms.

    If you don't want the passed in id to be shown in the view, you can remove it from the ModelState. Just have this code in the controller action

    ModelState.Remove("id")

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 6, 2014 6:44 PM

All replies

  • User-1202308568 posted

    You have a misspelling in your property (extra closing bracket):

    public int Id {get; set};}

    should be

    public int Id {get; set;}

    Thursday, March 6, 2014 11:30 AM
  • User-2007877324 posted

    This behaviour is by design :)

    As you know MVC is built on conventions and this may fall into that. Your model and the input parameter has the same name "id", you are getting this issue.

    When populating the textbox, MVC checks whether there is a value in the Request stream. If there is a value use it. The idea behind is to give preference to what user entered or provided. For example if user entered 20 in your text box and click submit button, when the page reloads you want to show 20 to the user and not the default value. Treat it something like viewstate in asp.net webforms.

    If you don't want the passed in id to be shown in the view, you can remove it from the ModelState. Just have this code in the controller action

    ModelState.Remove("id")

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 6, 2014 6:44 PM
  • User-2108432106 posted

    Thanks for the reply.

    It is something really disturbing because sometimes the parameters of the Action come from a completely different context where "id" has not the same meaning as the "id" provided to the ViewModel...

    Now that I know it, I'll be able to adapt my code.

    Thanks again

    Friday, March 7, 2014 2:40 AM