【问题标题】:ASP.NET - Avoid hardcoding pathsASP.NET - 避免硬编码路径
【发布时间】:2011-01-07 07:21:49
【问题描述】:

我正在寻找一种最佳实践解决方案,旨在减少在 ASP.NET 应用程序中硬编码的 URL 数量。

例如,当查看产品详细信息屏幕、对这些详细信息执行编辑然后提交更改时,用户将被重定向回产品列表屏幕。而不是编写以下代码:

Response.Redirect("~/products/list.aspx?category=books");

我想有一个合适的解决方案,让我可以做这样的事情:

Pages.GotoProductList("books");

其中Pages 是公共基类的成员。

我只是在这里吐口水,很想听听任何人管理其应用程序重定向的任何其他方式。

编辑

我最终创建了以下解决方案:我已经有一个公共基类,我向其中添加了一个 Pages 枚举(感谢 Mark),每个项目都有一个包含页面 URL 的 System.ComponentModel.DescriptionAttribute 属性:

public enum Pages
{
    [Description("~/secure/default.aspx")]
    Landing,
    [Description("~/secure/modelling/default.aspx")]
    ModellingHome,
    [Description("~/secure/reports/default.aspx")]
    ReportsHome,
    [Description("~/error.aspx")]
    Error
}

然后我创建了一些重载方法来处理不同的场景。我使用反射通过它的Description 属性获取页面的 URL,并将查询字符串参数作为匿名类型传递(也使用反射将每个属性添加为查询字符串参数):

private string GetEnumDescription(Enum value)
{
    Type type = value.GetType();
    string name = Enum.GetName(type, value);

    if (name != null)
    {
        FieldInfo field = type.GetField(name);
        if (field != null)
        {
            DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;

            if (attr != null)
                return attr.Description;
        }
    }

    return null;
}

protected string GetPageUrl(Enums.Pages target, object variables)
{
    var sb = new StringBuilder();
    sb.Append(UrlHelper.ResolveUrl(Helper.GetEnumDescription(target)));

    if (variables != null)
    {
        sb.Append("?");
        var properties = (variables.GetType()).GetProperties();

        foreach (var property in properties)
            sb.Append(string.Format("{0}={1}&", property.Name, property.GetValue(variables, null)));
    }

    return sb.ToString();
}

protected void GotoPage(Enums.Pages target, object variables, bool useTransfer)
{
    if(useTransfer)
        HttpContext.Current.Server.Transfer(GetPageUrl(target, variables));
    else
        HttpContext.Current.Response.Redirect(GetPageUrl(target, variables));
}

典型的调用如下所示:

GotoPage(Enums.Pages.Landing, new {id = 12, category = "books"});

评论?

【问题讨论】:

    标签: asp.net url response.redirect


    【解决方案1】:

    我建议您从 Page 类派生自己的类(“MyPageClass”)并在其中包含此方法:

    public class MyPageClass : Page
    {
        private const string productListPagePath = "~/products/list.aspx?category=";
        protected void GotoProductList(string category)
        {
             Response.Redirect(productListPagePath + category);
        }
    }
    

    然后,在您的代码隐藏中,确保您的页面派生自此类:

     public partial class Default : MyPageClass
     {
          ...
     }
    

    在此范围内,您只需使用以下命令即可重定向:

     GotoProductList("Books");
    

    现在,这有点受限,因为毫无疑问,您将拥有许多其他页面,例如 ProductList 页面。您可以在您的页面类中为它们中的每一个提供自己的方法,但这有点令人讨厌并且不能顺利扩展。

    我通过在其中保留一个带有页面名称/文件名映射的 db 表来解决类似这样的问题(我正在调用外部的、动态添加的 HTML 文件,而不是 ASPX 文件,所以我的需求有点不同,但我认为这些原则适用)。然后,您的调用将使用字符串或更好的枚举来重定向:

     protected void GoToPage(PageTypeEnum pgType, string category)
     {
          //Get the enum-to-page mapping from a table or a dictionary object stored in the Application space on startup
          Response.Redirect(GetPageString(pgType) + category);  // *something* like this
     }
    

    在您的页面上,您的调用将是:GoToPage(enumProductList, "Books");

    好消息是调用的是在祖先类中定义的函数(无需传递或创建管理器对象)并且路径非常明显(如果您使用枚举,智能感知将限制您的范围)。

    祝你好运!

    【讨论】:

    • 我最终做了类似的事情(参见上面的编辑),并将其标记为已接受,因为我使用了 Pages 枚举的想法。谢谢马克。
    【解决方案2】:

    您有很多可用的选项,它们都从创建映射字典开始,而您可以将关键字引用到硬 URL。无论您选择将其存储在配置文件还是数据库查找表中,您的选择都是无穷无尽的。

    【讨论】:

      【解决方案3】:

      您有大量可用的选项。数据库表或 XML 文件可能是最常用的示例。

      // Please note i have not included any error handling code.
      public class RoutingHelper
      {
          private NameValueCollecton routes;
      
          private void LoadRoutes()
          {
              //Get your routes from db or config file 
              routes = /* what ever your source is*/
          }
      
          public void RedirectToSection(string section)
          {
              if(routes == null) LoadRoutes();
      
              Response.Redirect(routes[section]);
          }
      }
      

      这只是示例代码,可以按照您的任何方式实现。您需要考虑的主要问题是要将映射存储在哪里。一个简单的xml文件就可以做到:

      `<mappings>
          <map name="Books" value="/products.aspx/section=books"/>
          ...
      </mappings>`
      

      然后将其加载到您的路线集合中。

      【讨论】:

        【解决方案4】:
        public class BasePage : Page
        {
            public virtual string GetVirtualUrl()
            {
                throw new NotImplementedException();
            }
        
            public void PageRedirect<T>() where T : BasePage, new()
            {
                T page = new T();
                Response.Redirect(page.GetVirtualUrl());
            }
        }
        
        public partial class SomePage1 : BasePage
        {
            protected void Page_Load()
            {
                // Redirect to SomePage2.aspx
                PageRedirect<SomePage2>();
            }
        }
        
        public partial class SomePage2 : BasePage
        {
            public override string GetVirtualUrl()
            {
                return "~/Folder/SomePage2.aspx";
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-02-26
          • 1970-01-01
          • 1970-01-01
          • 2022-10-31
          • 1970-01-01
          • 2021-06-05
          • 2013-04-04
          • 2021-09-11
          • 2011-01-01
          相关资源
          最近更新 更多