基于身份的查询过滤器.NET实现方法

e7arh2l6  于 2023-08-08  发布在  .NET
关注(0)|答案(2)|浏览(123)

我正在开发一个.NET WebApi应用程序,它是围绕一个干净的架构设计构建的。
在解决方案的更高层中,在WebApi项目中,控制器所在的地方,我有一个静态助手类,它有一个方法来检查当前用户是否存在于某个Active Directory组中。用户名从请求头中获取

public static bool IsUserInGroup(string userName, string userGroup)
{
    // blablabla

    return isUserInGroup;
}

字符串
在应用程序层中,我使用存储库类检索一些记录。

public List<MyObjectDto> GetValuation(int valuationId)
{
    // checkUserGroup?
    // filterExpression based on AD group

    var myObjectList = _repository.Get(filterExpression, includesProperties);

    return myObjectList;
}


我打算根据用户组过滤记录,我在想哪种方法更适合这种情况。
1.我是否应该将类更改为服务,将接口放在应用程序层,并在更高的位置实现它?
1.我应该简单地检查控制器中的用户组并向下传递结果吗?
1.我应该把helper类移到应用层吗?(我猜不像身份相关的逻辑不应该存在)
1.其他建议的办法
我是一个没有经验的软件开发人员,我会高度赞赏在这个问题上的专业意见:D
新编辑:

ruarlubt

ruarlubt1#

首先,让我展示数据层和业务逻辑层之间的细微差别。
一个需求进来了,“我需要活跃的员工”。
这是典型的代码:

interface IEmployeeDomainData
    public ICollection<Employee> GetActiveEmployees();

interface IEmployeeManagerBusinessLogic
    public ICollection<Employee> GetActiveEmployees();

字符串
以上就是我所说的“模仿”。
但模仿者是目光短浅的。
让我解释一下:
我强烈建议不要做上面的事情……而是让(域)数据层……“更可重用,本质上更通用”。
DomainDataLayer

IEmployeeDomainData

    Collection<Employee> GetActiveEmployees()  <<< NO !!!!!!!  HARD CODE BUSINESS RULE IN DOMAIN DATA LAYER.  DO NOT HARD CODE RULES IN THE DomainDataLayer.

    Better Option:

     Collection​<Employee> GetEmployeesByEmpStatus(int empStatusValue)  

    Even Better Option:

     Collection​<Employee> GetEmployeesByEmpStatuses(ICollection<int> empStatusValues)


为什么?将来你会有新的要求。

"Please provide a collection of Terminated Employees"

This is Ok for business logic layer ->             Collection<Employee> GetTerminatedEmployees()

Now, because you did NOT hard code your business logic rule in the DomainDataLayer, you can just REUSE and EXISTING DomainDataLayer method.

Below are the (now two) Business Logic Layer methods:

  Collection<Employee> GetActiveEmployees()​
  {
         return this.injectedEmpDomainDataLayer.GetEmployeesByEmpStatus​( activeEmpStatusSingleSourceOfTruthValue );
  }

     
  Collection<Employee> GetTerminatedEmployees()​
  {
         return this.injectedEmpDomainDataLayer.GetEmployeesByEmpStatus( terminatedEmpStatusSingleSourceOfTruthValue );
  }


这是两层之间一个微妙但重要的区别。他们不仅仅是彼此的“模仿者”。
....
然后,您还需要考虑“从数据存储(通常是RDBMS数据库)访问一行数据与获取单行的单列的成本是多少?”
在您的情况下,(对于您的User检查)我可能会首先在(域)数据层中获取“User”的ROW,使用
string userName,string userGroup
参数。
您不显示对象模型。用户有一个用户组还是多个用户组(1:N、M:N等)。
然后基于用户的返回,在业务逻辑层中做出关于它的决定。根据您的对象模型,您可以选择.Include(user => user.UserGroup(又名,添加导航属性)
我想说的是..从数据库中获取一个表的一行和获取一行的一列可能没有太大的区别,除非行DDL有很多列或者有一个大的列(BLOB/TEXT或类似的东西)。因此,开发人员应该考虑维护/重用与超级优化的SQL命令(EntityFramework或Dapper或您自己的自定义代码)执行。我一般都是坐一排的。
就像我的“GetTerminatedEmployees”例子一样。你有一些东西,你可以在未来重用,而不是把业务规则放在(域)数据层。
其他笔记。
您的WebApi层不是您的业务逻辑层。
这是一个“测量棒”。如果您想将业务逻辑公开为gRpc,该怎么办?还是(旧学校)周转基金?
您应该只在WebApi层中有处理WebApi的代码。主要是“收集输入参数”。推送到业务逻辑层..以Http友好的方式返回传出值。处理HTTP状态码(来自业务逻辑层的EXCEPTIONS)。
当gRPC被编码时…它应该是业务逻辑层的大量重用…具有相同的“收集输入参数”…。推送到业务逻辑层..以gRPC友好方式返回传出值。处理gRPC-Status代码(来自业务逻辑层中的EXCEPTIONS)。
虽然开发者说他们“理解业务逻辑层”的作用……但是,不让业务逻辑“滑入webapi/rest层”和“滑入(域)数据层”是一个持续的斗争。
非常重要的反模式:(使用https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/exception-throwing
您的BusinessLogic层(及其下)不应该有任何“http-status-codes,http-context”对象/值引用。
您的WebApi代码使用/codes-up http-status-codes、http-context等...但这一层“下面”的任何东西都不应该有它。我不能告诉你我遇到的使http-status-codes成为“exeptions/exception-stacktraces”(非常糟糕)替代品的代码库的数量。再次,参见:https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/exception-throwing
不要返回错误代码。
异常是报告框架中错误的主要方法。
✔️通过抛出异常来报告执行失败。
正如我经常提醒团队中的jr开发人员:
业务逻辑在哪一层?
(It这不是一个陷阱问题):它位于业务逻辑层。
但这就是问题所在它位于业务逻辑层。(不是“向上”到WebApi-Rest层,也不是“向下”到(域)数据层。
我会迅速复制我的答案的文本..因为反对票p0 lic 3可能会出现,如果我因为试图帮助某人而得到反对票,我将不得不删除我的答案。

niknxzdl

niknxzdl2#

应该有:
1.控制器
1.服务层
1.存储库层
将业务逻辑放在服务层。通过接口从控制器到服务层进行通信,也通过接口从服务层到存储库层进行通信。
抽象存在于高层次和低层次中。
这也将有助于在未来的重大变化类。
业务逻辑应该在服务层,所有的数据访问都在存储库层,这也将有助于将来的检查和处理。

相关问题