동적 URL과 함께 web.sitemap 사용 (URL 라우팅)
-
08-07-2019 - |
문제
Web.Sitemap에서 "대략적인"일치와 일치하고 싶습니다.
Web.sitemap 정적 사이트 맵 제공 업체는 한 가지를 제외하고 잘 작동합니다. 정적입니다!
따라서 내 페이지의 10,000 개의 기사 각각에 대한 SiteemapNode가 있어야한다면 다음과 같습니다.
- site.com/articles/1/article-title
- site.com/articles/2/another-article-title
- site.com/articles/3/another-article-again
- ...
- site.com/articles/9999/the-rast-article
기사 아래에있는 일에 맞게 사이트 맵으로 할 수있는 야생 카드 매핑이 있습니까?
아니면 내 WebForms 페이지에 현재 노드를 수동으로 설정하는 방법이 있습니까?
나는 "비트"의 도움을 찾았습니다 이 페이지 ASP.NET MVC 프레임 워크 에서이 작업을 수행 할 때 여전히 WebForms를위한 좋은 솔루션을 찾고 있습니다.
내가해야 할 일은 사용자 정의 사이트 맵 제공 업체를 만드는 것입니다.
해결책
이것은 위의 의견에 대한 응답입니다. 전체 코드를 게시 할 수는 없지만 기본적으로 제공자가 작동하는 방식입니다.
페이지 article.aspx가 있다고 가정하고 쿼리 문자열 매개 변수 "ID"를 사용하여 기사 제목과 본문을 검색하고 표시합니다. 그런 다음 이것은 web.sitemap에 있습니다.
<siteMapNode url="/article.aspx" title="(this will be replaced)" param="id" />
그런 다음이 수업을 만듭니다.
public class DynamicSiteMapPath : SiteMapPath
{
protected override void InitializeItem(SiteMapNodeItem item)
{
if (item.ItemType != SiteMapNodeItemType.PathSeparator)
{
string url = item.SiteMapNode.Url;
string param = item.SiteMapNode["param"];
// get parameter value
int id = System.Web.HttpContext.Current.Request.QueryString[param];
// retrieve article from database using id
<write your own code>
// override node link
HyperLink link = new HyperLink();
link.NavigateUrl = url + "?" + param + "=" + id.ToString();
link.Text = <the article title from the database>;
link.ToolTip = <the article title from the database>;
item.Controls.Add(link);
}
else
{
// if current node is a separator, initialize as usual
base.InitializeItem(item);
}
}
}
마지막으로, 정적 제공 업체를 사용하는 것처럼 코드 에서이 공급자를 사용합니다.
<mycontrols:DynamicSiteMapPath ID="dsmpMain" runat="server" />
내 수업은 이것보다 더 복잡하지만 이것들은 기본입니다. QueryString 매개 변수를 사용하는 대신 사용중인 우호적 인 URL을 분석하여 올바른 컨텐츠를 검색하는 데 사용할 수 있습니다. 모든 요청마다 추가 DB 조회를 최소화하려면 제공 업체에 캐싱 메커니즘을 추가 할 수 있습니다 (기사 제목은 일반적으로 자주 변경되지 않습니다).
도움이 되었기를 바랍니다.
다른 팁
이것은 내가 생각하는 당신의 질문에 대한 대답은 아니지만 아마도 당신에게 아이디어를 줄 수 있습니다. 한 번은 DynamicSitemAppath 클래스를 상속받는 SetemAppath를 작성했습니다. 각각에 사용자 정의 속성을 사용합니다 <siteMapNode>
Web.sitemap에서 태그 : 다음과 같습니다.
<siteMapNode url="dynamicpage.aspx" title="blah" params="id" />
그런 다음 DynamicSitemAppath 클래스는 "ID"매개 변수 값을 가져오고 데이터베이스에서 컨텐츠를 검색하며 현재 렌더링 된 SiteMap 항목 노드를 올바른 제목 및 링크로 무시합니다. 약간의 작업이 필요하지만 올바르게 수행하면 동적 페이지 지원을 제공하는 매우 깔끔한 방법입니다.
나는이 문제에 빠졌고 솔직히, 나를 행복하게하는 솔루션을 찾지 못했습니다 ... 그래서 나는 여기저기서 아이디어를 빌 렸습니다. 내 솔루션은 멀티 부문입니다. a) SiteemApprovider가 실제 페이지를 찾아 요청을 처리하고 노드를 사용하고 b) 표준 기술을 사용하여 사이트에서 사이트를 업데이트하십시오.
a) 내가 계속 실행 한 문제는 올바른 가상 경로가 없다면 Sitemap.currentNode가 NULL이고 SiteMapResolve 기능의 화재가된다는 것입니다. 이것을 해결하려면 XMLSITEMAPPROVIDER를 하위 클래스하고 CurrentNode를 무시합니다.
namespace WebFormTools
{
class RouteBaseSitemapProvider : XmlSiteMapProvider
{
public override SiteMapNode CurrentNode
{
get
{
var node = base.CurrentNode;
if (node == null)
{
// we don't have a node, see if this is from a route
var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;
if (page != null && page.RouteData != null)
{
// try and get the Virtual path associated with this route
var handler = page.RouteData.RouteHandler as PageRouteHandler;
if (handler != null) {
// try and find that path instead.
node = FindSiteMapNode(handler.VirtualPath);
}
}
}
return node;
}
}
}
}
기본적으로 기본 구현에 아무것도 찾지 못하면 경로를 찾아서 (있는 경우) 핸들러의 가상 경로를 사용하여 노드를 찾으십시오.
참조는 여기 내 web.config, global.asax 및 siteemap 파일의 일부입니다.
제공자 추가
<siteMap defaultProvider="RouteBaseSitemapProvider">
<providers>
<add name="RouteBaseSitemapProvider" type="WebFormTools.RouteBaseSitemapProvider" siteMapFile="Web.sitemap" />
</providers>
</siteMap>
경로:
routes.MapPageRoute("EvalRoutes",
"Evals/{type}/New.aspx",
"~/Evals/New.aspx");
그리고 사이트 맵 :
<siteMapNode url="~/Evals/New.aspx" title="New Eval - {type}" description="" />
b) I 서브 클래스 System.web.ui.page, 적절하게 이름이 지정된 BaseClass는 SiteemapResolve 이벤트에 핸들러를 등록하는 메소드를 추가합니다.
public System.Web.SiteMapNode Process(System.Web.SiteMapNode currentNode)
{
if (currentNode == null) return currentNode;
var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;
if (page != null && page.RouteData != null)
{
Dictionary<Regex, string> replacements = new Dictionary<Regex, string>();
// build a list of RegEx to aid in converstion, using RegEx so I can ignore class. Technically I could also
foreach (var key in page.RouteData.Values.Keys)
{
replacements.Add(new Regex(string.Format("\\{{{0}\\}}", key), RegexOptions.IgnoreCase), page.RouteData.Values[key].ToString());
}
// navigate up the nodes
var activeNode = currentNode;
while (activeNode != null)
{
// to the replacements
foreach(var replacement in replacements)
{
activeNode.Title = replacement.Key.Replace(activeNode.Title, replacement.Value);
}
activeNode = activeNode.ParentNode;
}
}
return currentNode;
}
여전히 URLS 맵을 적절하게 가져와야합니다 (경로를 수신하는 페이지의 URL을 사용합니다). 아마도 사이트 맵에서 사용자 정의 속성을 사용하여 노드에 URL을 렌더링하는 방법을 알려줄 것입니다.