【问题标题】:Is it possible to pass classes between controllers in ASP.NET MVC?是否可以在 ASP.NET MVC 中的控制器之间传递类?
【发布时间】:2009-10-21 02:08:19
【问题描述】:

是否可以在 ASP.NET MVC 控制器中执行类似的操作?

public ActionResult Index(CustomADT adt)
{
    ...
}

当你点击一个链接时,你会从另一个控制器传入一个类。还是只能传递字符串?

编辑:

稍微详细一点。假设我有以下类层次结构:

public class Area
{
    public string Name { get; set; }
    public ICollection<Building> Buildings { get; set; }
}

public class Building
{
    public string Name { get; set; }
}

所以Area 包含Buildings 的列表。现在,我有两个控制器,AreasControllerBuildingsController。两者都有一个Index() 方法。我想做的是当这个 URL 被导航到:

http://localhost/Areas/

它将列出所有区域。然后,当您转到此 URL 时:

http://localhost/Areas/1/Buildings/

它将列出 ID 为 1 的区域的所有建筑物。在BuildingsController 中,我收到一个 int 形式的 ID,然后使用它来查找正确的区域,如下所示:

public ActionResult Index(int areaId)
{
    var area = areaRepository.GetById(areaId);
    return View(area.Buildings);
}

现在,这对我来说似乎很笨拙。 areaId 必须作为 int 接收,然后我必须再次访问存储库以获取实际的 Area 对象。有什么办法可以代替:

public ActionResult Index(Area area)
{
    return View(area.Buildings);
}

而不是再次访问存储库并重新检索已经实例化的对象?由于 HTTP 的工作原理(您不能在 URL 中放置对象),我倾向于不,但也许有人有一个巧妙的技巧。

【问题讨论】:

  • 您似乎正在尝试解决问题中未描述的问题。这个问题的背景是什么?
  • 没有太多背景,真的。在我见过的所有教程中,它们仅在控制器之间传递字符串和整数(实际上是转换为整数的字符串),就像您单击链接时一样。这就是 HTTP 的工作方式,但不是编程的工作方式。由于控制器只是类,我想知道是否有任何方法可以在控制器之间传递类,但现在我考虑了一下,我认为这是不可能的,因为你正在发出一个 HTTP 请求,然后调用一个控制器。
  • “不要再次访问存储库并重新检索已经实例化的对象”......已经在哪里?如果您的控制器操作没有查找此内容,那会是什么? (正如您所提到的,HTTP 的无状态特性意味着在您自己的代码之外真的没有任何东西那里ModelBinder 行为尽管如此。)
  • 好点 Sixten。我是从以下角度考虑的,要进入 Buildings 视图,您必须通过 Areas 视图,但很可能是用户键入 URL 而不是在 Areas 视图上点击链接。

标签: asp.net-mvc routing controller


【解决方案1】:

是的,这是可能的。更重要的是,它通过所谓的“ModelBinders”内置在 MVC 本身中。模型绑定器使用反射将查询字符串/表单键/值对与您的 CustomADT 类对象匹配。只要您的表单提交相同的属性名称,您所拥有的就可以完美运行。

你的表格...

<% using (Html.BeginForm()) { %>

  <%= Html.TextBox("Title", Model.Title) %>
  <%= Html.TextBox("Description", Model.Description) %>

<% } %>

你的班级...

public class CustomADT
{
  public String Title {get; set;}
  public String Description {get; set;}
}

注意您的类的属性如何匹配表单键/值? ASP.NET MVC 内置了它,它会将它们与上面的示例 Index(CustomADT adt) 映射在一起。

如果您对绑定有特殊要求,您可以创建自己的自定义 IModelBinder 类并将其注册到 global.asax 中,以便在表单键/值对和模型(类)之间进行自定义映射。 (把它)

另外,我强烈建议阅读使用 ASP.NET MVC 的“ViewModel”模式(必读)。

我还写了一篇关于如何使用强类型操作方法的博客,它允许您将类从视图传递到控制器(并在控制器中传递给我提到的 Microsoft.Web.Mvc 程序集中的扩展) .

http://eduncan911.com/archive/tags/Asp.Net+Mvc/default.aspx

最后,没有从模型到查询字符串的直接转换来调用控制器上的另一个操作方法。但是,您可以使用默认的模型绑定来反映您的模型并为您创建它们:

return RedirectToAction("Index", "Home", myCustomADT);

我认为应该工作,因为最后一个参数是将作为查询字符串附加的集合。如果没有(我有疑问),您需要将每个属性作为匿名集合的一部分传递(新 { Title = myCustomADT.Title, Description = myCustomADT.Description);)。

一个更好的问题是,您为什么要这样做?你真的想重定向和传递视图模型。

【讨论】:

  • 他可能还需要将他的控制器签名重新定义为public ActionResult Index([Bind(Prefix="")]CustomADT adt)
  • 我已经修改了我的问题,更好地阐明了我想要做什么。我觉得我想做的和你描述的有点不一样。
【解决方案2】:

我在这里找到了可能的答案:

http://msdn.microsoft.com/en-us/library/dd394711%28VS.100%29.aspx

在标题为在操作方法之间传递状态的部分下。基本上,您将对象存储在TempData 字典中,然后将其作为字符串引用。这是一个丑陋的解决方案,因为它不是强类型的。

【讨论】:

  • TempData 是类型的。不过,它不是静态类型的。
  • 我认为 TempData 只是一个以魔术字符串为键的字典,值是一个对象,您稍后必须在视图中将其转换为正确的类型。
  • 这一切都正确,但它不会改变我写的内容。强类型和静态类型是有区别的。你需要强制转换告诉你它不是弱类型的。但是,它是动态类型的,而不是静态类型的。
  • 啊,我明白了。我把弱类型和动态类型混淆了。
猜你喜欢
  • 2011-01-17
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 2010-12-31
  • 2014-07-01
  • 1970-01-01
相关资源
最近更新 更多