Любите “макароны"?
Мне доводилось тратить много времени на поиск и устранение проблем, связанных неправильно указанными или пропущенными параметрами для страницы вебсайта. Я часто вижу в коде ASP.NET страницы мракобесие, подобное этому:
...
if (Request.RawUrl.ToLowerInvariant().Contains("/category/"))
{
DisplayCategories();
}
else if (Request.RawUrl.ToLowerInvariant().Contains("/author/"))
{
DisplayAuthors();
}
else if (Request.RawUrl.ToLowerInvariant().Contains("?tag="))
{
DisplayTags();
}
else if (Request.QueryString["year"] != null
|| Request.QueryString["date"] != null
|| Request.QueryString["calendar"] != null)
{
if (Request.RawUrl.Contains("year="))
Redirect();
else
DisplayDateRange();
}
else if (Request.QueryString["apml"] != null)
{
DisplayApmlFiltering();
}
else if (Request.QueryString.Count == 0
|| !string.IsNullOrEmpty(Request.QueryString["entry"])
|| !string.IsNullOrEmpty(Request.QueryString["theme"])
|| !string.IsNullOrEmpty(Request.QueryString["blog"]))
{
DisplayNormal();
}
...
Несчастная страница пытается обработать десятки различных наборов параметров. Из десятка вызывающих страниц эти ссылки собираются также вручную. И подобная каша варится во всем веб приложении, постепенно превращая код страниц в помойку. Знакомая ситуация?
Это можно предотвратить.
И сделать это можно инкапсулировав логику по созданию и разбору строки запроса (или хотя бы параметров этого запроса) внутрь отдельного класса. Можно создать примерно такой класс для параметров конкретной страницы - назовем его PageParameters:
public class PageParameters
{
public enum Name
{
Id,
Year,
Date
}
public string Id { get; set; }
public string Year { get; set; }
public string Date { get; set; }
public PageParameters()
{
// You could add default value initialization,
}
public PageParameters(NameValueCollection queryString)
{
Id = Retrieve(queryString, Name.Id);
Year = Retrieve(queryString, Name.Year);
Date = Retrieve(queryString, Name.Date);
}
public PageParameters(string queryString)
{
Id = Retrieve(queryString, Name.Id);
Year = Retrieve(queryString, Name.Year);
Date = Retrieve(queryString, Name.Date);
}
private static string Retrieve(NameValueCollection queryString,
Name parameterName)
{
string parameterValue = queryString[parameterName.ToString()];
if (string.IsNullOrEmpty(parameterValue))
{
// You could add default value initialization, or throw the error, etc..
}
return parameterValue;
}
public override string ToString()
{
// You could also add the conditions - whether to add
// the parameter is it was not set or not...
StringBuilder queryString = new StringBuilder();
queryString.AppendFormat("{0}={1}", Name.Id, Id);
queryString.Append("&");
queryString.AppendFormat("{0}={1}", Name.Year, Year);
queryString.Append("&");
queryString.AppendFormat("{0}={1}", Name.Date, Date);
return queryString.ToString();
}
}
Теперь - как его использовать?
На странице, которая должна уметь обрабатывать какие-то параметры рекоммендуется создавать статические методы для создания ссылки на эту страницу:
public class OnePage : System.Web.UI.Page
{
...
public static string GetShortLink()
{
return "OnePage.aspx";
}
public static string GetFullLink(string id, string year, string date)
{
// result will be:
// "OnePage.aspx?Id=<id>&Year=<year>&Date=<date>"
return string.Format("{0}?{1}", GetShortLink(),
new PageParameters {Id = id, Year = year, Date = date});
}
...
}
Там, где необходимо сегнерировать ссылку на страницу OnePage используем примерно такой код:
goOnePageHyperLink.NavigateUrl =
OnePage.GetFullLink("13", "2010", "18-02-2010");
Бонусы инкапсуляции параметров:
1. Мы теперь сможем не беспокоиться о поддержании имен параметров в консистентном состоянии по всему коду веб приложения.
2. Добавить все необходимые манипуляции с параметрами строки запроса в код класса PageParameters для удобства обработки вариантов запросов и повышения читаемости кода.
3. Централизовать логику разбора и составления строки запроса.
4. Избавиться от использования большого количества hard-coded строк.
Экономьте время!