【问题标题】:Object recieved in method from ActionLink always null从 ActionLink 的方法中收到的对象始终为空
【发布时间】:2016-01-14 09:08:29
【问题描述】:

我环顾四周,发现很多人都遇到过这个问题。然而我的并不完全相同。虽然其他问题通常通过使用正确的 ActionLink 方法重载来解决,并通过确保方法中接收到的对象类型正确来解决,但这不是来的。

在这个示例代码中,变量根据所有其他来源都设置正确,但是方法中接收的用户对象始终为空。

我做了什么:

  • 检查放在 ActionLink 上的对象是否有数据(有)
  • 检查我收到的对象的类型是否正确,以及我发送的对象是否正确
  • 尝试改用 Ajax ActionLink 和 HttpPost 方法

这是代码先从后端,然后是前端

public void DeleteUser(User user)
    {
        using (EFEntity context = new EFEntity())
        {
            context.User.Attach(user);
            context.User.Remove(user);
            context.SaveChanges();
            Response.Redirect("~/Home/someView");
        }
    }

动作链接前端:

foreach (User user in Model.userList)
{
    <tr>
        <td>
            @{
            number = number + 1;
            }
            @number
        </td>
        <td>@user.Gid</td>
        <td>@user.Name</td>
        <td>@user.Email</td>
        <td>@user.Permissions.Perm</td>
        <td>@user.LastUpdated</td>
        <td>
                @Html.ActionLink("Delete", "DeleteUser", "Service", user, new { @class = "btn btn-danger" })
        </td>
    </tr>
}

【问题讨论】:

  • 您不应该在ActionLink() 中传递复合体。如果对象有很多属性,您很容易超过查询字符串并抛出异常(并且它创建的丑陋查询字符串)。您应该只传递用户的 ID 属性。
  • 而且您甚至不应该使用操作链接 - 您正在修改数据,因此它应该是 POST - 目前它添加了用户浏览器历史记录,并且可以轻松地再次导航到。充其量这将意味着进行不必要的数据库调用以删除当前不存在的内容,最坏的情况可能会引发异常。强烈建议您遵循常规做法。
  • @StephenMuecke 请详细说明转发和浏览器历史记录,不清楚您的意思。当您单击此按钮时,它会刷新页面,因此您无法选择两次删除相同的内容。还是我误解了你的意思?
  • 它是一个链接。任何使用都可以在地址栏中输入。当用户单击链接时,您的糟糕地址将被添加到他们的浏览器历史记录中,这意味着他们可以轻松打开浏览器历史记录页面并再次单击它(导致删除不再存在的内容 - 并可能引发异常)应该在循环中生成一个表单 - @Html.BegnForm("DeleteUser", "Service", new { ID = user.ID }, FormMethod.Post, null)) { }` 并将方法更改为[HttpPost] public ActionResult DeleteUser(int ID)
  • 如果你在发帖,那么通过模型(除了通过网络发送的微不足道的额外数据)没有任何不利之处,但它是不必要的。删除实体所需的只是 ID - 例如 this answer

标签: c# .net asp.net-mvc entity-framework actionlink


【解决方案1】:

我发现了这个问题,它有点奇怪,解决起来并不难。

仔细检查用户对象并查看浏览器中的源代码,您可以在对象上看到某种字符串,其中包含一堆数字以及带有“动态代理”的东西。

通过进一步的研究,我了解到对象始终为空的原因是因为该对象是使用动态代理选项生成的。由于某种原因,它本身以某种方式启用,仅在此特定 EF 模型上启用。

修复是在实体框架中全局禁用动态代理。

怎么做:

转到您的 Model.edmx -> Model.Context.tt -> Model.Context.cs

您将添加“Configuration.ProxyCreationEnabled = false;”行在您的实体模型的公共方法中。

之前的代码:

public partial class EFEntity: DbContext
    {
        public EFEntity()
            : base("name=EFEntity")
        {
        }
        ......
    }

之后的代码:

public partial class EFEntity: DbContext
        {
            public EFEntity()
                : base("name=EFEntity")
            {
                Configuration.ProxyCreationEnabled = false;
            }
            ......
        }

这应该全局禁用代理创建并且应该解决这个特定问题。

希望它对某人有所帮助,我几天来一直在努力找出问题所在

【讨论】:

  • “修复是在实体框架中全局禁用动态代理” - 不,正确的修复是使用视图模型而不是实体框架模型。如果您已经查看了生成的 HTML,您也不必在这个问题上花费数天时间。 :)
  • 当您只想知道要删除的内容时,我认为没有必要返回视图模型。您对我花了多长时间才发现问题的评论不是很有建设性,请您保持主题。无论您认为什么代码是更好的做事方式,都不是那么重要,因为这不是这里的问题。在这种情况下,即使使用视图模型也可能仍然会导致相同的问题,因为 EF 中的所有用户对象都是使用动态代理生成的。
  • 我刚刚发布了这个以防其他人遇到这个问题,因为我在搜索它时找不到任何帮助。所以要么解决他们的问题,要么引导他们走上正确的轨道
  • 的“答案”“我试图用一只鞋把这颗钉子钉在一块木头上,现在钉子已经弯曲了。我该如何拉直它?”还有“你可以用钳子把钉子弯回来拉直”。然而,问题和答案都没有解决真正的问题:“人们通常用锤子将钉子插入物体,这是更好的工具”。您不应该将您的数据层暴露给您的视图层,期间。它引入了像你在这里遇到的问题。人们仍然需要延迟加载和代理创建。
  • 另外,你在这个问题上花了多长时间是无关紧要的,所以请你把你的答案保持在主题上。我只是指出“为什么我的模型不绑定”很容易通过查看生成的 HTML 来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
相关资源
最近更新 更多