我的网站上列出了大约1700篇使用ASP.NET 4.0 Web窗体创建的文章。这些文章的网址格式为:
http://www.mymymyarticles.com/Article.aspx?ID=400
我已经探索了ASP.NET友好URL以及IIS URL重写。这些扩展很棒但是一旦创建了规则,它们就会对所有网址进行一般处理。
我是否有可能为我网站上的每个网址手动生成自己的网址字符串?例如:
我希望将http://www.mymymyarticles.com/Article.aspx?ID=400
永久重定向到http://www.mymymyarticles.com/this-is-a-very-long-url
,而
http://www.mymymyarticles.com/Article.aspx?ID=500
可以重定向到http://www.mymymyarticles.com/article/short-url
和
http://www.mymymyarticles.com/Article.aspx?ID=523
可以重定向到http://www.mymymyarticles.com/very-short-url
所以你可以看到我想手动生成的网址没有统一性。基本上我想完全控制网址。我怎么能这样做呢。 会影响效果吗?
感谢任何例子。
答案 0 :(得分:0)
我通过使用以下架构
在服务器上创建xml文件来克服这个问题<URLMapper>
<Code>1</Code>
<OLDURL>%Oldurl.aspx%</OLDURL>
<NEWURL>default.aspx</NEWURL>
<PermanentRedirect>true</PermanentRedirect>
<Order>1</Order>
<Status>true</Status>
</URLMapper>
将Application_Start Event中的这个加载到应用程序变量中(以数据表的形式)。
并在Begin Request -
中void Application_BeginRequest(object sender, EventArgs e)
{
if (Application["URLMapper"] == null) return;
DataTable dtURLs = Application["URLMapper"] as DataTable;
if (dtURLs.Rows.Count == 0) return;
string OrigUrl = HttpContext.Current.Request.Url.ToString().ToLower().Replace("'", "`");
DataRow[] drFound = dtURLs.Select("Status = true and '" + OrigUrl.Trim() + "' like oldurl", "Order",DataViewRowState.CurrentRows);
if (drFound.Length == 0) return;
string OldURL = drFound[0]["OldURL"].ToString().Replace("%","");
Response.RedirectPermanent(OrigUrl.Replace(OldURL, drFound[0]["NewURL"].ToString().Trim()), true);
return;
}
答案 1 :(得分:0)
您是否有办法将ID映射到新页面的网址?如果是这种情况,您可以使用ASP.NET路由实现此目的。我要做的是从定义路线开始:
var route = routes.MapRoute(
"LegacyDocument",
"Articles.aspx{*pathInfo}",
null,
constraints: new { pathInfo = new LegacyDocumentRouteConstraint() }
);
route.RouteHandler = new RedirectRouteHandler();
此路由仅捕获/articles.aspx
的任何请求,但它具有约束和自定义路由处理程序。
约束的目的是确保我们至少拥有ID查询字符串属性,它是一个数字:
public class LegacyDocumentRouteConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.UrlGeneration)
{
// Don't both doing anything while we generate links.
return false;
}
string id = httpContext.Request.QueryString["id"];
if (string.IsNullOrWhiteSpace(id))
{
// No query string argument was provided.
return false;
}
int documentId;
if (!int.TryParse(id, out documentId))
{
// The Id is not a number.
return false;
}
// Set the output document Id in the route values.
values["documentId"] = documentId;
return true;
}
}
如果未提供ID,或者不是数字,我们无法匹配现有文档,因此将跳过该路线。但是当满足约束时,我们将一个变量存储在路由值values["documentId"] = documentId
中,这样我们就可以在以后的路由处理程序中再次使用它(而不必再次从查询字符串中解析它):
public class RedirectRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext context)
{
int documentId = (int)context.RouteData.Values["documentId"];
return new RedirectLegacyDocumentHttpHandler(documentId);
}
private class RedirectLegacyDocumentHttpHandler : IHttpHandler
{
private int _documentId;
public RedirectHttpHandler(int documentId)
{
_documentId = documentId;
}
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
var response = context.Response;
string url = ResolveNewDocumentUrl();
if (url == null)
{
// Issue a 410 to say the document is no longer available?
response.StatusCode = 410;
}
else
{
// Issue a 301 to the new location.
response.RedirectPermanent(url);
}
}
public string ResolveNewDocumentUrl()
{
// Resolve to a new url using _documentId
}
}
}
路由处理程序执行从ASP.NET路由映射回ASP.NET运行时的IHttpHandler
逻辑的逻辑。在普通的MVC中,这将映射到调用控制器的标准MvcHandler,但在我们的例子中,我们只需要发出重定向。
在路由处理程序中,我们从路由值中获取文档ID,并创建一个执行实际重定向的新HTTP处理程序。您需要找到解决实际新网址(ResolveNewDocumentUrl
)的位置,但通常会解析网址,如果网址返回为null,我们将发出{{ 1}}回复说客户(更重要的是抓取工具)项目不再存在,或者它会向新网址发出带有相应位置标头的HTTP 410 Gone
。