TLDR;我个人只会在操作中保留访问检查。您可以随时尝试使用其他函数和 lambda 对其进行泛化,例如:
return IfAccessIsGood("CompanyA","anotherparam",()=>{ /* do something */ });
但这是我最初为您整理的完整回复:
听起来您的参数在控制器操作内部发生了变化,这些参数指定了哪个公司,并且您根据公司执行访问检查,例如:
[AuthorizeCustom]
[Route("{company}/{something}")]
[HttpPost]
public async Task<IHttpActionResult> DoSomething(string company, string something) {
if(company == "A" && something == "NOTA")
{
return BadRequest("Your company can't do that!!!");
}
else if(company == "B" && something == "NOTB")
{
return BadRequest("Your company can't do that!!!");
}
else {} // do the thing
}
显然,您的实现可能看起来更加优雅,但我认为它在幕后做了类似的事情。
如果必须从根本上区别对待公司访问,您可以创建一个继承自 ApiController 的基类,并将该基类实现为 CompanyA 和 CompanyB 实现作为您的控制器,这将使它们完全分开。然后,您可以覆盖一个 Access 函数来检查访问,并为您公开的 api 实现每个方法。您的路线将不再是可变的,而是:
[Route("CompanyA/{something}")]
[Route("CompanyB/{something}")]
这些都将驻留在从 Base 继承的自己的类中,因此允许您进行所需的任何控制,而实际上不必复制大量代码。
这确实很棘手,因为属性不能被继承(至少不能通过通常的方式),但你可以这样做:
[AuthorizeCustom]
[RoutePrefix("CompanyA")]
public class CompanyA : BaseClass
{
[Route("{something}")]
[HttpPost]
override async Task<IHttpActionResult> DoSomething(string something) { return await base.DoSomething(something); }
override bool CheckAccess(string something) {
if(something != "A") return false;
else return true;
}
}
您可以通过标准化访问权限并简单地覆盖一个属性以获取公司价值而不是在每个公司实现中覆盖访问权限来使这更加优雅,这仍然不是一个很好的解决方案,除非您可以通过以下方式找到一些其他好处覆盖集中式功能。
老实说,我可能只是停留在控制器操作本身的逻辑上。如果您想轻松进行单元测试,请将动作逻辑的核心放在其他地方,并在动作中简单地返回其值,这样您就可以在单独的函数/类中对 99% 的逻辑进行单元测试。