将一个大对象从视图传递给控制器​​上的操作

时间:2012-12-26 09:18:12

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我想从视图中将一个大对象传递给控制器​​的动作。像这样:

查看

<div>@Html.ActionLink("Send us an email", "Index", 
"Email", new { o = @Model.Exception }, null)</div>

控制器

public class EmailController : Controller
    {
        [AllowAnonymous]
        public ActionResult Index(object o)
        {
            new BaseServices.Emailer().SendEmail(o);

            return View();
        }

    }

问题是:传递的对象太大了,我猜MVC无法从中创建一个参数并将其添加到路由表/字典中。因此,我的电子邮件控制器的索引操作永远不会被调用。代码在两者之间的某处炸弹。

2 个答案:

答案 0 :(得分:5)

不,你不能这样做。 ASP.NET MVC不是一些 magic 。它依赖于标准的HTTP和HTML。正如您在使用GET请求时在HTTP中所知,没有 .NET对象的概念。您无法在Web应用程序中询问如何传递对象,因为这未定义。

有一个查询字符串参数的概念。这就是你能传递的东西=&gt;简单的查询字符串参数:

@Html.ActionLink(
    "Send us an email", 
    "Index", 
    "Email", 
    new { id = Model.Exception.Id, text = Model.Exception.Text }, 
    null
)

魔术的来源是ASP.NET MVC现在将使用2个简单的查询字符串参数(id和text)将它们映射到控制器操作中视图模型的相应属性。

但是当然为了工作,ASP.NET MVC需要知道模型的类型。您不能只使用object,因为此类型没有idtext属性。

所以:

public ActionResult Index(MyViewModel o)

现在但是发送复杂类型呢?那么,你必须问自己的问题是为什么首先将这种类型传递给视图?是因为用户应该编辑它的一些属性吗?那么你应该使用包含输入字段的HTML表单,允许用户编辑它们。

但是既然你已经将这个物体卡在锚中那么重点是什么?服务器可以从首先获取它的任何地方获取此对象。所以你需要的只是将一个简单的id传递给服务器:

@Html.ActionLink(
    "Send us an email", 
    "Index", 
    "Email", 
    new { id = Model.Exception.Id }, 
    null
)

并让控制器操作将此id作为参数:

public ActionResult Index(int id)

好了,现在你知道了id =&gt;因此,您可以从该实体持久存储的任何位置检索相应的实体。

现在有些人可能会建议您在渲染视图之前将对象存储到会话中,然后从会话中检索此对象。就个人而言,我不是会议的忠实粉丝,因为它将状态引入应用程序。这意味着在没有首先调用第一个操作的情况下,您永远不能调用第二个操作。这也意味着您无法将第二个操作添加到浏览器收藏夹中。这也意味着,如果您在Web场中运行应用程序,则无法再在内存中存储会话=&gt;您将不得不为此会话使用进程外存储。会议太麻烦了。

答案 1 :(得分:1)

你无法在视图中真正传递它。

相反,请考虑将TempData中的异常存储在呈现视图的控制器中....

public ActionResult DisplayErrorAndOptionToEmailIt()
{

    TempData["LastError"] = m.Exception;
    return View();
}

然后当请求进来时从临时数据中检索它并通过电子邮件发送

public ActionResult SendTheEmail()
{
    var e = TempData["LastError"] as Exception;
    if (e != null)
    {
        EmailHelper.SendExceptionEmail(e);
    }
    return View();
}

另一方面,存储完整对象并不是最佳做法。如果可能,只存储您需要的内容:

public ActionResult DisplayErrorAndOptionToEmailIt()
{

    TempData["LastError"] = m.Exception.Message;
    return View();
}