Дружественные URL-адреса для ASP.NET

Фреймворки Python всегда предоставляют способы обработки URL-адресов, которые передают данные запроса элегантным способом, например, http://somewhere.overtherainbow.com/userid/123424/

Я хочу, чтобы вы обратили внимание на конечный путь / userid / 123424 /

Как это сделать в ASP.NET?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
0
22 256
6

Ответы 6

Также обратите внимание на ASP.NET MVC или, если вы настроены на веб-формы, на новое пространство имен System.Web.Routing в ASP.NET 3.5 SP1.

В этом примере для реализации понятных URL-адресов используется маршрутизация ASP.NET.

Примеры отображений, которые обрабатывает приложение:

http: // samplesite / userid / 1234 - http: //samplesite/users.aspx? userid = 1234
http: // samplesite / userid / 1235 - http: //samplesite/users.aspx? userid = 1235

В этом примере используются строки запроса и не требуется изменять код на странице aspx.

Шаг 1 - добавьте необходимые записи в web.config

<system.web>
<compilation debug = "true">
        <assemblies>
            …
            <add assembly = "System.Web.Routing, Version=3.5.0.0,    Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </assemblies>
    </compilation>
…
    <httpModules>
    …
        <add name = "UrlRoutingModule" type = "System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        </httpModules>
</system.web>
<system.webServer>
    …
    <modules>
        …
        <add name = "UrlRoutingModule" type = "System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>
    <handlers
…   
        <add name = "UrlRoutingHandler" preCondition = "integratedMode" verb = "*" path = "UrlRouting.axd" type = "System.Web.HttpForbiddenHandler,                 System.Web, Version=2.0.0.0, Culture=neutral,              PublicKeyToken=b03f5f7f11d50a3a"/>
    </handlers>
</system.webServer>

Шаг 2 - добавьте таблицу маршрутизации в global.asax

Определите отображение удобного URL-адреса на страницу aspx, сохранив запрошенный ИД пользователя для дальнейшего использования.

void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add("UseridRoute", new Route
    (
       "userid/{userid}",
       new CustomRouteHandler("~/users.aspx")
    ));
}

Шаг 3 - реализуйте обработчик маршрута

Добавьте строку запроса в текущий контекст до того, как начнется маршрутизация.

using System.Web.Compilation;
using System.Web.UI;
using System.Web;
using System.Web.Routing;

public class CustomRouteHandler : IRouteHandler
{
    public CustomRouteHandler(string virtualPath)
    {
        this.VirtualPath = virtualPath;
    }

    public string VirtualPath { get; private set; }

    public IHttpHandler GetHttpHandler(RequestContext
          requestContext)
    {
        // Add the querystring to the URL in the current context
        string queryString = "?userid = " + requestContext.RouteData.Values["userid"];
        HttpContext.Current.RewritePath(
          string.Concat(
          VirtualPath,
          queryString)); 

        var page = BuildManager.CreateInstanceFromVirtualPath
             (VirtualPath, typeof(Page)) as IHttpHandler;
        return page;
    }
}

Код из users.aspx

Код на странице aspx для справки.

protected void Page_Load(object sender, EventArgs e)
{
    string id = Page.Request.QueryString["userid"];
    switch (id)
    {
        case "1234":
            lblUserId.Text = id;
            lblUserName.Text = "Bill";
            break;
        case "1235":
            lblUserId.Text = id;
            lblUserName.Text = "Claire";
            break;
        case "1236":
            lblUserId.Text = id;
            lblUserName.Text = "David";
            break;
        default:
            lblUserId.Text = "0000";
            lblUserName.Text = "Unknown";
            break;
}

Я знаю, что это старый, но он получил высокие оценки в Google. Есть ли причина, по которой GetHttpHandler никогда не вызывается? Я помещаю туда код, генерирующий ошибку времени выполнения, и, конечно же, вызываются все методы, кроме GetHttpHandler, по запросу.

HMR 14.03.2013 17:38

Это альтернативный пример, который также использует маршрутизацию ASP.NET для реализации удобных URL-адресов.

Примеры отображений, которые обрабатывает приложение:

http: // samplesite / userid / 1234 - http: //samplesite/users.aspx? userid = 1234
http: // samplesite / userid / 1235 - http: //samplesite/users.aspx? userid = 1235

В этом примере не использует строки запроса, но требуется дополнительный код на странице aspx.

Шаг 1 - добавьте необходимые записи в web.config

<system.web>
<compilation debug = "true">
        <assemblies>
            …
            <add assembly = "System.Web.Routing, Version=3.5.0.0,    Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </assemblies>
    </compilation>
…
    <httpModules>
    …
        <add name = "UrlRoutingModule" type = "System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        </httpModules>
</system.web>
<system.webServer>
    …
    <modules>
        …
        <add name = "UrlRoutingModule" type = "System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>
    <handlers
…   
        <add name = "UrlRoutingHandler" preCondition = "integratedMode" verb = "*" path = "UrlRouting.axd" type = "System.Web.HttpForbiddenHandler,                 System.Web, Version=2.0.0.0, Culture=neutral,              PublicKeyToken=b03f5f7f11d50a3a"/>
    </handlers>
</system.webServer>

Шаг 2 - добавьте таблицу маршрутизации в global.asax

Определите отображение удобного URL-адреса на страницу aspx, сохранив запрошенный ИД пользователя для дальнейшего использования.

void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add("UseridRoute", new Route
    (
       "userid/{userid}",
       new CustomRouteHandler("~/users.aspx")
    ));
}

Шаг 3 - реализуйте обработчик маршрута

Передайте на страницу контекст маршрутизации, содержащий параметр. (Обратите внимание на определение IRoutablePage)

using System.Web.Compilation;
using System.Web.UI;
using System.Web;
using System.Web.Routing;

public interface IRoutablePage
{
    RequestContext RequestContext { set; }
}

public class CustomRouteHandler : IRouteHandler
{
    public CustomRouteHandler(string virtualPath)
    {
        this.VirtualPath = virtualPath;
    }

    public string VirtualPath { get; private set; }

    public IHttpHandler GetHttpHandler(RequestContext
          requestContext)
    {
        var page = BuildManager.CreateInstanceFromVirtualPath
             (VirtualPath, typeof(Page)) as IHttpHandler;

        if (page != null)
        {
            var routablePage = page as IRoutablePage;

            if (routablePage != null) routablePage.RequestContext = requestContext;
        }

        return page;
    }
}

Шаг 4 - Получите параметр на целевой странице

Обратите внимание на реализацию IRoutablePage.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Routing;

public partial class users : System.Web.UI.Page, IRoutablePage
{
    protected RequestContext requestContext;

    protected object RouteValue(string key)
    {
        return requestContext.RouteData.Values[key];
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        string id = RouteValue("userid").ToString();
        switch (id)
        {
            case "1234":
                lblUserId.Text = id;
                lblUserName.Text = "Bill";
                break;
            case "1235":
                lblUserId.Text = id;
                lblUserName.Text = "Claire";
                break;
            case "1236":
                lblUserId.Text = id;
                lblUserName.Text = "David";
                break;
            default:
                lblUserId.Text = "0000";
                lblUserName.Text = "Unknown";
                break;
        }
    }

    #region IRoutablePage Members

    public RequestContext RequestContext
    {
        set { requestContext = value; }
    }

    #endregion
}

С этой реализацией мне повезло больше, чем с другой. У queryString были проблемы при использовании Ajax. Эта реализация немного сложнее, но она того стоила.

proudgeekdad 29.03.2011 07:13

Вот еще один способ сделать это с помощью ASP.NET MVC

Во-первых, вот код контроллера с двумя действиями. Индекс получает список пользователей из модели, идентификатор пользователя получает отдельного пользователя:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcApplication1.Controllers
{
    public class UsersController : Controller
    {
        public ActionResult Index()
        {
            return View(Models.UserDB.GetUsers());
        }
        public ActionResult userid(int id)
        {
            return View(Models.UserDB.GetUser(id));
        }
    }
}

Вот представление Index.asp, оно использует ActionLink для создания ссылок в правильном формате:

<%@ Page Language = "C#" AutoEventWireup = "true" CodeBehind = "Index.aspx.cs" Inherits = "MvcApplication1.Views.Index" %>
<%@ Import Namespace = "MvcApplication1.Controllers" %>
<%@ Import Namespace = "MvcApplication1.Models" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml" >
<head runat = "server">
    <title></title>
</head>
<body>
    <div>
    <h2>Index of Users</h2>
           <ul>
            <% foreach (User user in (IEnumerable)ViewData.Model) { %>
                 <li>
                       <%= Html.ActionLink(user.name, "userid", new {id = user.id })%>
                 </li>
            <% } %>
           </ul>
    </div>
</body>
</html>

А вот представление userid.aspx, в котором отображаются сведения о человеке:

<%@ Page Language = "C#" AutoEventWireup = "true" CodeBehind = "userid.aspx.cs" Inherits = "MvcApplication1.Views.Users.userid" %>
<%@ Import Namespace = "MvcApplication1.Controllers" %>
<%@ Import Namespace = "MvcApplication1.Models" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml">
<head runat = "server">
    <title></title>
</head>
<body>
    <div>
        <table border  = "1">
            <tr>
                <td>
                ID
                </td>
                <td>
                <%=((User)ViewData.Model).id %>
                </td>
            </tr>
            <tr>
                <td>
                Name
                </td>
                <td>
                <%=((User)ViewData.Model).name %>
                </td>
            </tr>
        </table>
    </div>
</body>
</html>

И, наконец, для полноты картины приведем код модели:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class UserDB
    {
        private static List<User> users = new List<User>{
            new User(){id=12345, name = "Bill"},
            new User(){id=12346, name = "Claire"},
            new User(){id=12347, name = "David"}
        };

        public static List<User> GetUsers()
        {
            return users;
        }

        public static User GetUser(int id)
        {
            return users.First(user => user.id == id);
        }

    }

    public class User
    {
        public int id { get; set; }
        public string name { get; set; }
    }
}

Я использую переписчик URL от Intelligencia:

http://urlrewriter.net/

Настроить его было так просто - может быть, час на то, чтобы все это настроить и запустить. Очень мало проблем с этим ...

Я бы порекомендовал это, но должен отметить, что не пробовал других.

Удачи!

Я разработал Библиотека NuGet с открытым исходным кодом для этой проблемы, который неявно преобразует EveryMvc / Url в каждый-mvc / url.

Пунктирные URL-адреса намного удобнее для SEO и легче читаются. URL-адреса в нижнем регистре, как правило, создают меньше проблем. (Подробнее в моем сообщении в блоге)

Пакет NuGet: https://www.nuget.org/packages/LowercaseDashedRoute/

Чтобы установить его, просто откройте окно NuGet в Visual Studio, щелкнув правой кнопкой мыши Project и выбрав NuGet Package Manager, а на вкладке «Online» введите «Lowercase Dashed Route», и он должен появиться.

В качестве альтернативы вы можете запустить этот код в консоли диспетчера пакетов:

Install-Package LowercaseDashedRoute

После этого вы должны открыть App_Start / RouteConfig.cs и закомментировать существующий вызов route.MapRoute (...) и добавить вместо него следующее:

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
  new RouteValueDictionary(
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
    new DashedRouteHandler()
  )
);

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

URL-адрес проекта с открытым исходным кодом: https://github.com/AtaS/lowercase-dashed-route

Другие вопросы по теме