【问题标题】:Best way to handle Controller bound Role parsing处理控制器绑定角色解析的最佳方法
【发布时间】:2020-06-24 19:10:54
【问题描述】:

我有一个模式用于根据用户角色更改通用控制器的ViewResult。我经常重用这段代码,因为偶尔我需要添加ViewBag 项来处理特殊情况。

我不得不复制和粘贴代码让我很困扰,但我想不出一种有效的方法来在控制器之外创建一个不需要大量杂技(传递控制器和视图袋)的类或方法在签名等)正常运行。

有正确的方法吗?

public async Task<IActionResult> Index()
{
    if (User.Identity.IsAuthenticated)
    {
        string email = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
        Profile profile = 
            await Helper.GetProfile(HttpContext, User.FindFirstValue(ClaimTypes.NameIdentifier));
        if (profile == null)
        {
            return RedirectToAction("Index", "Profile", new { exists = false });
        }
        else
        {
            switch (profile.Role)
            {
                case Role.VendorRepresentative:
                    ViewBag.Invoices = await Invoices.Instance.GetInvoicesByVendorRepIdAsync(profile.id);
                    return View("~/Views/Home/VendorRep.cshtml", profile);
                case Role.VendorCustomerService:
                    return View("~/Views/Home/VendorService.cshtml", profile);
                case Role.VendorSalesManager:
                    ViewBag.Invoices = new List<Invoice>();
                    return View("~/Views/Home/VendorManager.cshtml", profile);
                case Role.Distributor:
                    ViewBag.Invoices = new List<Invoice>();
                    return View("~/Views/Home/Distributor.cshtml", profile);
                default:
                    return View();
            }
        }
    }
    return View();
}

【问题讨论】:

  • 您考虑过使用[Authorize] 属性吗? docs.microsoft.com/en-us/aspnet/web-api/overview/security/…
  • ^^ 如果他们不在角色中,那只会向他们显示拒绝访问页面。看起来他想根据他们的角色动态更改视图
  • 可能您想编写一个自定义 Filter,它将根据他们的角色重定向到正确的操作
  • 第一件事是保持代码 S-O-L-I-D。由于每个场景都在做同样的事情,我会用多态性替换条件语句。这将是重构代码的良好开端,并且会真正清除您可以使用的任何设计模式,因此您不必复制和粘贴。如上所述,过滤器属性可以很好地工作,但我会先清理条件语句。
  • 我将从接口和对象开始。 IHomeView 使用 '.GetView() 和 GetViewBag' 之类的方法以及 homeVendorView: IHomeView 之类的类我还将重构 httpContextHelper 注入带有一些 IOC 容器的类构造函数中,这样你就不会每节课都要传给他们。如果我有更多时间,我可以试着做点什么。

标签: c# asp.net-mvc asp.net-core roles


【解决方案1】:

当您集中一个流程时会发生这种情况。它必须包含标识每个消费者组的逻辑,并且必须包含每个消费者的处理过程。

您重用相同的模型,然后将那些特定于消费者的“附加”附加到 ViewBag 的事实仅证明该模型不能代表流程。当一个流程对每个消费者群体只有很小的变化时,模型就像一个产品系列。每个组都由一个变体表示。这些场景将鼓励您设计一个基本模型。例如,您可以将角色枚举与它们各自的索引视图以及可能修改的操作相关联。要真正代表一个产品系列,您的模型应该为您倾销的 ViewBag 项目分配空间。

但是,针对变体对核心产品进行标准化(集中化)并不能防止需求发生冲突。经理将希望模拟用户或为用户页面访问加上时间戳。一组将希望 UI 元素获取其他人无法访问的数据。产品系列模型一直工作到某个点,直到每个组的请求包含足够的处理以因集中复杂性而需要分离。

http://www.powersemantics.com/p.html

不是通过解释进行处理,这需要阅读整个代码体以确定每个组发生了什么处理,而是通过将请求转换为进程来解决问题。

将流程中的每一步都视为由消费者的索引请求表示。它们不仅由对 Index 的网页调用明确指定,而且可以更改。每个角色的索引请求实际上是它所代表的步骤的复合指令。因此,根据请求变量(Role)发出流程,最后调用序列。

VendorRepresentative
* Authenticate
* Load invoices
Index for VendorRepresentative role translates to -> Auth + LoadInvoices

VendorSalesManager
* Authenticate
* Instantiate invoices
Index for VendorSalesManager role translates to -> Auth + InstantiateInvoices

现在,如果需要添加另一个组,您的流程可以轻松扩展。此外,如果您的用户需要控制来运行某个步骤(或不需要,或为其指定值),此模型允许您将他们的参数直接映射到流程指令。

【讨论】:

    猜你喜欢
    • 2021-08-17
    • 2020-05-14
    • 2016-01-24
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 2015-03-28
    相关资源
    最近更新 更多