是否有可能在asp.net MVC 5中拥有一个匿名控制器?

时间:2014-05-22 14:29:35

标签: asp.net-mvc controller multi-tenant

我们已经构建了一个MVC应用程序,该应用程序使用分层文件夹,子文件夹和页面发布完整的网站。生成的页面严格来说是HTML,不会在我们的MVC应用程序中发布。我们的客户可以使用他们选择的任何合规字符串为其文件夹和页面命名。可以想象,一旦网站被托管,他们最终可能会得到一个URL,例如: someDomain.com/folder/subfolder1/subfolder2/page-slug。嵌套子文件夹的数量没有限制。

我们希望在我们的MVC应用程序中复制他们的网站,以便他们能够在发布之前测试它们,也许我们可以在需要时自己提供托管。

明显的问题是,我们如何处理, MVC应用程序中的myMVCApp.com/folder/subfolder1/subfolder2/page-slug?

如果我们可以通过某种方式设置路由来处理这样的事情,那么我们可以通过“/”来轻松获取请求所需的内容。“/ /。

最后一段将是前一段文件夹中包含的页面。然后我们可以使用这些字符串搜索我们的数据库以获得所需的内容。

非常感谢您的帮助。

进一步的问题: 回应Tomi提供的答案。

我将代码添加到控制器的类中,但是我收到以下警告: enter image description here

我不确定我错过了什么?我把代码放在了哪里?再次感谢。

更新2.我意识到我实际上并没有创建控制器工厂,所以我按照我在此处找到的部分示例:http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/。自从实现它以来,我不再收到任何构建错误,但是当我运行调试时,它会崩溃内置的IISEXPRESS,而不会出现任何错误消息。

这是我的控制器工厂代码:

public class FolderControllerFactory : IControllerFactory
{

    public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        try
        {
            // Get the path
            string path = requestContext.RouteData.Values["pathInfo"].ToString();

            IController controller = new FolderController(path);

            return controller;
        }
        catch
        {
            // Log routing error here and move on

            return CreateController(requestContext, controllerName);

        }
    }


    public void ReleaseController(IController controller)
    {
        var disposable = controller as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }

    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Default;
    }

}

这是我的全球:

ControllerBuilder.Current.SetControllerFactory(typeof(ProofPixApp.Controllers.FolderControllerFactory));

最后我的控制器:

public class FolderController : Controller
{
    private string _path;
    public FolderController(string path)
    {
        _path = path;
    }


    public ActionResult Index(string name)
    {
        ViewBag.Message = "Hello " + name;
        return View("/Views/" + _path);
    }
}

几点说明:

    1. I removed the 'override' from public IController CreateController
    because I kept receiving the initial error I posted.  

    2. I added public void ReleaseController and the public
       SessionStateBehavior GetControllerSessionBehavior methods to the
       CreateController class to avoid other build errors.

    3. I removed 'base.' from the catch clause because it too was causing a
       build error.

解: 我通过检查在createController方法中查看pathValue不为null来避免错误,如下所示:

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

        // Get the path
        string path = "";
        if (requestContext.RouteData.Values["pathInfo"] != null)
        {
            path = requestContext.RouteData.Values["pathInfo"].ToString();
        }

        IController controller = new FolderController(path);

        return controller;

    }

1 个答案:

答案 0 :(得分:1)

我不知道是什么页面slug,但这里是我如何实现您请求的路由的解决方案。

我创建了一个自定义ControllerFactory来处理url并将其传递给控制器​​。此ControllerFactory构造我们用于处理文件夹路由请求的控制器。我们从routevalues获取路径,然后将其传递给FolderController。

    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        try
        {
            // Get the path
            string path = requestContext.RouteData.Values["pathInfo"].ToString();

            IController controller = new FolderController(path);

            return controller;
        }
        catch
        {
            // Log routing error here and move on

            return base.CreateController(requestContext, controllerName);
        }
    }

这是控制器。重定向到给定路径的action方法现在称为Index。 actionmethod返回它从url中找到的视图。

public class FolderController : Controller
{
    private string _path;
    public FolderController(string path)
    {
        _path = path;
    }
    public FolderController()
    {
    }

    public ActionResult Index(string name)
    {
        ViewBag.Message = "Hello " + name;
        return View("/Views/"+_path);
    }
}

最后一步是编写我们自己的路线并注册工厂。打开RouteConfig.cs。我的新RegisterRoutes方法如下所示:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "Dynamic",
            url: "{*pathInfo}",
            defaults: new { controller = "Folder", action = "Index", id = UrlParameter.Optional }
            );
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

在global.asax中,我们需要通过在Application_Start方法中添加这一行来注册我们的FolderControllerFactory

ControllerBuilder.Current.SetControllerFactory(typeof(FolderControllerFactory)); 

那就是它!还有很多工作要做,比如处理不正确的网址等。此外,我不认为这支持普通的html文件,文件必须是.cshtml或asp格式。

以下是测试:

我的文件夹结构:

Views folder in studio

我请求的网址:

localhost:port/Mainfolder/Subfolder/Subfolder2/view.cshtml?name=Tomi

Route Debugger插件的结果:

Web page