【问题标题】:Asp.net core model doesn't bind from formAsp.net 核心模型不从表单绑定
【发布时间】:2017-03-03 11:51:08
【问题描述】:

我从 3rd-side 静态页面(由 Adob​​e Muse 生成)捕获发布请求并使用 MVC 操作处理它。

<form method="post" enctype="multipart/form-data">
   <input type="text" name="Name">
   ...
</form>

空表单动作的路由:

app.UseMvc(routes => routes.MapRoute(
   name: "default",
   template: "{controller=Home}/{action=Index}"));

但是在相应的操作中,我的模型每个属性都是空的

行动:

[HttpPost]
public void Index(EmailModel email)
{
   Debug.WriteLine("Sending email");
}

型号:

public class EmailModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Company { get; set; }
    public string Phone { get; set; }
    public string Additional { get; set; }
}

Request.Form 包含表单中的所有值,但模型为空

[0] {[Name, Example]}
[1] {[Email, Example@example.com]}
[2] {[Company, Hello]}
[3] {[Phone, Hello]}
[4] {[Additional, Hello]}

【问题讨论】:

  • 你为什么使用enctype="multipart/form-data"?您无需指定此项,因为您的模型不包含任何文件上传。可能您的问题由此引起。删除并尝试。
  • @ademcaglin 删除了 enctype 属性。没有帮助。 Request.Form 仍然具有所有值,但 model 为空。
  • 您是否使用任何 javascript 代码发送表单?
  • @ademcaglin 不,只是纯表单提交

标签: c# asp.net forms asp.net-core model-binding


【解决方案1】:

注意不要为动作参数指定与模型属性相同的名称,否则绑定器将尝试绑定到该参数并失败。

public async Task<IActionResult> Index( EmailModel email ){ ... }

public class EmailModel{ public string Email { get; set; } }

将操作参数“电子邮件”更改为不同的名称,它将按预期绑定。

public async Task<IActionResult> Index( EmailModel uniqueName ){ ... }

【讨论】:

  • 谢谢!我的视图模型中有一个名为“Model”的属性,它破坏了绑定。
  • 似乎 ASP.NET Core 的模型绑定代码可能会在这种情况下抛出异常,从而使我们感到震惊!
  • 我的意思是......哇......这是我自己找不到的东西。
  • 你是我的天使!
  • 好吧,那是一个小时的毫无意义的调试,我再也回不来了。
【解决方案2】:

我不确定这是不是同样的情况,但我遇到了同样的问题,没有什么对我有用。
我的问题是我的视图模型类中有一个名为 Model 的属性

public string Model { get; set; }

当我将属性重命名为 ModelName 时,一切都再次正常工作,即使没有 FromForm 属性。

看起来一些特殊的属性名称对于 asp.net mvc 模型绑定可能有点问题。

所以,我的建议是检查您的模型属性,也许尝试一一重命名,以检查问题是否存在。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    我也遇到了同样的问题 这个文档帮助我理解模型绑定 https://docs.asp.net/en/latest/mvc/models/model-binding.html

    我通过确保属性名称与表单字段名称完全匹配解决了我的问题 我还添加了 [FromForm] 属性来准确指定绑定源。

    【讨论】:

      【解决方案4】:

      我今天遇到了这个问题,虽然事后看来这很明显,但我想补充一点,您需要确保您要绑定的模型上的属性的访问修饰符是正确的。我有一些public MyProperty { get; internal set; },它们不会绑定。删除了internal,它们工作得很好。

      【讨论】:

      • 天哪,这就是我遇到的问题。如果没有您的出色帮助,我永远不会想到这一点。谢谢!!
      【解决方案5】:

      ASP.Net Core 3.1

      就我而言,我使用的是 Ajax 发布的复杂模型(包含其他模型的模型,例如共享模型),因此视图中的输入自动命名为“ChildModel.PropertyName”(参见代码)

         [HttpPost]
         [ValidateAntiForgeryToken] // ("AUVM.PropertyName")
         public async Task<JsonResult> AddUser([FromForm]AUVM aUVM) //Parameter name must match the first part of the input name in order to bind
         {
      
         }
      
         [HttpPost]
         [ValidateAntiForgeryToken]
         public async Task<JsonResult> AddUser([FromForm]AUVM someUniqueName) //This is wrong and won't bind
         {
      
         }
      

      【讨论】:

        【解决方案6】:

        void 更改为 ActionResult

        [HttpPost]
        public ActionResult Index(EmailModel email)
        

        并且不要忘记从您的视图和操作中验证 AntiForgeryToken。

        // to your form in view 
        @Html.AntiForgeryToken()
        // ------------
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(EmailModel email)
        

        【讨论】:

        • 没有帮助。我也不能使用AntiForgeryToken,因为这个页面不是我的,而是由 3rd 方工具 (Adobe Muse) 生成的
        • 我认为您无法使用不在操作视图中的工具将其作为模型。您可以尝试使用表单获取方法获取价值,而不是作为模型。按参数名称。索引(字符串名称、字符串电子邮件、字符串公司、字符串电话)。并在过程中将此值转换为您的对象模型。
        • 我也认为 mvc 找不到模型什么的,是的,我可以使用一堆动作参数,或者用Request.Form 填充它,或者尝试用@987654325 来做@,我只是想了解为什么我不能只使用默认模型绑定。也许我错过了一些约定?
        【解决方案7】:

        如果请求模型中的一个或多个属性未能绑定到请求模型上的可接受值,也会发生此问题。

        在我的例子中,我应该将 List&lt;string&gt; 类型传递给属性,但不小心传递了 string。这导致整个请求模型变为null

        【讨论】:

          【解决方案8】:

          在我的例子中,我使用 MVC 4.0 命名您发布的对象的约定。例如,

          js:$http.post("SaveAnswer", { answer: answerValues })

          C#:public ActionResult SaveAnswer([FromBody] AnswerVM answer) {...}

          当我将 js 更改为 $http.post("SaveAnswer", answerValues) 时,一切正常。

          【讨论】:

            【解决方案9】:

            我遇到了这个问题,当我在底层模型上有多个构造函数时,模型不会绑定,例如:

            public class EmailModel
            {
                public EmailModel()
                {}
            
                public EmailModel(string _name, string _company)
                {
                    Name = _name;
                    Company = _company;
                }
                public string Name { get; set; }
                public string Email { get; set; }
                public string Company { get; set; }
                public string Phone { get; set; }
                public string Additional { get; set; }
            }
            

            通过删除除一个构造函数之外的所有构造函数来修复:

            public class EmailModel
            {
                public EmailModel()
                {}
            
                public string Name { get; set; }
                public string Email { get; set; }
                public string Company { get; set; }
                public string Phone { get; set; }
                public string Additional { get; set; }
            }
            

            【讨论】:

              【解决方案10】:

              我遇到了同样的问题,我想分享我的案例中发生的事情以及我是如何得到解决方案的。也许,有人可能会觉得知道它很有用。

              我的上下文是 ASP.NET Core 3.1 Razor 页面。 我有一个处理程序

              public async Task<JsonResult> OnPostLogin([FromForm] LoginInput loginData)
              {
                
              }
              

              而且我的 ViewModel 中有一个属性

                public LoginInput LoginInput { get; set; }
              

              在我的 Razor 页面中,我使用了这样的表单:

               <form asp-page-handler="Login" method="post">
              
               <input asp-for="LoginData.UserNameOrEmail">
              
               .....
               
                      
              

              因此,请注意,在我的表单中,我使用了属性 LoginInput.UserNameOrEmail,但在我的处理程序参数中,我使用了参数名称 loginData。 ASP.NET Core 怎么会知道,这个 LoginInput.UserNameOrEmail 实际上是 loginData.UserNameOrEmail。它不能,对吧?因此,它没有绑定我的表单数据。

              然后,当我将 ViewModel 属性“LoginInput”重命名为与处理程序参数相同的名称时,如下所示:

              public LoginInput LoginData { get; set; }
              

              ASP.NET Core 然后发现表单数据与参数名称匹配,然后开始正确绑定。我的问题解决了。

              【讨论】:

                猜你喜欢
                • 2018-06-22
                • 2019-11-14
                • 1970-01-01
                • 2021-08-03
                • 2022-12-16
                • 1970-01-01
                • 1970-01-01
                • 2019-04-08
                • 1970-01-01
                相关资源
                最近更新 更多