11

我们正在构建一个代码非常少的网站,它主要只是提供一堆静态页面。我知道随着时间的推移会发生变化,我们会想要交换更多的动态信息,所以我决定继续使用 ASP.NET MVC2 和 Spark 视图引擎构建一个 Web 应用程序。将有几个控制器必须进行实际工作(例如在 /products 区域中),但其中大部分将是静态的。

我希望我的设计师能够构建和修改站点,而不必在每次他们决定添加或移动页面时都要求我编写新的控制器或路由。因此,如果他想添加一个“ http://example.com/News ”页面,他可以在 Views 下创建一个“News”文件夹并在其中放置一个 index.spark 页面。稍后,如果他决定想要一个 /News/Community 页面,他可以将 community.spark 文件放到该文件夹​​中并让它工作。

我可以通过让我的控制器覆盖 HandleUnknownAction 来获得没有特定操作的视图,但我仍然必须为每个文件夹创建一个控制器。每次他们决定向站点添加区域时都必须添加一个空控制器并重新编译,这似乎很愚蠢。

有没有办法让这更容易,所以我只需要编写一个控制器并在需要完成实际逻辑时重新编译?某种“主”控制器将处理没有定义特定控制器的任何请求?

4

5 回答 5

6

您必须为实际的控制器/动作编写路由映射,并确保默认将索引作为动作并且 id 是“catchall”,这样就可以了!

    public class MvcApplication : System.Web.HttpApplication {
        public static void RegisterRoutes(RouteCollection routes) {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = "catchall" } // Parameter defaults
            );

        }

        protected void Application_Start() {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);

            ControllerBuilder.Current.SetControllerFactory(new CatchallControllerFactory());

        }
    }

public class CatchallController : Controller
    {

        public string PageName { get; set; }

        //
        // GET: /Catchall/

        public ActionResult Index()
        {
            return View(PageName);
        }

    }

public class CatchallControllerFactory : IControllerFactory {
        #region IControllerFactory Members

        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {

            if (requestContext.RouteData.Values["controller"].ToString() == "catchall") {
                DefaultControllerFactory factory = new DefaultControllerFactory();
                return factory.CreateController(requestContext, controllerName);
            }
            else {
                CatchallController controller = new CatchallController();
                controller.PageName = requestContext.RouteData.Values["action"].ToString();
                return controller;
            }

        }

        public void ReleaseController(IController controller) {
            if (controller is IDisposable)
                ((IDisposable)controller).Dispose();
        }

        #endregion
    }
于 2010-06-09T21:15:38.387 回答
3

This link might be help,

If you create cshtml in View\Public directory, It will appears on Web site with same name. I added also 404 page.

[HandleError]
    public class PublicController : Controller
    {
        protected override void HandleUnknownAction(string actionName)
        {
            try
            {
                this.View(actionName).ExecuteResult(this.ControllerContext);
            }
            catch
            {
                this.View("404").ExecuteResult(this.ControllerContext);
            }
        }
    }
于 2013-12-19T09:58:40.733 回答
1

您不能为所有静态页面创建一个单独的控制器并使用 MVC 路由将所有内容(除了实际工作的控制器之外)重定向到它,并包含路径参数吗?然后在该控制器中,您可以有逻辑根据路由发送给它的文件夹/路径参数显示正确的视图。

虽然我不知道火花视图引擎处理事情,但它必须编译视图吗?我真的不确定。

于 2010-06-09T19:24:05.583 回答
1

反思保罗的回答。我没有使用任何特殊的视图引擎,但这是我所做的:

1) 创建一个 PublicController.cs。

// GET: /Public/
[AllowAnonymous]
public ActionResult Index(string name = "")
{
    ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
    // check if view name requested is not found
    if (result == null || result.View == null)
    {
        return new HttpNotFoundResult();
    }
    // otherwise just return the view
    return View(name);
}

2) 然后在 Views 文件夹中创建一个 Public 目录,并将您想要公开的所有视图放在那里。我个人需要这个,因为我从来不知道客户是否想在不重新编译代码的情况下创建更多页面。

3) 然后修改 RouteConfig.cs 以重定向到 Public/Index 动作。

routes.MapRoute(
    name: "Public",
    url: "{name}.cshtml", // your name will be the name of the view in the Public folder
    defaults: new { controller = "Public", action = "Index" }
);

4)然后从您的观点中引用它,如下所示:

<a href="@Url.RouteUrl("Public", new { name = "YourPublicPage" })">YourPublicPage</a> <!-- and this will point to Public/YourPublicPage.cshtml because of the routing we set up in step 3 -->

Not sure if this is any better than using a factory pattern, but it seems to me the easiest to implement and to understand.

于 2013-11-16T03:34:39.763 回答
0

我认为您可以创建自己的控制器工厂,该工厂将始终实例化相同的控制器类。

于 2010-06-11T20:18:57.087 回答