0

我创建了一个自定义 DNN 模块,该模块将路由用于某些功能。

我使用以下模式注册了一条路由:Data/{table}/{action}.aspx(我使用了一个实现 DNN 的 IServiceRouteMapper 的类,它有一个在 DNN 启动时调用的 RegisterRoutes 方法)。

路由注册成功,可以在每个页面请求的 RouteTable 中看到。

但是,应该与路由匹配的每个请求都会导致 DNN 显示其 404 错误页面。换句话说,DNN 似乎决定请求 URL 应该与 DNN 页面匹配,但事实并非如此。

如果我将友好的 URL 提供程序配置从 urlFormat="advanced" 更改为 urlFormat="searchfriendly",那么路由将成功运行。

我的结论是,DNN 友好的 URL 提供程序(实现为 HTTP 模块)首先拦截请求(即在路由匹配可以启动之前),并且在“高级”模式下假定它是页面 URL,然后尝试查找CMS 中的匹配页面,但失败。然而,在“搜索友好”模式下,它让它去,所以路由匹配可以查看请求。

我想将友好的 URL 提供程序保持在“高级”模式(因为 URL 更清晰)。我还想找到一些不涉及例如编写我自己的友好 URL 提供程序的简单解决方案!

在 web.config 中,URL 路由似乎在友好的 URL 提供程序之前就在管道中,所以我很困惑为什么会发生上述情况:

<modules runAllManagedModulesForAllRequests="true">
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
  <add name="RequestFilter" type="DotNetNuke.HttpModules.RequestFilter.RequestFilterModule, DotNetNuke.HttpModules" preCondition="managedHandler" />
  <add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule, DotNetNuke.HttpModules" preCondition="managedHandler" />

编辑:按要求添加 IServiceRouteMapper 实现,即注册路由的位置。Navigator.SiteRootFolder 是一个返回“数据”的常量。

public void RegisterRoutes(IMapRoute mapRouteManager)
{
    // This method is called automatically by DNN on startup
    RegisterRoutes(RouteTable.Routes);
}

private static void RegisterRoutes(RouteCollection routes)
{
    if (Global.CanCreateDataContext())
    {
        Global.MetaModel.RegisterContext(
            new EFDataModelProvider(() => Global.CreateDataContext(Global.Context.DataContextAssemblyLocation)),
            new ContextConfiguration { ScaffoldAllTables = Global.Context.ScaffoldAllTables });

        Global.MetaModel.DynamicDataFolderVirtualPath = string.Format("~/{0}/DynamicData", Navigator.SiteRootFolder);

        routes.Add(
            new DynamicDataRoute(string.Format("{0}/{{table}}/{{action}}.aspx", Navigator.SiteRootFolder))
            {
                Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
                Model = Global.MetaModel
            });
    }
}
4

1 回答 1

1

这确实是一种在 DNN 中创建服务的非标准方式。通常你会使用一个简单的路由映射器来实现 DotNetNuke.Web.Api.IServiceRouteMapper ,如下所示:

public class ServiceRouteMapper : IServiceRouteMapper
{   public void RegisterRoutes(IMapRoute mapRouteManager)
    {
        mapRouteManager.MapHttpRoute(
            moduleFolderName: "MyModule",
            routeName: "default", 
            url: "{controller}/{action}",
            namespaces: new[] { "MyCompany.Dnn.MyModule.Controllers" });
    }
}

这将导致以下路线:

/DesktopModules/MyModule/Api/Data/List(假设您有一个名为“DataController”的控制器类和一个名为“list”的方法。

这不会干扰 DNN 的友好 URL 提供程序的原因是因为“/DesktopModules”是被 URL 提供程序忽略的保留路径。

现在,如果您坚持拥有完全自定义的路由,则可以向 Url Provider 添加路径忽略。为此,您需要在 HostSettings 表中添加(或更新,如果存在)一条 SettingName = "AUM_DoNotRewriteRegEx" 的记录。下面是一个示例脚本,可以将路径“/Data”添加到忽略列表。

IF NOT EXISTS (SELECT * FROM HostSettings WHERE SettingName = 'AUM_DoNotRewriteRegEx' )
BEGIN
    INSERT INTO HostSettings (SettingName, SettingValue, SettingIsSecure, CreatedByUserId, CreatedOnDate, LastModifiedByUserId, LastModifiedOnDate)
    VALUES('AUM_DoNotRewriteRegEx','/DesktopModules/|/Providers|/LinkClick\.aspx|/Data', 0, -1, GETDATE(), -1, GETDATE())
END
ELSE
BEGIN
    UPDATE HostSettings SET SettingValue = (select SettingValue + '|/Data' from HostSettings where settingname = 'AUM_DoNotRewriteRegEx')
    where SettingName = 'AUM_DoNotRewriteRegEx'
END
于 2019-09-02T19:55:54.557 回答