【发布时间】:2011-05-28 05:23:40
【问题描述】:
MVC {controller}/{action}/{id} 中的默认路由在大多数情况下非常有用,因为如果传入的 url 不包含参数,则可以设置默认值,但是还有一种方法可以指定默认操作控制器上不存在操作?
我想要实现的是能够拥有具有几个特定操作的控制器,然后是它自己的包罗万象,它使用 url 从基本 CMS 中获取内容。
例如,产品控制器将类似于:
public class ProductsController: Controller{
public ActionResult ProductInfo(int id){...}
public ActionResult AddProduct(){...}
public ActionResult ContentFromCms(string url){...}
}
默认路由将处理/Products/ProductInfo/54 等,但/Products/Suppliers/Acme 的请求url 将返回ContentFromCms("Suppliers/Acme");(将url 作为参数发送会更好但不需要,并且我从Request 中获取它的无参数方法将没事)。
目前我可以想到两种可能的方法来实现这一点:
创建一个反映在控制器上的新约束,以查看它是否确实具有给定名称的操作,并在 {controller}/{action}/{id} 路由中使用它,从而使我能够拥有更通用的包罗万象,例如 {controller}/{*url}。
覆盖控制器上的HandleUnknownAction。
第一种方法似乎是一种相当迂回的检查方法,而第二种方法我不太了解 MVC 和路由的内部结构,不知道如何进行。
更新
没有任何回复,但我想我会留下我的解决方案,以防将来有人发现这个问题,或者让人们提出改进/更好的方法
对于我想要拥有自己的包罗万象的控制器,我给了他们一个界面
interface IHasDefaultController
{
public string DefaultRouteName { get; }
System.Web.Mvc.ActionResult DefaultAction();
}
然后我从 ControllerActionInvoker 派生并覆盖 FindAction。这将调用基 FindAction,然后,如果基返回 null 并且控制器隐含我使用默认操作名称再次调用 FindAction 的接口。
protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
ActionDescriptor foundAction = base.FindAction(controllerContext, controllerDescriptor, actionName);
if (foundAction == null && controllerDescriptor.ControllerType.GetInterface("Kingsweb.Controllers.IWikiController") != null)
{
foundAction = base.FindAction(controllerContext, controllerDescriptor, "WikiPage");
}
return foundAction;
}
因为我还想要路由中的参数,所以我还替换了控制器上默认 Actionresult 开头的 RouteData
ControllerContext.RouteData = Url.RouteCollection[DefaultRouteName].GetRouteData(HttpContext);
【问题讨论】:
标签: asp.net asp.net-mvc-2 routing