ASP。基于数据存储值的MVC路由

时间:2021-05-28 11:00:12

How would you tackle this problem:

如何解决这个问题:

I have data in my data store. Each item has information about:

我的数据库里有数据。每个项目都有以下信息:

  • URL = an arbitrary number of first route segments that will be used with requests
  • URL =将用于请求的任意数量的第一个路由段
  • some item type = display will be related to this type (read on)
  • 某些项类型= display将与此类型相关(请继续阅读)
  • title = used for example in navigation around my application
  • title =用于导航应用程序
  • etc.
  • 等。

Since each item can have an arbitrary number of segments, I created a custom route, that allows me to handle these kind of requests without using the default route and having a single greedy route parameter.

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

Item type will actually define in what way should content of a particular item be displayed to the client. I was thinking of creating just as many controllers to not have too much code in a single controller action.

项目类型将实际定义如何向客户端显示特定项目的内容。我想创建同样多的控制器,使其在一个控制器动作中没有太多的代码。

So how would you do this in ASP.NET MVC or what would you suggest would be the most feasible way of doing this?

如何在ASP中实现呢。NET MVC或者你认为最可行的方法是什么?

Edit: A few more details

My items are stored in a database. Since they can have very different types (not inheritable) I thought of creating just as many controllers. But questions arise:

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

  1. How should I create these controllers on each request since they are related to some dynamic data? I could create my own Controller factory or Route handler or possibly some other extension points as well, but which one would be best?

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

  2. I want to use MVC basic functionality of using things like Html.ActionLink(action, controller, linkText) or make my own extension like Html.ActionLink(itemType, linkText) to make it even more flexible, so Action link should create correct routes based on Route data (because that's what's going on in the background - it goes through routes top down and see which one returns a resulting URL).

    我想使用MVC的基本功能,比如Html。ActionLink(动作、控制器、链接文本)或者我自己做一个扩展,比如Html。ActionLink(itemType, linkText)使其更加灵活,因此Action link应该基于路由数据创建正确的路由(因为这是后台发生的事情——它从上到下遍历路由并查看哪个路由返回结果URL)。

  3. I was thinking of having a configuration of relation between itemType and route values (controller, action, defaults). Defaults setting may be tricky since defaults should be deserialized from a configuration string into an object (that may as well be complex). So I thought of maybe even having a configurable relation between itemType and class type that implements a certain interface like written in the example below.

    我想在itemType和route值(controller, action, default)之间设置一个关系。设置默认值可能比较麻烦,因为默认值应该从配置字符串反序列化为对象(这也可能很复杂)。所以我想,甚至可以在itemType和类类型之间建立一个可配置的关系,实现一个特定的接口,如下面的例子所示。

  4. My routes can be changed (or some new ones added) in the data store. But new types should not be added. Configuration would provide these scenarios, because they would link types with route defaults.

    我的路由可以在数据存储中更改(或者添加一些新的)。但是不应该添加新的类型。配置将提供这些场景,因为它们将使用路由默认值链接类型。

Example:

例子:

Interface definition:

接口定义:

public interface IRouteDefaults
{
    object GetRouteDefaults();
}

Interface implementation example:

接口实现的例子:

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

Configuration example:

配置的例子:

<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>

To address performance hit I can cache my items and work with in-memory data and avoid accessing the database on each request. These items tend to not change too often. I could cache them for like 60 minutes without degrading application experience.

为了解决性能问题,我可以缓存我的项目并使用内存中的数据,并避免在每个请求*问数据库。这些项目往往不会经常改变。我可以将它们缓存大约60分钟,而不会降低应用程序体验。

2 个解决方案

#1


3  

There is no significant performance issue if you define a complex routing dictionary, or just have one generic routing entry and handle all the cases yourself. Code is code

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

Even if your data types are not inheritable, most likely you have common display patterns. e.g.

即使您的数据类型不是可继承的,您也很可能有常见的显示模式。如。

  • List of titles and summary text
  • 标题和摘要文本的列表
  • item display, with title, image, description
  • 项目显示,标题,图像,描述
  • etc

If you can breakdown your site into a finite number of display patterns, then you only need to make those finite controllers and views

如果您可以将您的站点分解成有限数量的显示模式,那么您只需要做出那些有限的控制器和视图。

You them provide a services layer which is selected by the routing parameter than uses a data transfer object (DTO) pattern to take the case data and move it into the standard data structure for the view

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

#2


2  

The general concept you mention is not at all uncommon and there are a few things to consider:

你提到的一般概念并不少见,有一些事情需要考虑:

  1. The moment I hear about URL routing taking a dependency on data coming from a database, the first thing I think about is performance. One way to alleviate potentialy performance concerns is to use the built in Route class and have a very generic pattern, such as "somethingStatic/{*everythingElse}". This way if the URL doesn't start with "somethingStatic" it will immediately fail to match and routing will continue to the next route. Then you'll get all the interesting data as the catch-all "everythingElse" parameter.

    当我听说URL路由依赖于来自数据库的数据时,我首先想到的是性能。缓解潜在性能问题的一种方法是使用在Route类中构建的,并且具有非常通用的模式,例如“somethingStatic/{everythingElse}”。这样,如果URL没有以“somethingStatic”开头,它将立即无法匹配,路由将继续到下一个路由。然后,您将获得所有有趣的数据作为“所有其他”参数。

  2. You can then associate this route with a custom route handler that derives from MvcRouteHandler and overrides GetHttpHandler to go to the database, make sense of the "everythingElse" value, and perhaps dynamically determine which controller and action should be used to handle this request. You can get/set the routing values by accessing requestContext.RouteData.Values.

    然后,您可以将此路由与源自MvcRouteHandler的自定义路由处理程序关联起来,并重写GetHttpHandler以进入数据库,理解“everythingElse”值,并可能动态地确定应该使用哪个控制器和操作来处理此请求。您可以通过访问requestContext.RouteData.Values获得/设置路由值。

  3. Whether to use one controller and one action or many of one or many of each is a discussion unto itself. The question boils down to how many different types of data do you have? Are they mostly similar (they're all books, but some are hardcover and some are softcover)? Completely different (some are cars, some are books, and some are houses)? The answer to this should be the same answer you'd have if this were a computer programming class and you had to decide from an OOP perspective whether they all have a base class and their own derives types, or whether they could be easily represented by one common type. If they're all different types then I'd recommend different controllers - especially if each requires a distinct set of actions. For example, for a house you might want to see an inspection report. But for a book you might want to preview the first five pages and read a book review. These items have nothing in common: The actions for one would never be used for the other.

    是使用一个控制器和一个动作,还是使用一个或多个动作,都是对自身的讨论。问题归结为你有多少不同类型的数据?它们大多相似吗(它们都是书,但有些是精装书,有些是精装书)?完全不同(有些是汽车,有些是书,有些是房子)?如果这是一个计算机编程类,你必须从OOP的角度来决定它们是否都有基类和它们自己的派生类型,或者它们是否可以用一个公共类型来表示。如果它们都是不同的类型,那么我建议使用不同的控制器——特别是如果每个控制器都需要一组不同的操作。例如,对于一栋房子,你可能想要看一份检查报告。但是对于一本书,你可能想要预览前五页并阅读书评。这些项目没有什么共同之处:一个人的行动永远不会被另一个人所使用。

  4. The problem described in #3 can also occur in reverse, though: What if you have 1,000 different object types? Do you want 1,000 different controllers? Without having any more information, I'd say for this scenario 1,000 controllers is a bit too much.

    第3条中所描述的问题也可以反过来发生:如果您有1000个不同的对象类型怎么办?你想要1000个不同的控制器吗?没有更多的信息,对于这个场景,1000个控制器有点太多了。

Hopefully these thoughts help guide you to the right solution. If you can provide more information about some of the specific scenarios you have (such as what kind of objects these are and what actions can apply to them) then the answer can be refined as well.

希望这些想法能帮助你找到正确的解决方案。如果您可以提供关于某些特定场景的更多信息(比如这些场景是什么类型的对象以及可以对它们应用什么操作),那么答案也可以得到细化。

#1


3  

There is no significant performance issue if you define a complex routing dictionary, or just have one generic routing entry and handle all the cases yourself. Code is code

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

Even if your data types are not inheritable, most likely you have common display patterns. e.g.

即使您的数据类型不是可继承的,您也很可能有常见的显示模式。如。

  • List of titles and summary text
  • 标题和摘要文本的列表
  • item display, with title, image, description
  • 项目显示,标题,图像,描述
  • etc

If you can breakdown your site into a finite number of display patterns, then you only need to make those finite controllers and views

如果您可以将您的站点分解成有限数量的显示模式,那么您只需要做出那些有限的控制器和视图。

You them provide a services layer which is selected by the routing parameter than uses a data transfer object (DTO) pattern to take the case data and move it into the standard data structure for the view

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

#2


2  

The general concept you mention is not at all uncommon and there are a few things to consider:

你提到的一般概念并不少见,有一些事情需要考虑:

  1. The moment I hear about URL routing taking a dependency on data coming from a database, the first thing I think about is performance. One way to alleviate potentialy performance concerns is to use the built in Route class and have a very generic pattern, such as "somethingStatic/{*everythingElse}". This way if the URL doesn't start with "somethingStatic" it will immediately fail to match and routing will continue to the next route. Then you'll get all the interesting data as the catch-all "everythingElse" parameter.

    当我听说URL路由依赖于来自数据库的数据时,我首先想到的是性能。缓解潜在性能问题的一种方法是使用在Route类中构建的,并且具有非常通用的模式,例如“somethingStatic/{everythingElse}”。这样,如果URL没有以“somethingStatic”开头,它将立即无法匹配,路由将继续到下一个路由。然后,您将获得所有有趣的数据作为“所有其他”参数。

  2. You can then associate this route with a custom route handler that derives from MvcRouteHandler and overrides GetHttpHandler to go to the database, make sense of the "everythingElse" value, and perhaps dynamically determine which controller and action should be used to handle this request. You can get/set the routing values by accessing requestContext.RouteData.Values.

    然后,您可以将此路由与源自MvcRouteHandler的自定义路由处理程序关联起来,并重写GetHttpHandler以进入数据库,理解“everythingElse”值,并可能动态地确定应该使用哪个控制器和操作来处理此请求。您可以通过访问requestContext.RouteData.Values获得/设置路由值。

  3. Whether to use one controller and one action or many of one or many of each is a discussion unto itself. The question boils down to how many different types of data do you have? Are they mostly similar (they're all books, but some are hardcover and some are softcover)? Completely different (some are cars, some are books, and some are houses)? The answer to this should be the same answer you'd have if this were a computer programming class and you had to decide from an OOP perspective whether they all have a base class and their own derives types, or whether they could be easily represented by one common type. If they're all different types then I'd recommend different controllers - especially if each requires a distinct set of actions. For example, for a house you might want to see an inspection report. But for a book you might want to preview the first five pages and read a book review. These items have nothing in common: The actions for one would never be used for the other.

    是使用一个控制器和一个动作,还是使用一个或多个动作,都是对自身的讨论。问题归结为你有多少不同类型的数据?它们大多相似吗(它们都是书,但有些是精装书,有些是精装书)?完全不同(有些是汽车,有些是书,有些是房子)?如果这是一个计算机编程类,你必须从OOP的角度来决定它们是否都有基类和它们自己的派生类型,或者它们是否可以用一个公共类型来表示。如果它们都是不同的类型,那么我建议使用不同的控制器——特别是如果每个控制器都需要一组不同的操作。例如,对于一栋房子,你可能想要看一份检查报告。但是对于一本书,你可能想要预览前五页并阅读书评。这些项目没有什么共同之处:一个人的行动永远不会被另一个人所使用。

  4. The problem described in #3 can also occur in reverse, though: What if you have 1,000 different object types? Do you want 1,000 different controllers? Without having any more information, I'd say for this scenario 1,000 controllers is a bit too much.

    第3条中所描述的问题也可以反过来发生:如果您有1000个不同的对象类型怎么办?你想要1000个不同的控制器吗?没有更多的信息,对于这个场景,1000个控制器有点太多了。

Hopefully these thoughts help guide you to the right solution. If you can provide more information about some of the specific scenarios you have (such as what kind of objects these are and what actions can apply to them) then the answer can be refined as well.

希望这些想法能帮助你找到正确的解决方案。如果您可以提供关于某些特定场景的更多信息(比如这些场景是什么类型的对象以及可以对它们应用什么操作),那么答案也可以得到细化。