четверг, 7 августа 2008 г.

URL rewriting в ASP.NET

URL rewriting - это такая штука, которая позволяет из некрасивых урлов с параметрами, вроде
www.somesite.ru/?cat=blogs&author=darja&year=2008&month=8
позволяет делать красивые, т.н. Человеку понятные урлы (ЧПУ), вроде
www.somesite.ru/blogs/darja/2008/8

Возникла у меня такая задача. Есть табличка (вернее, ListView), данные в которой располагаются на нескольких страницах. Пейджер у таблицы устроен так, что к N-ной странице можно обратиться http://localhost/Default.aspx?page=N И вот захотелось, чтобы к n-ной странице таблички можно было бы обратиться как http://localhost/N. Типа так ссылки приятнее выглядят и роботам хорошо. Итак, было найдено следующее решение.

URL rewriting

  1. Скачиваем библиотеку ThunderMain.URLRewriter.dll, кидаем в свой проект.
  2. В Global.asax добавляем:
    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
      ThunderMain.URLRewriter.Rewriter.Process();
    }
    
  3. Вносим изменения в web.config. В configSections пишем:
    <sectionGroup name="system.web">
      <section name="urlrewrites" type="ThunderMain.URLRewriter.Rewriter, ThunderMain.URLRewriter,
     Version=1.0.783.30976, Culture=neutral, PublicKeyToken=7a95f6f4820c8dc3"/></sectionGroup>
    
    Далее, в system.web пишем:
    <urlrewrites><rule>
      <url>/(\d*)</url>
      <rewrite>Default.aspx?page=$1</rewrite></rule>
    </urlrewrites>
    
    Элементов rule может быть несколько. В узле url указывается регулярное выражение, которому должен удовлетворять url, который мы хотим переписывать, в rewrite - на что мы будем его заменять. Можно использовать стандартные для регулярных выражений группы ($1, $2 и т.д., как в перле). В нашем случае, по адресу http://localhost/N, где N - число, загрузится http://localhost/Default.aspx?page=N. Всё очень просто.
  4. Также потребуется некоторая донастройка IIS. А именно, нужно зайти в настройки сайта -> Home directory -> Configuration -> Mappings и добавить там обработчик для файлов .* такой же, как для aspx (ну там C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll). И обязательно снять галочку "Verify that file exists".
UPDATE: Кстати, у меня тут практика показала, что прописывать в IIS мэппинг для .* не есть хорошо, потому что при этом ломаются стили и прочие статические файлы, потому что IIS и их начинает спрашивать с asp.net-a. Я в итоге, дабы не париться, сделала адреса вида http://localhost/N.htm и добавила в IIS мэппинг только для .htm

Пейджер у ListView

Итак, к страницам уже можно обращаться по адресу http://localhost/N. Но в ссылки пейджера всё ещё выглядят по-прежнему. Делаем следующее.
  1. Пейджер выносим в отдельный div и ставим у него style="display:none".
  2. Под листвью добавляем панельку:
    <asp:Panel ID="Pager" runat="server" onprerender="Pager_PreRender">
    </asp:Panel>
    
  3. В коде пишем:
    protected void Pager_PreRender(object sender, EventArgs e)
    {
      Pager.Controls.Clear();
    
      DataPager pager = (DataPager)RatingListView.FindControl("RatingPager");
    
      int count = pager.TotalRowCount;
      int pageSize = pager.PageSize;
      int pagesCount = count / pageSize + (count % pageSize == 0 ? 0 : 1);
      int pageSelected = pager.StartRowIndex / pageSize + 1;
    
      for (int i = 1; i <= pagesCount; ++i)
      {
        if (pageSelected != i)
        {
          HyperLink link = new HyperLink();
          link.NavigateUrl = link.ResolveUrl(i.ToString());
          link.Text = i.ToString();
          Pager.Controls.Add(link);
        }
        else
        {
          Label label = new Label();
          label.Text = i.ToString();
          Pager.Controls.Add(label);
        }
    
        Literal space = new Literal();
        space.Text = " ";
        Pager.Controls.Add(space);
      }
    }
    
    Здесь RatingListView - наш листвью, RatingPager - его "родной" пейджер.

Литература