【问题标题】:MVC3 – ViewModels and controller functionalty: suggested design patternsMVC3 – ViewModels 和控制器功能:建议的设计模式
【发布时间】:2011-05-08 14:52:13
【问题描述】:

我已经为一个不太可用的呼叫中心应用程序构建了一个简单的基于 MVC3 的工单入口网站,并且正在尝试重构我的原型以更好地遵循设计模式,部分是为了使其更易于维护,但主要是作为一种学习锻炼。 面向用户的视图是一种由基本用户信息和一些允许选择各种资源类型的面板组成的表单。每种资源类型(硬件、软件等)都以相同的方式显示:使用带有添加/删除按钮的双重可过滤列表框,如果请求的资源需要对齐,则有条件地显示可选的“对齐”文本区域,以及通用 cmets。 我为各个面板构建了以下 ViewModel:

public class RequestableList
{
    // list of requestable items ids requiring justification
    private List<string> _restrictedItems = new List<string>();
    public List<string> RestrictedItems
    {
        get { return _restrictedItems; }
        set { _restrictedItems = value; }
    }

    // the key-value pairs from which to populate available items list
    private Dictionary<string, string> _availableItems = new Dictionary<string, string>();
    public Dictionary<string, string> AvailableItems
    {
        get { return _availableItems; }
        set { _availableItems = value; }
    }

    // item ids requested by user
    private List<string> _requestedItems = new List<string>();
    public List<string> RequestedItems
    {
        get { return _requestedItems; }
        set { _requestedItems = value; }
    }
}

主 ViewModel 然后根据需要由多个 RequestableLists 组成:

public class SimpleRequestViewModel
{
    public UserInfo userInfo { get; set; }
    public RequestableList Software {get;set;}
    public RequestableList Hardware {get;set;}
    public RequestableList Access {get;set;}
    public string SoftwareAdditionalInfo { get; set; }
    public string HardwareAdditionalInfo { get; set; }
    public string AccessFileMailShare { get; set; }
    public string AccessAdditionalInfo { get; set; }
    public string SoftwareJustification { get; set; }
    public string HardwareJustification { get; set; }
    public string AccessJustification { get; set; }
    public string Comment { get; set; }
}

我为 SimpleRequestViewModel(及其变体)创建了一个强类型视图,并为 RequestableList 创建了一个强类型 EditorTemplate,用于连接双列表框、过滤和 jquery。所有渲染都很好并且正在运行,但代码目前有异味。

发布到控制器时,如果模型有效,我必须将其翻译成可读的文本描述,以便在呼叫中心应用程序中创建新工单。让控制器执行翻译成可读文本感觉不对,但我在尝试设计另一个类来翻译视图模型时遇到了障碍。

  1. 仅发布选定的项目值,因此在将请求转换为文本之前,我必须首先查找所提供值的适当文本(它们在描述中是必需的)。控制器是当前唯一有权访问此查找查询的呼叫中心数据模型的对象。
  2. 有 2 个相似的 ViewModel 包含不同的 RequestableList 组合,因此任何翻译器都必须能够翻译各种组合。一个只有硬件和软件,另一个可能有硬件软件,还有几个 RequestableList。

我考虑直接在 ViewModel 中覆盖 ToString(),但不喜欢那里的业务逻辑(条件渲染),而且,一旦发布,ViewModel 不包含列表框中所选项目的文本,所以它需要访问数据模型。 将发布的值转换为文本,因为它当前在控制器中处理,因为它在 switch 语句中处理。控制器获取每个发布的 RequestableList 并在构建新的工单描述之前填充原始的“可用”字段。

switch (requestCategory)
{
    case RequestableCategory.Software:
        itemList = sde.GetSoftware();
        break;
    case RequestableCategory.Hardware:
        itemList = sde.GetHardware();
        break;
    case RequestableCategory.Access:
        itemList = sde.GetAccess();
        break;
    case RequestableCategory.Telecom:
        itemList = sde.GetTelecom();
        break;
    default:
        throw new ArgumentException();
}

所以,我的问题:

  1. 您推荐哪些模式用于执行已发布的视图模型到工单描述的翻译?
  2. 当您需要文本和值时,通常如何处理选择框的“仅发布值”问题?
  3. 有没有更好的方法来解决这个问题?

再次,我希望这对我来说是一次学习经历,并且如果需要,我非常愿意提供额外的信息或描述。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 design-patterns asp.net-mvc-controller


    【解决方案1】:

    一些建议:

    1. 将呼叫中心提交的逻辑抽象到它自己的类中。提供(从控制器)访问呼叫中心数据库所需的任何依赖项。使用重载有不同的方法来处理各种类型的视图模型。大概描述来自数据库,因此您可以根据此类中的值从数据库中提取描述。此类还可以负责为显示操作构建视图模型。请注意,使用这种模式,类可以直接、通过存储库甚至通过 Web 服务/API 与 DB 交互。

    2. 如果在第二次从数据库中查找描述时出现性能问题,请使用实现一些缓存的存储库模式。我怀疑除非您的呼叫中心非常大,否则不会,但这将是优化查询逻辑的地方。存储库可以是控制器传递给提交类的东西。

    3. 如果不需要在控制器中直接访问数据库,可以考虑直接将代理类作为依赖传递。

    它可能看起来像:

    private ICallCenterBroker CallCenterBroker { get; set; }
    
    public RequestController( ICallCenterBroker broker )
    {
       this.CallCenterBroker = broker;
       // if not using DI, instantiate a new one
       // this.CallCenterBroker = broker ?? new CallCenterBroker( new CallCenterRepository() );
    }
    
    [HttpGet]
    public ActionResult CreateSimple()
    {
        var model = this.CallCenterBroker.CreateSimpleModel( this.User.Identity.Name );
        return View( model );
    }
    
    
    [HttpPost]
    public ActionResult CreateSimple( SimpleRequestViewModel request )
    {
        if (Model.IsValid)
        {
           var ticket = this.CallCenterBroker.CreateTicket( request );
           // do something with ticket, perhaps create a different model for display?
           this.CallCenterBroker.SubmitTicket( ticket );
           return RedirectToAction( "index" ); // list all requests?
        }
        return View();
    }
    

    【讨论】:

    • 完美。出于某种原因,我不喜欢在控制器和视图之外的任何地方使用 ViewModel。现在经纪人已经到位,圈复杂度已大大降低。感谢您的回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 2012-07-05
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多