Asp.net核心模型不受形式约束

时间:2016-10-21 08:41:05

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

我从第三方静态页面(由Adobe 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]}

9 个答案:

答案 0 :(得分:33)

注意不要为action参数指定一个与model属性相同的名称,否则binder将尝试绑定到参数并失败。

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

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

更改操作参数&#39; email&#39;使用不同的名称,它将按预期绑定。

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

答案 1 :(得分:1)

我不确定是不是同样的情况,但是我遇到了同样的问题,没有什么能真正为我工作 我的问题是我的视图模型类中有一个名为Model的属性

public string Model { get; set; }

当我将属性重命名为ModelName时,即使没有FromForm属性,一切都恢复正常。

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

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

希望这有帮助。

答案 2 :(得分:1)

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
   {

   }

答案 3 :(得分:0)

void 更改为 ActionResult

[HttpPost]
public ActionResult Index(EmailModel email)

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

// to your form in view 
@Html.AntiForgeryToken()
// ------------

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(EmailModel email)

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

我今天遇到了这个问题,尽管事后看来似乎很明显,只是以为我要补充一下,您需要确保要绑定的模型上Properties的访问修饰符正确。我在某些物品上装有public MyProperty { get; internal set; },它们将不会束缚。删除了internal,它们工作正常。

答案 6 :(得分:0)

就我而言,我使用的是MVC 4.0约定来命名要发布的对象。例如,

  

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

     

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

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

答案 7 :(得分:0)

我遇到了以下问题:当我在基础模型上有多个构造器时,模型不绑定:

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

答案 8 :(得分:0)

我遇到了同样的问题,我想分享我的案子发生的情况以及如何获得解决方案。也许,有人可能会觉得有用。

我的上下文是 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发现表单数据与参数名称匹配,然后开始正确绑定。我的问题解决了。