ASP.NET - избегайте жестких путей - PullRequest
5 голосов
/ 20 января 2010

Я ищу оптимальное решение, которое направлено на уменьшение количества URL-адресов, жестко закодированных в приложении ASP.NET.

Например, при просмотре экрана сведений о продукте, выполнении редактирования этих сведений и последующей передаче изменений пользователь перенаправляется обратно на экран списка продуктов. Вместо того, чтобы кодировать следующее:

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

Я бы хотел иметь решение, позволяющее мне сделать что-то вроде этого:

Pages.GotoProductList("books");

где Pages является членом общего базового класса.

Я просто наплевал и хотел бы услышать любой другой способ, которым кто-либо управляет перенаправлениями своих приложений.

EDIT

Я закончил тем, что создал следующее решение: у меня уже был общий базовый класс, к которому я добавил перечисление Pages (спасибо Mark), каждый элемент имел атрибут System.ComponentModel.DescriptionAttribute, содержащий URL страницы:

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

Затем я создал несколько перегруженных методов для обработки различных сценариев. Я использовал отражение, чтобы получить URL-адрес страницы через атрибут Description, и я передаю параметры строки запроса как анонимный тип (также используя отражение для добавления каждого свойства в качестве параметра строки запроса):

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"});

Комментарии

Ответы [ 3 ]

4 голосов
/ 20 января 2010

Я бы посоветовал вам получить свой собственный класс («MyPageClass») из класса Page и включить в него этот метод:

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. Вы могли бы дать каждому из них свой собственный метод в своем классе страниц, но это довольно уродливо и не является плавно расширяемым.

Я решаю проблему подобного рода, сохраняя таблицу базы данных с отображением имени страницы / имени файла (я вызываю внешние, динамически добавляемые файлы 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, "Книги");

Приятно то, что вызов относится к функции, определенной в классе предков (не нужно передавать или создавать объекты менеджера), и путь довольно очевиден (intellisense ограничит ваши диапазоны, если вы используете перечисление).

Удачи!

1 голос
/ 20 января 2010

У вас есть огромное количество вариантов, доступных здесь. Таблица базы данных или файл 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>`

, а затем просто загрузите это в свою коллекцию маршрутов.

1 голос
/ 20 января 2010

У вас есть множество доступных опций, и все они начинаются с создания словаря сопоставления, тогда как вы можете ссылаться на ключевое слово на жесткий URL. Независимо от того, решили ли вы сохранить его в файле конфигурации или в таблице поиска в базе данных, ваши возможности безграничны.

...