我想从视图中将一个大对象传递给控制器的动作。像这样:
查看
<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无法从中创建一个参数并将其添加到路由表/字典中。因此,我的电子邮件控制器的索引操作永远不会被调用。代码在两者之间的某处炸弹。
答案 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
,因为此类型没有id
或text
属性。
所以:
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();
}