ASP.NET MVC 中的基本控制器类有哪些好的候选者?
我见过很多人谈论在他们的 ASP.NET MVC 项目中使用基本控制器。我见过的典型示例是针对日志记录或 CRUD 脚手架执行此操作。基本控制器类还有哪些其他好的用途?
I've seen a lot of people talk about using base controllers in their ASP.NET MVC projects. The typical examples I've seen do this for logging or maybe CRUD scaffolding. What are some other good uses of a base controller class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
基本控制器类没有什么好的用途。
现在听我说完。
Asp.Net MVC,尤其是 MVC 3 具有大量的可扩展性挂钩,它们提供了一种更加解耦的方式来向所有控制器添加功能。由于控制器类非常重要并且是应用程序的核心,因此保持它们轻量、敏捷并与其他所有内容松散耦合非常重要。
日志基础设施属于
构造函数并应该被注入
通过 DI 框架。
CRUD 脚手架应由
代码生成或自定义
ModelMetadata 提供者。
全局异常处理应该是
由自定义 ActionInvoker 处理。
全局查看数据和授权
应该由动作过滤器处理。
使用全局操作过滤器变得更加容易
在MVC3中。
常量可以放入另一个名为 ApplicationConstants 或其他内容的类/文件中。
基本控制器通常由缺乏经验的 MVC 开发人员使用,他们不了解 MVC 的所有不同可扩展性部分。现在请不要误会我的意思,我不会评判并与出于所有错误原因使用它们的人一起工作。它只是为您提供更多工具来解决常见问题的经验。
我几乎可以肯定,除了基本控制器类之外,没有任何问题无法使用其他可扩展性挂钩来解决。不要采用最紧密的耦合形式(继承),除非有重大的生产力原因并且您不违反 Liskov。我更愿意采用 < 1 秒在我的控制器中输入属性 20 次,例如 public ILogger Logger { get;放; } 而不是引入紧密耦合,这会以更重要的方式影响应用程序。
甚至像 userId 或多租户密钥这样的东西也可以放入 ControllerFactory 而不是基本控制器中。基本控制器类的耦合成本是不值得的。
There are no good uses of a base controller class.
Now hear me out.
Asp.Net MVC, especially MVC 3 has tons of extensibility hooks that provide a more decoupled way to add functionality to all controllers. Since your controllers classes are very important and central to an application its really important to keep them light, agile and loosely coupled to everything else.
Logging infrastructure belongs in a
constructor and should be injected
via a DI framework.
CRUD scaffolding should be handled by
code generation or a custom
ModelMetadata provider.
Global exception handling should be
handled by an custom ActionInvoker.
Global view data and authorization
should be handled by action filters.
Even easier with Global action filters
in MVC3.
Constants can go in another class/file called ApplicationConstants or something.
Base Controllers are usually used by inexperienced MVC devs who don't know all the different extensibility pieces of MVC. Now don't get me wrong, I'm not judging and work with people who use them for all the wrong reasons. Its just experience that provides you with more tools to solve common problems.
I'm almost positive there isn't a single problem you can't solve with another extensibility hook than a base controller class. Don't take on the the tightest form of coupling ( inheritance ) unless there is a significant productivity reason and you don't violate Liskov. I'd much rather take the < 1 second to type out a property 20 times across my controllers like
public ILogger Logger { get; set; }
than introduce a tight coupling which affects the application in much more significant ways.Even something like a userId or a multitenant key can go in a ControllerFactory instead of a base controller. The coupling cost of a base controller class is just not worth it.
我喜欢使用基本控制器进行授权。
我没有用“授权”属性来装饰每个操作,而是在基本控制器中进行授权。授权操作列表是从登录用户的数据库中获取的。
请阅读下面的链接以获取有关授权的更多信息。
进行通用授权的良好实践在自定义控制器工厂中?
I like to use base controller for the authorization.
Instead of decorating each action with "Authorize" attribute, I do authorization in the base controller. Authorized actions list is fetched from database for the logged in user.
please read below link for more information about authorization.
Good practice to do common authorization in a custom controller factory?
我用它来访问会话、应用程序数据等。
我还有一个应用程序对象,它保存应用程序名称等内容,我从基类访问它
本质上我将它用于我经常重复的事情
哦,我应该提到我不要将其用于业务逻辑或数据库访问。我想对于基类来说,常量也是一个很好的选择。
I use it for accessing the session, application data etc.
I also have an application object which holds things like the app name etc and i access that from the base class
Essentially i use it for things i repeat a lot
Oh, i should mention i don't use it for buisiness logic or database access. Constants are a pretty good bet for a base class too i guess.
我在许多项目中使用了基本控制器并且工作得非常好。我主要用于
I have used base controller in many of my projects and worked fantastic. I mostly used for
根据我的经验,您想要放入基本控制器中的大部分逻辑理想情况下都应该放入操作过滤器中。动作过滤器只能用常量初始化,所以在某些情况下你不能这样做。在某些情况下,您需要将操作应用于系统中的每个操作方法,在这种情况下,将逻辑放在基础中可能比使用新的 actionFilter 属性注释每个操作方法更有意义。
我还发现将引用服务的属性(否则与控制器分离)放入基础中很有帮助,使它们易于一致地访问和初始化。
From my experience most of the logic you'd want to put in a base controller would ideally go into an action filter. Action Filter's can only be initialized with constants, so in some cases you just can't do that. In some cases you need the action to apply to every action method in the system, in which case it may just make more sense to put your logic in a base as opposed to annotating every action method with a new actionFilter attribute.
I've also found it helpful to put properties referencing services (which are otherwise decoupled from the controller) into the base, making them easy to access and initialized consistently.
我所做的是使用通用控制器基类来处理:
BaseCRUDController
,它需要一个ICRUDService
对象作为构造函数参数,因此基类类将处理创建 / 编辑 / 删除。并且确保在虚拟模式下处理自定义情况ICRUDService
具有诸如保存 / 更新 / 删除 / Find / ResetChache /... 我为我创建的每个存储库实现了它,这样我就可以向它添加更多功能。Error / Notification 消息处理:布局中带有
@TempData["MHError"]
代码和属性的部分在基本控制器中,例如公共通知错误
{
设置 { TempData["MHError"] = 值; }
获取{返回(通知)TempData.Peek(“MHError”); }
}
,我可以轻松处理每次必须编写或使用代码生成器创建的方法。
但这种方法也有其弱点。
What i did was to use a generic controller base class to handle:
BaseCRUDController<Key,Model>
which required aICRUDService<TModel>
object as constructor parameter so the base class will handle Create / Edit / Delete. and sure in virtual mode to handle in custom situationsICRUDService<TModel>
has methods like Save / Update / Delete / Find / ResetChache /... and i implement it for each repository I create so i can add more functionality to it.Error / Notification messages handling: a part in Layout with
@TempData["MHError"]
code and a Property in base Controller likepublic Notification Error
{
set { TempData["MHError"] = value; }
get { return (Notification) TempData.Peek("MHError"); }
}
With this Abstract classes i could easily handle methods i had to write each time or create with Code Generator.
But this approach has it's weakness too.
我们使用 BaseController 来做两件事:
We use the BaseController for two things:
我现在使用基本控制器使用 i18N 库进行国际化。它提供了一种方法,我可以使用它来本地化控制器中的任何字符串。
I'm using a base controller now for internationalization using the i18N library. It provides a method I can use to localize any strings within the controller.
Filter不是线程安全的,在数据库访问和依赖注入的情况下,使用它时数据库连接可能会被其他线程关闭。
Filter is not thread safe, the condition of database accessing and dependency injection, database connections might be closed by other thread when using it.
我们使用基本控制器:
.User
属性,因为我们使用自己的 User 对象,该对象应该具有我们自己的自定义属性。OnActionExecuted
逻辑并添加一些全局操作过滤器We used base controller:
.User
property because we use our own User object that should have our own custom properties.OnActionExecuted
logic and add some global action-filters