2009-08-18 49 views
46

任何人都可以告訴我如何從一個操作方法內的另一個控制器上調用一個方法嗎?我不想重定向。我想在不同的控制器上調用一個方法,該方法返回一個字符串並在我的操作方法中使用響應。在不同的控制器上的.NET MVC調用方法

+1

什麼是上下文?可能有更好的方法來達到你想要的。 – 2009-08-18 21:45:40

+1

我正在使用IoC,並通過我的控制器訪問所有數據。我想要檢索通過不同控制器可用的特定用戶數據。 – user135498 2009-08-18 22:01:21

+1

我不知道很多關於IoC的知識,但是可能將您的方法移動到ActionFilter可以幫助您做你想做的事情http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx這遵循原則IoC對我的理解 – 2009-08-18 22:56:36

回答

11

你可以在你的動作方法中實例化控制器並調用你需要的其他方法嗎?

public ActionResult YourActionMethod() 
{ 
    SomeController c = new SomeController(); 
    ActionResult result = c.SomeMethod(); 

    return View(); 
} 
+1

該caviet是我使用Castle Windsor IoC注入數據上下文的連接字符串。我很掙扎,因爲mvc框架會自動化化控制器。 – user135498 2009-08-18 21:52:19

+7

該解決方案可以*工作*,但它不雅觀。 – 2010-10-22 18:18:20

2

看起來你正在試圖做一些控制器不是爲了設計的。 在某些類中將您所需的方法設計爲公共方法,並從兩個控制器操作中調用。

+0

這也被稱爲應用程序服務。 (http://wiki.sharparchitecture.net/SettingUpNorthwind.ashx)它通常屬於服務層,但您可以重構到域模型中,方法是Domain Object Specific。 (http://martinfowler.com/eaaCatalog/serviceLayer.html) – 2010-10-22 18:17:12

41

聽起來像你應該重構你的應用程序,並將產生字符串的功能提取到一個新的獨立類(或重用現有類,如果你有一個適合的類),並讓兩個控制器使用該類。

+1

也被稱爲服務層。 (http://martinfowler.com/eaaCatalog/serviceLayer.html)http://wiki.sharparchitecture。net/SettingUpNorthwind.ashx – 2010-10-22 18:25:32

+12

也許他想要生成的字符串是一個已由另一個控制器構建的HTML字符串。考慮將此字符串提供給HTML生成器的示例。調用一個控制器動作並捕獲字符串中的視圖結果聽起來像是一種很好的方法。 – pettys 2011-04-20 13:57:16

+1

只是一個想法:做一個「超級控制器」,既繼承,並堅持共同功能在那裏.. – user230910 2015-04-12 06:41:57

8

我沒有使用Castle Windsor IoC,但理論上你應該能夠創建一個自定義的Controller工廠類,然後通過在Global中註冊來指示MVC框架使用這個自定義控制器工廠。 asax.css文件,在Application_Start事件:

protected void Application_Start() 
{ 
    RegisterRoutes(RouteTable.Routes); 
    ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactor()); 
} 

[見臨Asp.Net MVC 2框架,史蒂芬·桑德森,Apress出版,頁64 - 66]

這樣的話,你可以從你的實例化控制器代碼中的任何地方。

從「當前」控制器或從其他代碼調用另一個控制器的操作的概念是非常錯誤的。控制器只是類。當MVC框架以特殊方式調用它們時,它們只會成爲「控制器」。

因此,這是正確的和錯誤的歸結爲什麼你這樣做,而不是你是否應該。

如果你只是使用控制器作爲一個類,那麼這很好。如果您嘗試使用此功能向用戶發送響應,則應如上所述使用RedirectToAction。

將控制器用作類而不是控制器有很多原因。例如,測試您的控制器時。因此,將你的控制器視爲一個類是必要的,而不是錯誤的。

使用控制器作爲一個類的非測試場景例如:

我寫一個利用MVC框架的模板功能來產生HTML郵件的HTML迷你框架,所有的Web應用程序需要的東西出於某種原因(例如訂單確認電子郵件)。

大致來說,你實例化MailManagerController(爲簡單起見,假設你沒有使用IOC)在NormalController的行動(即需要發送電子郵件),然後執行:

MailManagerController mailmanager = new MailManagerController(); 
string html = mailmanager.OrderConfirmation(order).RenderToString(); 
Postman.SendEmail(html, order.UserEmailAddress, "MyApp order confirmation"); 

凡RenderToString是一個擴展方法在ViewResultBase上呈現Action的輸出(返回一個ViewResultBase對象)爲一個字符串,而Postman是一個靜態類,它處理一旦你有文本發送郵件。

這種技巧的好處在於您可以使用MVC框架生成模板化的電子郵件,因爲OrderConfirmation Action將具有關聯的視圖,如果不是您要發送的電子郵件的HTML模板,該視圖就是無關緊要的。

+2

「因此,這是正確和錯誤歸結爲什麼你這樣做,而不是你是否應該或不。 「人們可能會有很大的不同。通常的功能通常可以並且應該被重構爲服務層。 (http://martinfowler.com/eaaCatalog/serviceLayer.html)在許多地方都可以看到這種邏輯分區,包括Grails MVC技術棧(請參閱優秀的書,Grails in Action)(http://www.grails.org /doc/1.0.x/guide/8.%20The%20Service%20Layer.html)和SharpArchitecture .NET棧(http://wiki.sharparchitecture.net/SettingUpNorthwind.ashx) – 2010-10-22 18:19:16

+0

此外,有人可能會爭辯說,MailManagerController這裏應該是一個注入控制器的應用程序服務。使用IoC的原則:pubilc ActionResult SendMail(){mailService.sendMail(new OrderConfirmation(order)); //假設服務已被IoC容器注入} – 2010-10-22 18:23:39

+0

我正在接近類似的需求 - 從一個控制器的動作中選擇一點功能。實際上,特別關注郵件管理器角色。聽取更多關於上述方法優點的想法會有所幫助。 – justSteve 2010-11-30 18:52:45

10

您可以通過方法HtmlHelper來實現此目的。但是它不是簡單的一個動作方法(設計)獲得的HtmlHelper實例

@Html.Action("OtherAction") 

在視圖中,你會做這樣的。事實上,它是這樣一個可怕的黑客,我不願意,甚至張貼...

var htmlHelper = new HtmlHelper(new ViewContext(
             ControllerContext, 
             new WebFormView(ControllerContext, "HACK"), 
             new ViewDataDictionary(), 
             new TempDataDictionary(), 
             new StringWriter()), 
           new ViewPage()); 

var otherViewHtml = htmlHelper.Action("ActionName", "ControllerName"); 

這部作品MVC 3,你可能需要從ViewContext構造函數刪除StringWriter ARG的MVC 2,IIRC。

< /黑客>

+1

要獲得'Action'方法,還需要添加對System.Web.Mvc.Html的使用引用。 – JasonRShaver 2012-05-14 20:18:10

+0

什麼是ControllerContext?從哪裏得到它? – 2012-06-28 03:20:55

+0

丹,你從當前的控制器得到它,那是你從另一個控制器調用的那個... – 2012-08-01 12:35:36

-5

我一直在尋找同樣的事情,但嚴重的人,爲什麼需要寫這樣複雜的答案。

這裏有一個帖子說會回答很乾脆: Using Html.ActionLink to call action on different controller

基本上你只需要使用ActionLink的這個過載: ActionLink(HtmlHelper, String, String, String, Object, Object)

所以,你將有: ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)

如果您沒有任何routeValues(這是Action的輸入)或htmlAttributes,您必須將它們設置爲null。

下面是一個例子電話: @Html.ActionLink("Add New Student", "Create", "Student", null, new { @class = "btn btn-primary" })

+0

不幸的是,這個答案與實際問題無關。 – 2016-09-30 19:04:51

21

您可以用下面的辦法來調用一個方法的其他控制器上:

var otherController = DependencyResolver.Current.GetService<OtherController>(); 
var result = otherController.SomeMethod(); 

這在ASP.NET MVC5爲我工作。希望它也能爲你工作。

+0

與此有關的問題是沒有上下文。所以如果你使用的話,比如說「Server.MapPath(....」),它會出錯,因爲服務器什麼都不是。 – 2016-09-30 19:03:41

相關問題