Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the model binder need an empty constructor

Tags:

c#

asp.net-mvc

I need some help with some fundamentals here...

I have this controller that serves up my view with an instance of a class (at least that's how I think it works). So since I am giving my view a new instance of the object, why does it have to create a NEWer one for the model binding for my post back? Please look at the below example.

[HttpGet]
public ActionResult Index(){
  int hi = 5;
  string temp = "yo";
  MyModel foo = new MyModel(hi, temp);
  return View(foo);
}
[HttpPost] 
public ActionResult Index(MyModel foo){
  MyModel poo = foo;
  if(poo.someString == laaaa)
    return RedirctToAction("End", "EndCntrl", poo);
  else
    throw new Exception();
}

View:
@model myApp.models.MyModel

@html.EditorFor(m => m.hi) 
<input type="submit" value="hit"/>

Model:
public class MyModel {
 public int hi {get; set;}
 public string someString {get; set;}
 public  stuff(int number, string laaaa){
  NumberforClass = number;
  someString = laaaa;
 }
}

Why do I need a blank constructor? Furthermore, if I had an parameterless constructor, why would poo.someString change by the time I got to RedirctToAction("End", "EndCntrl", poo)?

like image 438
S1r-Lanzelot Avatar asked Feb 11 '23 08:02

S1r-Lanzelot


1 Answers

Why do I need a blank constructor?

because of

[HttpPost] 
public ActionResult Index(MyModel foo){ ... }

You asked the binder to give you a concrete instance on Post, so the binder needs to create that object for you. Your original object does not persist between the GET and POST actions, only (some of) its properties live on as HTML fields. Thats what "HTTP is stateless" means.

It becomes a little more obvious when you use the lower level

[HttpPost] 
public ActionResult Index(FormCollection collection)
{ 
      var Foo = new MyModel();
      // load the properties from the FormCollection yourself
}

why would poo.someString change by the time I got to RedirctToAction("End", "EndCntrl", poo)?

Because someString isn't used in your View. So it will always be blank when you get the new model back. To change that:

@model myApp.models.MyModel    
@html.HiddenFor(m => m.SomeString) 

@html.EditorFor(m => m.hi) 
<input type="submit" value="hit"/>

this will store the value as a hidden field in the HTML and it will be restored for you on POST.

like image 66
Henk Holterman Avatar answered Feb 13 '23 03:02

Henk Holterman