【问题标题】:ASP.NET MVC routing based on data store values基于数据存储值的 ASP.NET MVC 路由
【发布时间】:2010-12-29 12:02:37
【问题描述】:

你会如何解决这个问题:

我的数据存储中有数据。每个项目都有以下信息:

  • URL = 将与请求一起使用的任意数量的第一路由段
  • 某些项目类型 = 显示将与此类型相关(继续阅读)
  • title = 用于例如在我的应用程序中导航

由于每个项目可以有任意数量的段,我创建了一个自定义路由,它允许我在不使用默认路由和单个贪婪路由参数的情况下处理这类请求。

项目类型实际上将定义特定项目的内容应该以何种方式显示给客户端。我正在考虑创建尽可能多的控制器,以便在单个控制器操作中没有太多代码。

那么您将如何在 ASP.NET MVC 中执行此操作,或者您认为最可行的方法是什么?

编辑:更多细节

我的项目存储在数据库中。因为它们可以有非常不同的类型(不可继承),所以我想创建尽可能多的控制器。但问题出现了:

  1. 我应该如何在每个请求上创建这些控制器,因为它们与一些动态数据相关?我可以创建自己的控制器工厂或路由处理程序,或者可能还有其他一些扩展点,但哪一个最好?

  2. 我想使用 MVC 基本功能,使用 Html.ActionLink(action, controller, linkText) 之类的东西,或者制作我自己的扩展,例如 Html.ActionLink(itemType, linkText) 以使其更加灵活,因此 Action 链接应该根据 Route 数据创建正确的路由(因为那是后台发生了什么 - 它自上而下遍历路由,然后查看哪个路由返回结果 URL)。

  3. 我正在考虑配置 itemType路由值(控制器、操作、默认值)之间的关系。默认值设置可能很棘手,因为默认值应该从配置字符串反序列化为对象(这也可能很复杂)。所以我想甚至可能在 itemTypeclass type 之间有一个可配置的关系,它实现了一个特定的接口,如下例所示。

  4. 我的路线可以在数据存储中更改(或添加一些新路线)。但不应添加新类型。配置将提供这些场景,因为它们会将类型与路由默认值联系起来。

示例

接口定义:

public interface IRouteDefaults
{
    object GetRouteDefaults();
}

接口实现示例:

public class DefaultType : IRouteDefaults
{
    public object GetRouteDefaults()
    {
        return new {
            controller = "Default",
            action = "Show",
            itemComplex = new Person {
                Name = "John Doe",
                IsAdmin = true
            }
    }
}

配置示例:

<customRoutes>
    <route name="Cars" type="TypeEnum.Car" defaults="MyApp.Routing.Defaults.Car, MyApp.Routing" />
    <route name="Fruits" type="TypeEnum.Fruit" defaults="MyApp.Routing.Defaults.Fruit, MyApp.Routing" />
    <route name="Shoes" type="TypeEnum.Shoe" defaults="MyApp.Routing.Defaults.Shoe, MyApp.Routing" />
    ...
    <route name="Others" type="TypeEnum.Other" defaults="MyApp.Routing.Defaults.DefaultType, MyApp.Routing" />
</customRoutes>

为了解决性能问题,我可以缓存我的项目并使用内存中的数据,并避免在每次请求时访问数据库。这些项目往往不会经常更改。我可以在不降低应用体验的情况下将它们缓存 60 分钟。

【问题讨论】:

    标签: asp.net asp.net-mvc database routing


    【解决方案1】:

    您提到的一般概念并不少见,有几点需要考虑:

    1. 当我听说 URL 路由依赖于来自数据库的数据时,我首先想到的是性能。减轻潜在性能问题的一种方法是使用内置的 Route 类并具有非常通用的模式,例如"somethingStatic/{*everythingElse}"。这样,如果 URL 不以“somethingStatic”开头,它将立即无法匹配,并且路由将继续到下一个路由。然后,您将获得所有有趣的数据作为包罗万象的“everythingElse”参数。

    2. 1234563应该使用 action 来处理这个请求。您可以通过访问requestContext.RouteData.Values 来获取/设置路由值。
    3. 是使用一个控制器和一个动作,还是使用一个或多个中的多个,这本身就是一个讨论。问题归结为您拥有多少种不同类型的数据?它们大多相似吗(它们都是书,但有些是精装书,有些是平装书)?完全不同(有些是汽车,有些是书,有些是房子)?如果这是一个计算机编程类并且您必须从 OOP 的角度来决定它们是否都具有基类和它们自己的派生类型,或者它们是否可以很容易地表示为一种常见的类型。如果它们都是不同的类型,那么我会推荐不同的控制器 - 特别是如果每​​个控制器都需要一组不同的操作。例如,对于房屋,您可能希望查看检查报告。但是对于一本书,您可能希望预览前五页并阅读书评。这些项目没有任何共同点:一项的操作永远不会用于另一项。

    4. #3 中描述的问题也可能反过来发生:如果您有 1,000 个不同的对象类型怎么办?您想要 1,000 个不同的控制器吗?在没有更多信息的情况下,我想说对于这种情况 1000 个控制器有点太多了。

    希望这些想法能帮助您找到正确的解决方案。如果您可以提供有关您所拥有的某些特定场景的更多信息(例如这些是什么类型的对象以及可以对其应用哪些操作),那么答案也可以得到改进。

    【讨论】:

    • 好的,所以在 #2 中,您正在描述诸如在旅途中决定控制器/动作之类的东西。好的。但是你会如何使用 Html.ActionLink 呢?他们也使用路线数据。
    • Html.ActionLink 等助手的工作方式完全相同。当您使用该助手时,它将遍历路线集合中的每条路线,直到找到匹配的路线。如果您有正确的约束集和/或默认值和/或参数化段,则匹配将完全一样。当然,如果您 非常 自定义,给路由命名(调用 Add 时的可选参数)可能更有意义,然后您可以使用 Html.RouteLink() 并指定名称。这会导致路由直接跳转到一个命名路由,而不是遍历整个列表。
    【解决方案2】:

    如果您定义一个复杂的路由字典,或者只有一个通用路由条目并自己处理所有情况,则不会出现重大的性能问题。代码就是代码

    即使您的数据类型不可继承,您也很可能有共同的显示模式。例如

    • 标题和摘要文本列表
    • 项目显示,带有标题、图片、描述

    如果您可以将您的网站分解为有限数量的显示模式,那么您只需要制作这些有限的控制器和视图

    您提供一个由路由参数选择的服务层,然后使用数据传输对象 (DTO) 模式获取案例数据并将其移动到视图的标准数据结构中

    【讨论】:

    • 是的,我确实有有限数量的显示模式。我打算这样做。创建同样多的控制器来处理这些,因为这些控制器实际上处理某个导航子树。问题是我不能硬编码路线。这些导航子树确实有一个可以帮助我的 TypeId。我会定义一个将某些控制器与 TypeId 连接起来的配置。路线可以随时更改,类型不会。这可行吗?
    • 实现自己的 IRouteHandler 并创建一个 ProcessRequest 方法可能很简单,该方法通过优化的代码而不是 RouteData 字典完成所有路由/类型映射 - 请参阅weblogs.asp.net/fredriknormen/archive/2007/11/18/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 2012-10-01
    • 2023-03-31
    • 2011-10-19
    • 1970-01-01
    相关资源
    最近更新 更多