背景
我们网站上有一些链接,其格式如下:
http://oursite.com/books/c_sharp_in_depth_12345。
为了处理这个问题,我们使用了一个简单的属性,叫做Url
:
public class Book
{
public string Url { get; set;}
}
基本上,URL 来自我们网站的域、网站的一部分(即书籍)、页面名称和用于识别资源的唯一 ID。完整的 URL 存储在数据库中。
我们不喜欢我们的数据库存储部分名称的事实。这是 Web 图层属性的属性,而不是书籍的属性。数据库不应依赖于 web 层。
因此,我们从 URL 中删除该部分并获得以下内容:
public class Book
{
public string UrlWithoutSection { get; set;}
}
好的,这适用于这个 URL。但是后来我们公司的 SEO 沙皇说我们的 URL 是错误的,而我们的真爱谷歌只有在我们像这样重写我们的 url 时才会爱我们:
http://oursite.com/programming-books/c-sharp-in-depth-12345
呃,哦,我以为我们已经删除了对web层的数据库依赖,但是我们没有。事实证明,我们已经删除了对该部分的依赖,但 URL 的格式仍然存在于数据库中。我们通过将 URL 抽象为一个对象来解决这个问题:
public class OurUrl
{
public string title { get; set; }
public string id { get; set; }
}
酷,现在对 web 层的依赖已经消失了。哦哦,这次我们的CEO来找我们了。我们刚买了一家新公司,现在我们卖杂志。嗯,很棒吗?杂志 URL 将如下所示:
http://oursite.com/magazines/computers/stack-overflow-the-magazine/2012/01/01/12345
好的,没问题,只需创建另一个对象。
public class OurMagazineUrl : OurUrl
{
public DateTime PublishedDate { get; set; }
// Magazine enum will have to be created.
public MagazineType Type { get; set; }
}
它有效,但我开始意识到我们有一个大网站的计划。很多网址。许多不同格式的 URL。每次创建一个新类似乎都是一件令人头疼的事情。
简而言之问题
您如何处理 URL,以便 Web 层与业务层和数据层正确解耦?我想出了几个关于解决方案的想法:
有关问题的更多信息
我希望这有助于澄清一些困惑。
我们正在使用 ASP.Net MVC。我们使用路线。我们使用助手。我们将扁平化的 DTO 传递给我们的 Web 层,而不是业务对象。这个问题涉及服务层和 DTO 的爆炸式增长。
这主要是一个高流量的新闻网站,而不是一个行业网站。它可以有许多不同的网址,并且网址可以随时更改。它们可能很复杂,并且可以由管理层任意确定。
URL 示例(不是真实的,出于示例目的而编造)。
1. http://oursite.com/news/wi/politics/supreme-court/recent-ruling-someid
2. http://oursite.com/news/wi/politics/election-2012/candidate-x-takes-stand-on-issue-y-someid
3. http://oursite/com/news/politics/mayor-says-things-are-a-ok-someid
4. http://oursite.com/news/milwaukee/local-bar-named-to-HOF-someid
5. http://oursite.com/news/wi/politics/supreme-court-someid
6. http://oursite.com/news/whatever-cat-our-CEO-wants/subcat1/subcat2/etc/2011/10/31/some-story-someid
以上都是“文章”,我们有一个文章类。一篇文章有许多导航属性,例如 AuthorObject、RelatedLinksCollection 等。业务对象太重而无法传递给客户端,因此我们传递了扁平化信息的 DTO(例如 AuthorName)。然而,上述链接可能需要不同的信息,即使它们都是“文章”。
- 需要类别、子类别、标题和 ID
- 需要类别、子类别、政治类别、标题和 ID
- 需要类别、标题和 ID
- 需要类别、标题和 ID
- 需要类别、子类别、标题和 ID
- 需要 CEOCategory、CeoSubcategory、PublishedDate、Title 和 Id
在静态编程语言(例如 c#)中,通常的处理方法是创建单独的 DTO 类。您可以添加继承来减少一些代码,但您仍然会得到多个“文章”dto 类。
public class IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public class StateArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string StateCode { get; set; }
public string Subcategory { get; set; }
}
public class SupremeCourtArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string Subcategory { get; set; }
}
public class ArbitraryCeoArticleDto: IArticleDto {
//who knows
}
等等
以任何可能的方式编写自定义网址的能力不可协商。如果一篇文章与某事(状态、类别等)相关,它可以成为 url 的一部分。
解决方案?
根据需要继续添加
Url
对象。多少?至少有十几个,但命名它们会很麻烦。为每个业务对象做一个可以解决名称问题,但这意味着数十或数百个新对象。呸。IOC - 通过配置将路由模式传递给数据访问层。然后数据访问层可以创建一个完整的 url。url 模式名称仍然是一个问题。
使用
Dictionary<TKey, TValue>
,KeyValuePair<TKey, TValue>
等来拉入。使用
Expando
orDynamicObject
作为 url 详细信息。因此 url 将包含几个基本属性(name
和id
),但必要时可以添加其他属性。
我正在考虑使用 4),因为动态编程似乎比静态语言做得更好。但是,可能只是我最看重它,因为我喜欢玩新玩具(我以前没有使用过expando)。
由于对象爆炸,它比 1) 更好。我不确定 2) 是否适用于复杂的场景。您可以使用 DI 将简单的路由名称 + 路由信息传递给数据层,但在没有额外收益的情况下似乎更难完成。它可能不适用于复杂的路线——为此,我认为您需要在 UI 端有一个规则引擎。
与 3) 相比,我认为 4) 稍微好一些。如果我弄错了,有人纠正我,但动态类型似乎只不过是字典顶部的语法糖,但具有更简洁的代码的优势。只是一个想法。