MVC3 - ViewModels和控制器功能:建议的设计模式

时间:2011-05-08 14:52:13

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

我为一个不太实用的呼叫中心应用程序构建了一个简单的基于MVC3的票证入口站点,并试图重构我的原型以更好地遵循设计模式,部分原因是为了使其更易于维护,但主要是作为一种学习行使。 除了允许选择各种资源类型的几个面板之外,面向用户的视图是由基本用户信息组成的表单。每种资源类型(硬件,软件等)都以相同的方式显示:使用带有添加/删除按钮的双重可过滤列表框,可选的“对齐”文本区域,有条件地显示所请求的资源是否需要对齐,以及一般注释。 我为各个面板构建了以下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. 有两个类似的ViewModel包含RequestableLists的不同组合,因此任何翻译者都必须能够翻译各种组合。一个只有硬件和软件,另一个可能有硬件软件,还有一些可请求列表。
  3. 我考虑直接在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. 我有更好的方法来解决这个问题吗?
    4. 同样,我希望这对我来说是一次学习经历,并且非常愿意在需要时提供额外的信息或描述。

1 个答案:

答案 0 :(得分:1)

一些建议:

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

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

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

  4. 看起来像是:

    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();
    }