2017-08-03 64 views
2

我正在建立一个网站。尽管很小(按页面计算),但还是有一些大笔资金登陆页面以及常用的库存页面。Webforms路由 - 相同的签名与不同的页面?

因为场地相对较小,页面结构持平。

https://example.com/contact 
https://example.com/big-money-page 

我们计划引进很多不同的网页设计更多的网页。这意味着我们将使用母版页和/或aspx模板页面并创建我们自己的数据库驱动的CMS。

这是我能看到的问题是与URL路由:

模板类型1

Route url: /{Name} - e.g. /big-money-page 
Physica path: ~/template1.aspx 

模板类型2

Route url: /{Name} - e.g. /new-supporting-page 
Physical path: ~/template2.aspx 

我想使这项工作不会中断现有的金钱页面,如果可能的话,保持熟悉的网站结构,对于访问者来说,template1和template2是类似的页面,并且不会自然地驻留在不同的文件夹中 - 它们只是设计不同。

此外,固定深路由文件夹结构使其难以在将来的变化。

我一直在使用WF路由有一段时间了,但总是简单的方法。任何人都知道我可以如何使这些改变在有限的后果下工作?

UPDATE --------------------------------------------- -----------------------

好的,在没有任何反馈的情况下,我想出了一个想法放在桌子上。我会很感激可以想象的可用性和任何缺点的反馈。

我的想法是有一个虚拟路由/页面。

该路线的格式为http://example.com/{name}

虚拟页面使用placeholder {name}从目标页面的数据库中检索数据。

然后我们的Server.Transfer到正确的目标网页,使用我们从数据库中检索到的数据。

我认为这会工作,但我担心的事情我不知道:对Server.Transfer的

  • 浏览器兼容性
  • 性能开销
  • 输出缓存的影响
  • 其他东西,甚至没有跨越我的脑海

当然,这不是一个理想的解决方案,但我也打开任何其他想法。

回答

2

在WebForm项目中,可以使用自定义的HTTPModule实现该任务。实施包括几个步骤。一个简化的版本是如下:
1. SQL

create table dbo.UrlMap (
    publicUrl varchar(255) not null primary key, 
    PhysUrl varchar(255) not null 
) 

填写表的一些数据,如

publicUrl  PhysUrl 
big-money-page template1.aspx?id=1 
huge-money-page template1.aspx?id=2 
no-money-page template2.aspx?id=3 
other-page  template1.aspx?id=4 

2. App_Code文件夹中创建类

using System; 
using System.Web; 

/// <summary> 
/// Implements IHttpModule with custom URLs 
/// </summary> 
public class UrlMap:IHttpModule 
{ 
    /// <summary> 
    /// Initialize the module 
    /// </summary> 
    /// <param name="context"></param> 
    void IHttpModule.Init(HttpApplication context) 
    { 
     context.BeginRequest += Context_BeginRequest; 
     context.PostMapRequestHandler += Context_PostMapRequestHandler; 
    } 

    private void Context_BeginRequest(object sender, EventArgs e) 
    { 
     var app = (HttpApplication)sender; 
     Url2PhysPath(app.Request.Path, app); 
    } 

    private void Context_PostMapRequestHandler(object sender, EventArgs e) 
    { 
     var app = (HttpApplication)sender; 
     var pg = app.Context.Handler as System.Web.UI.Page; 
     if (pg != null) 
     { 
      pg.PreRenderComplete += Pg_PreRenderComplete; 
     } 
    } 

    private void Pg_PreRenderComplete(object sender, EventArgs e) 
    { 
     ProcessPageTree((System.Web.UI.Control)sender); 
    } 

    /// <summary> 
    /// Replaces physical URLs on the page with "beutified" version 
    /// </summary> 
    /// <param name="control"></param> 
    private void ProcessPageTree(System.Web.UI.Control control) 
    { 
     var form = control as System.Web.UI.HtmlControls.HtmlForm; 
     if (form != null) 
     { 
      form.Action = BeautifyUrl(form.Page.Request.Url.PathAndQuery); 
     } 
     //other types in a similar way 
     if (control.HasControls()) 
     { 
      foreach(System.Web.UI.Control c in control.Controls) 
      { 
       ProcessPageTree(c); 
      } 
     } 
    } 
    /// <summary> 
    /// Helper function. Can be inlined. 
    /// Searches "beautified" url in a DB and rewrites path 
    /// </summary> 
    /// <param name="url"></param> 
    /// <param name="app"></param> 
    private static void Url2PhysPath(string url, HttpApplication app) 
    { 
     using (var cnn = new System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SiteCnn"].ConnectionString)) 
     { 
      var cmd = new System.Data.SqlClient.SqlCommand("select physPath from dbo.urlMap where [email protected]", cnn); 
      cmd.CommandType = System.Data.CommandType.Text; 
      cmd.Parameters.Add("@url", System.Data.SqlDbType.VarChar, 255).Value = url; 
      cnn.Open(); 
      string physPath = null; 
      using(var r = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection)) 
      { 
       if (r.Read()) 
       { 
        physPath = (string)r["physPath"]; 
       } 
       r.Close(); 
      } 
      if (!string.IsNullOrEmpty(physPath)) 
      { 
       app.Context.RewritePath("/" + physPath); 
      } 
     } 
    } 

    /// <summary> 
    /// Helper function 
    /// </summary> 
    /// <param name="physUrl"></param> 
    /// <returns>returns original url when nothing is found</returns> 
    private static string BeautifyUrl(string physUrl) 
    { 
     using (var cnn = new System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SiteCnn"].ConnectionString)) 
     { 
      var cmd = new System.Data.SqlClient.SqlCommand("select publicUrl from dbo.urlMap where [email protected]", cnn); 
      cmd.CommandType = System.Data.CommandType.Text; 
      cmd.Parameters.Add("@url", System.Data.SqlDbType.VarChar, 255).Value = physUrl; 
      cnn.Open(); 
      string pubUrl = physUrl;//to return original url when nothing is found 
      using(var r = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection)) 
      { 
       if (r.Read()) 
       { 
        pubUrl = (string)r["publicUrl"]; 
       } 
       r.Close(); 
      } 
      return pubUrl; 
     } 

    } 
    /// <summary> 
    /// Required by interface 
    /// </summary> 
    void IHttpModule.Dispose() 
    { 
    // throw new NotImplementedException(); 
    } 
} 

3.修改Web.config
注册模块。以下行添加到configuration \ system.webServer \ modules

<add name="UrlRewriter" type="UrlMap" preCondition="managedHandler"/> 

跟进的Server.Transfer的不是一个问题
浏览器兼容性。浏览器接收HTML只

性能开销不多
影响缓存的更好,然后template.aspx?id=123
这甚至还没有穿过我的脑海publicUrl都和physUrl必须是唯一的其他的事情输出缓存。在实践中,您可以将静态的Dictionary<string, string>变量中的直接和倒转键查找进行缓存。

+0

感谢Alex的精湛解释。 –