Asp.net MVC RouteBase 和 IoC
我正在通过子类化 RouteBase 创建自定义路线。我在那里有一个依赖项,我想与 IoC 连接。 GetRouteData 方法只接受 HttpContext,但我也想添加到我的工作单元中......不知何故。
我正在使用 StructureMap,但是有关如何使用任何 IoC 框架执行此操作的信息将会很有帮助。
I am creating a custom route by subclassing RouteBase. I have a dependency in there that I'd like to wire up with IoC. The method GetRouteData just takes HttpContext, but I want to add in my unit of work as well....somehow.
I am using StructureMap, but info on how you would do this with any IoC framework would be helpful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,这是我们的解决方案。很多小细节可能会被省略,但总体思路就在这里。这个答案可能是原始问题的一种偏离,但它描述了问题的一般解决方案。
我将尝试解释负责用户在运行时创建的普通自定义 HTML 页面的部分,因此不能拥有自己的控制器/操作。因此,路由应该以某种方式在运行时构建,或者使用自定义 IRouteConstraint“包罗万象”。
首先,让我们陈述一些事实和要求。
所以我们这样做:
1. PageController
是的,负责我们所有内容页面的特殊控制器。唯一的操作是
Display(int id)
(实际上我们有一个特殊的 ViewModel 作为参数,但为了简单起见,我使用了int id
。页面及其所有内容数据由
Display()
方法内的 ID 解析。该方法本身返回ViewResult
(在PageViewModel
之后强类型化)或NotFoundResult。
以防找不到页面。2. 自定义 IRouteConstraint
我们必须在某处定义用户实际请求的 URL 是否引用我们的自定义页面之一。为此,我们有一个特殊的
IsPageConstraint
。实现IRouteConstraint
接口。在约束的Match()
方法中,我们只需调用PageRepository
来检查是否存在与我们请求的页面匹配的页面。 URL。如果我们找到该页面,则将“id”参数(及其值)添加到 RouteData 字典中,并且它会自动绑定到PageController.Display(int id) 通过
DefaultModelBinder
。但我们需要一个 RouteData 参数来检查。我们从哪里得到的?来了...
3. 使用“catch-all”参数的路由映射
重要提示:该路由定义在路由映射列表的最后,因为它非常通用,而不是具体的。我们首先检查所有显式定义的路由,然后检查
Page
(如果需要,可以轻松更改)。我们只是这样绘制我们的路线:
停下来!映射中出现的
DependencyRouteConstraint
东西是什么?嗯,这就是窍门。4. DependencyRouteConstraint这
只是
IRouteConstraint
的另一个通用实现,它采用 "real"IRouteConstraint
(IsPageConstraint) 并解析它(给定的TConstraint
) 仅当调用Match()
方法时。它使用依赖项注入,因此我们的IsPageConstraint
实例已注入所有实际依赖项!然后,我们的
DependencyRouteConstraint
只需调用dependentConstraint.Match()
提供所有参数,从而将实际的“匹配”委托给“真实的”IRouteConstraint。注意:这个类实际上依赖于ServiceLocator。
总结
这样我们就有了:
Route
清晰干净;IRouteConstraint
在需要时都会使用依赖注入;希望这有帮助。
Well, here is our solution. Many little details may be omitted but overall idea is here. This answer may be a kind of offtop to original question but it describes the general solution to the problem.
I'll try to explain the part that is responsible for plain custom HTML-pages that are created by users at runtime and therefore can't have their own Controller/Action. So the routes should be either somehow built at runtime or be "catch-all" with custom IRouteConstraint.
First of all, lets state some facts and requirements.
So we do it this way:
1. PageController
Yes, special controller that is responsible for all our content pages. And there is the only action that is
Display(int id)
(actually we have a special ViewModel as param but I used anint id
for simplicity.The page with all its data is resolved by ID inside that
Display()
method. The method itself returns eitherViewResult
(strongly typed afterPageViewModel
) orNotFoundResult
in case when page is not found.2. Custom IRouteConstraint
We have to somewhere define if the URL user actually requested refers to one of our custom pages. For this we have a special
IsPageConstraint
that implementsIRouteConstraint
interface. In theMatch()
method of our constraint we just call ourPageRepository
to check whether there is a page that match our requested URL. We have our PageRepository injected by StructureMap. If we find the page then we add that "id" parameter (with the value) to the RouteData dictionary and it is automatically bound toPageController.Display(int id)
byDefaultModelBinder
.But we need a RouteData parameter to check. Where we get that? Here comes...
3. Route mapping with "catch-all" parameter
Important note: this route is defined in the very end of route mappings list because it is very general, not specific. We check all our explicitly defined routes first and then check for a
Page
(that is easily changeable if needed).We simply map our route like this:
Stop! What is that
DependencyRouteConstraint
thing appeared in mapping? Well, thats what does the trick.4. DependencyRouteConstraint<TConstraint> class
This is just another generic implementation of
IRouteConstraint
which takes the "real"IRouteConstraint
(IsPageConstraint) and resolves it (the givenTConstraint
) only whenMatch()
method called. It uses dependency injection so ourIsPageConstraint
instance has all actual dependencies injected!Our
DependencyRouteConstraint
then just calls thedependentConstraint.Match()
providing all the parameters thus just delegating actual "matching" to the "real" IRouteConstraint.Note: this class actually has the dependency on ServiceLocator.
Summary
That way we have:
Route
clear and clean;DependencyRouteConstraint
;IRouteConstraint
uses dependency injection whenever needed;Hope this helps.
所以,问题是:
这就是为什么我不认为 RouteBase 类的子类是某些数据库工作依赖项的好地方。它使一切紧密耦合且不可扩展。实际上是不可能进行依赖注入的。
从现在开始(我猜有某种已经可以工作的系统),您实际上只有一个或多或少可行的选择,即:
Route
中获得对静态服务定位器本身的依赖。使用 CSL,您只需在
GetRouteData
中调用:或仅使用 StructureMap(没有 CSL 外观):
即可完成。又快又脏。关键字实际上是“脏”:)
当然,有更灵活的解决方案,但它需要一些架构更改。如果您提供有关在路由中获取的数据的更多详细信息,我可以尝试解释我们如何解决
Pages
路由问题(使用 DI 和自定义IRouteConstraint
)。So, the problem is:
And that is why I don't see the children of RouteBase class as a good place for some DB work dependency. It makes everything closely coupled and non-scalable. It is actually impossible to perform Dependency Injection.
From now (I guess there is some kind of already working system) you actually have just one more or less viable option that is:
Route
.With CSL you have to just call inside
GetRouteData
:or with just StructureMap (without CSL facade):
and you're done. Quick and dirty. And the keyword is "dirty" actually :)
Sure, there is much more flexible solution but it needs a few architectural changes. If you provide more details on exactly what data you get in your routes I can try to explain how we solved our
Pages
routing problem (using DI and customIRouteConstraint
).