我们正在为我们的项目开发一个'插件'架构,在这里扩展软件的功能,客户端可以编写自己的控制器并将其包含在项目中。 (插件将根据客户端将添加到模式中的表生成不同的输出。)
通过控制器操作中的操作来访问插件,例如/reports/get/?type=spending
因此,在这种情况下,操作必须将控制器放在“插件”区域内并调用索引操作(例如areas/plugin/spending/index
)。如何在/reports/get/?type=spending
操作中调用此操作并获取其输出?
答案 0 :(得分:8)
Html.RenderAction Method用于在视图中呈现其他操作的输出。从中获益,在控制器中也是如此
using System.Web.Mvc.Html;
public void Index()
{
StringBuilder resultContainer = new StringBuilder();
StringWriter sw = new StringWriter(resultContainer);
ViewContext viewContext = new ViewContext(ControllerContext, new WebFormView(ControllerContext, "fakePath"), ViewData, TempData, sw);
HtmlHelper helper = new HtmlHelper(viewContext, new ViewPage());
helper.RenderAction("create");
sw.Flush();
sw.Close();
resultContainer.ToString(); //"This is output from Create action"
}
public ActionResult Create()
{
return Content("This is output from Create action");
}
实际上,RenderAction可以传递您想要的所有路由数据,而不仅仅是动作名称
答案 1 :(得分:3)
RedirectToAction可能是最好的选择 - 这样你就可以使用内置的路由找到正确的行动 - 比如
return RedirectToAction("Index", "SpendingPlugin");
如果你不想要重定向,你可以像Nathan建议的那样直接找到并调用控制器方法,但这往往会变得不必要地复杂并干扰定位视图。
答案 2 :(得分:3)
注意:这个解决方案可能看起来有点复杂,但它确实是解决问题的唯一方法,正如提问者在他的问题中所描述的那样,更具体地说是对他的问题的评论,其中说:“它是关于创建正在请求的控制器,从actionresult读取输出。 “(强调我的)
控制器和操作只是类和方法的奇特名称。为什么不像对待任何其他类一样实例化控制器,然后在控制器上调用索引操作?最困难的部分是实例化控制器,因为你要使用'插件'架构,所有关于控制器的信息都是它的名字作为字符串。然而,没有什么可以解决的问题:
// GET: /reports/get/?type=spending
public Controller Reports
{
public ActionResult Get(string typeName)
{
Type typeOfController;
object instanceOfController;
try
{
typeOfController = System.Reflection.Assembly.GetExecutingAssembly().GetType(name: typeName, throwOnError: true, ignoreCase: true)
instanceOfController = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(typeName: typeName, ignoreCase: true);
}
catch(Exception ex)
{
// Controller not found
return View("InvalidTypeName");
}
ActionResult result = null;
try
{
result = typeOfController.InvokeMember("Index", System.Reflection.BindingFlags.InvokeMethod, null, instanceOfController, null)as ActionResult;
}
catch(Exception ex)
{
// Perhaps there was no parametersless Index ActionMethod
// TODO: Handle exception
}
return result;
}
}