Python 框架总是提供处理 URL 的方法,这些 URL 以优雅的方式传达请求的数据,例如 http://somewhere.overtherainbow.com/userid/123424/
我想让你注意结束路径 /userid/123424/
在 ASP.NET 中如何做到这一点?
此示例使用 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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 页面的映射,保存请求的用户 ID 供以后使用。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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 步 - 实现路由处理程序
在路由发生之前将查询字符串添加到当前上下文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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页面上的代码供参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 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;
} |
这是另一个使用 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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 页面的映射,保存请求的用户 ID 供以后使用。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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的定义)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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 的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| 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
} |
我一直在使用 Intelligencia 的 URL 重写器:
http://urlrewriter.net/
配置非常简单 - 可能需要一个小时才能全部启动并运行。很少有问题...
我会推荐它,但我应该提到我没有尝试过任何其他的。
祝你好运!
这是使用 ASP.NET MVC 的另一种方法
首先,这是包含两个操作的控制器代码。 Index 从模型中获取用户列表,userid 获取单个用户:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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 以正确的格式创建链接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| %@ 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
h2Index 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 视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| %@ 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 |
最后为了完整起见,下面是模型代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcApplication1.Models
{
public class UserDB
{
private static ListUser users = new ListUser{
new User(){id=12345, name="Bill"},
new User(){id=12346, name="Claire"},
new User(){id=12347, name="David"}
};
public static ListUser 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; }
}
} |
我为这个问题开发了一个开源 NuGet 库,它隐式地将 EveryMvc/Url 转换为 every-mvc/url。
虚线网址对 SEO 更友好且更易于阅读。小写 URL 往往会产生较少的问题。 (更多关于我的博文)
NuGet 包:https://www.nuget.org/packages/LowercaseDashedRoute/
要安装它,只需在 Visual Studio 中打开 NuGet 窗口,方法是右键单击项目并选择 NuGet 包管理器,然后在"在线"选项卡上键入"小写虚线路径",它应该会弹出。
或者,您可以在包管理器控制台中运行此代码:
Install-Package LowercaseDashedRoute
之后,您应该打开 App_Start/RouteConfig.cs 并注释掉现有的 route.MapRoute(...) 调用并添加它:
1 2 3 4 5 6
| routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller ="Home", action ="Index", id = UrlParameter.Optional }),
new DashedRouteHandler()
)
); |
就是这样。所有的 url 都是小写、虚线和隐式转换,无需您执行任何操作。
开源项目网址:https://github.com/AtaS/lowercase-dashed-route
另外,请查看 ASP.NET MVC,或者如果您设置在 webforms 上,请查看 ASP.NET 3.5 SP1 中的新 System.Web.Routing 命名空间