为什么模型绑定器需要一个空构造函数

时间:2015-04-24 21:22:22

标签: c# asp.net-mvc

我需要一些基本面的帮助...

我有这个控制器用一个类的实例来提供我的视图(至少我认为它是如何工作的)。因为我给我的视图一个新的对象实例,为什么它必须为我的帖子创建一个更新的模型绑定?请看下面的例子。

[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;
 }
}

为什么我需要一个空白构造函数?此外,如果我有一个无参数构造函数,为什么poo.someString会在我到达RedirctToAction("End", "EndCntrl", poo)时发生变化?

4 个答案:

答案 0 :(得分:6)

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.

答案 1 :(得分:2)

传递给视图的模型与您在请求中收到的模型之间没有直接连接。在最终的情况下,初始请求和响应的代码将在IIS的不同实例或甚至不同的机器中运行。

因此,当请求返回时,ASP.Net MVC需要重新创建所有对象(控制器,模型,...)。拥有默认构造函数允许运行时创建新对象,而无需了解自定义构造函数的特定参数。

附注:对于泛型,存在类似的构造函数重构,您只能为默认构造函数指定where T:new()

答案 2 :(得分:0)

I am a little confused by the question but instead have you tried this:

[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 added a parameterized constructor.

Ex: MyObject item = new MyObject();

答案 3 :(得分:0)

It doesn't need a parameter less constructor as long you do not define any constructors. If you define a constructor with parameters, you need then a parameter less constructor as it is the one used by the model binder..

when you postback the values, the binder will map your request in a typed object, it first creates the object, and then tries to map your posted values to some property.

If you can not have a parameter less constructor... if code is not Under your control, then you have to create a Custom binder.