【问题标题】:Fallback Route in ASP MVC if action doesn't exist如果操作不存在,则 ASP MVC 中的后备路由
【发布时间】: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


    【解决方案1】:

    你的方法很好。作为旁注:

    替换

    controllerDescriptor.ControllerType.GetInterface("Kingsweb.Controllers.IWikiController") != null
    

    typeof(Kingsweb.Controllers.IWikiController).IsAssignableFrom(controllerDescriptor.ControllerType)
    

    这是一种更强类型的方式,然后通过字符串传递接口的名称:如果明天更改命名空间怎么办?..

    【讨论】:

      猜你喜欢
      • 2014-09-28
      • 2016-05-22
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-10-08
      相关资源
      最近更新 更多