【问题标题】:Why does the model binder need an empty constructor为什么模型绑定器需要一个空的构造函数
【发布时间】:2023-04-08 19:19:01
【问题描述】:

我在这里需要一些基础知识方面的帮助...

我有这个控制器,它为我的视图提供一个类的实例(至少我认为它是这样工作的)。所以,既然我给我的视图一个新的对象实例,为什么它必须为我的回发的模型绑定创建一个新的实例?请看下面的例子。

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

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

【问题讨论】:

  • 阅读本文,了解模型绑定如何工作的基础知识。 msdn.microsoft.com/en-us/magazine/hh781022.aspx
  • 你在说什么空构造函数?我在您的示例中看到的唯一构造函数是“stuff(int number, string laaaa)”
  • 请使您的代码保持一致,仅发布实际编译的内容。 class stuff != class MyModel, hi != NumberforClass

标签: c# asp.net-mvc


【解决方案1】:

为什么我需要一个空白的构造函数?

因为

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

您要求活页夹在 Post 上为您提供一个具体实例,因此活页夹需要为您创建该对象。您的原始对象不会在 GET 和 POST 操作之间持续存在,只有(部分)其属性作为 HTML 字段存在。这就是“HTTP 是无状态的”的意思。

当你使用较低级别时会变得更明显

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

为什么当我到达RedirctToAction("End", "EndCntrl", poo) 时 poo.someString 会发生变化?

因为someString 未在您的视图中使用。所以当你拿回新模型时它总是空白的。要改变它:

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

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

这会将值作为隐藏字段存储在 HTML 中,并将在 POST 时为您恢复。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      我对这个问题有点困惑,但你有没有试过这个:

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

      如果你添加了一个参数化的构造函数,你只需要一个无参数的构造函数。

      例如:MyObject item = new MyObject();

      【讨论】:

        【解决方案4】:

        只要您不定义任何构造函数,它就不需要无参数构造函数。如果定义带参数的构造函数,则需要一个无参数构造函数,因为它是模型绑定器使用的构造函数..

        当您回发值时,活页夹会将您的请求映射到类型化对象中,它首先创建对象,然后尝试将您发布的值映射到某个属性。

        如果你不能有一个无参数的构造函数......如果代码不在你的控制之下,那么你必须创建一个自定义活页夹。

        【讨论】:

        • 它确实需要一个无参数的ctor。如果您不定义自己的 ctor,c# 编译器会自动为您添加一个这一事实并不意味着模型绑定不需要一个。
        • 耶耶...这就是我含蓄地说的!但也许你就是这样的教授?
        • 不,你没有在任何地方暗示它,事实上你暗示不是这样。而且这不是学术的东西,有些人还不知道c#编译器会为你插入一个默认的构造函数。
        猜你喜欢
        • 2021-06-17
        • 1970-01-01
        • 2016-10-05
        • 2012-12-25
        • 2018-02-27
        • 1970-01-01
        • 2019-10-14
        相关资源
        最近更新 更多