Why does the model binder need an empty constructor

I need help with some basics here ...

I have this controller serving my view with an instance of the class (at least the way I think it works). So since I am giving my view on a new object instance, why should it create a NEWer to bind the model for my post? Check out the example below.

[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 you need an empty constructor? Moreover, if I had a parameterless constructor, why poo.someString

change by the time I got to RedirctToAction("End", "EndCntrl", poo)

?

+3


source to share


4 answers


Why do you need an empty constructor?

due to

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

      

You asked the binder to give you a specific example in Post, so the binder should create that object for you. Your original object does not persist between GET and POST actions, only (some of) its properties live as HTML fields. That's what "stateless HTTP" means.

It becomes a little more obvious if you use a lower level



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

      

why does poo.someString change by the time I get to RedirctToAction("End", "EndCntrl", poo)

?

Because it is someString

not used in your view. Therefore, when you return a new model, it will always be empty. To change this:

@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 HTML and it will be restored for you in the POST.

+4


source


There is no direct relationship between the model you pass and the model you receive in the request. In the end, the code for the initial request and response will run on different IIS instances or even different machines.

Therefore, when returning an ASP.Net MVC request, all objects (controller, model, ...) must be recreated. Having a default constructor allows you to create a new object at runtime without knowing the specific arguments for your custom constructor.



Side note. A similar reconstruction for a constructor exists for generics where you can only specify a where T:new()

default constructor.

+1


source


I'm a little confused by the question, but you tried this instead:

[HttpPost] 
public ActionResult Index(MyModel foo){
  if(foo.someString == "laaaa")
    return RedirctToAction("End", "EndCntrl", foo);
  else
    throw new Exception();
}

      

You only need a parameterless constructor if you've added a parameterized constructor.

Ex: MyObject item = new MyObject ();

0


source


It doesn't need a constructor with a lower value since you don't define any constructors. If you are defining a constructor with parameters, you need a constructor with a smaller value than the one used by the model nexus.

when you return values, the binder will map your query to a typed object, it first creates the object and then tries to map your posted values ​​to some property.

If you can't have less constructor, if the code is not under your control, then you need to create a custom binder.

-1


source







All Articles