重构ViewModel映射 - 处理多个服务调用

时间:2017-05-15 17:07:53

标签: c# asp.net asp.net-mvc mvvm automapper

我需要重构和整理下面的控制器,它是我的第一个MVC应用程序。当我开始使用重构控制器时,我已经成功使用了AutoMapper,但我不确定如何处理ViewModel的数据来自多个服务调用的情况。而这种情况似乎经常出现在稍微重一些的视图模型中,在那里我可以提供各种信息。

在同一视图模型之上调用多个映射调用似乎是违反直觉的,感觉我错过了一些良好的实践或常见的方法。或许我错了,这是常用的方法。

0)一般以某种方式使用AutoMapper的想法,但正如我所说,我找不到合适的方法来实现它,我想保持控制器相对较薄,但我也不喜欢#39 ; t想要有太多不必要的/过度抽象的抽象。我知道如何映射TaskEvent属性,即使我没有。

1)考虑在视图模型上使用一些构建方法并传递所需的数据。

2)考虑在我的数据库实体和视图模型之间建立一个模型,但我不知道如何执行它,我想我通过一些例子看到人们返回"模型"来自包含复杂数据的服务调用,然后使用Automapper将这些模型映射到ViewModel,而不是像其他人一样将服务调用和域实体直接映射到ViewModel。

3)看到人们在一个示例中使用了 facade ,并考虑到了这一点。

这只是我在MVC下的第一个项目,我想 学习一个强大的通用方法,这个方法被认为是写得很好和良好的实践 所以我可以使用它完全重构并从那里继续改进。

        BKQEventCustomData BKQEventData = BKQHelper.ParseBase64EventData(Server.UrlDecode(Request.Url.Query));
        var cutomData = JsonConvert.DeserializeObject<NopOrderData>(BKQEventData.custom.data.ToString());

        var model = new TaskEventViewModel();
        if (BKQEventData != null)
        {
            AuthenticateRequest(BKQEventData.xcm.clid, BKQEventData.xcm.opid);

            model.PlacesList = new SelectList(_placesService.GetPlacesByClientId(BKQProfile.ClientId).Where(p => p.Active), "PlaceId", "Name");
            model.ServicesList = new SelectList(_serviceService.GetServicesByClientId(BKQProfile.ClientId).Where(s => s.Active), "ServiceId", "Name");
            model.ContractorsList = new SelectList(_contractorService.GetContractorsByClientId(BKQProfile.ClientId), "ContractorId", "BKQFullName");
            model.StatusList = new SelectList(_statusService.GetStatusByClientId(BKQProfile.ClientId), "StatusId", "Name");

            model.TaskEvent = new TaskEvent();
            model.TaskEvent.Title = string.Empty;
            model.TaskEvent.BKQCustomData = BKQEventData.custom.data.ToString();
            model.TaskEvent.BKQCustomDataType = BKQEventData.custom.type.ToString();
            model.TaskEvent.BKQClientId = BKQEventData.xcm.clid;
            model.TaskEvent.BKQOperatorId = BKQEventData.xcm.opid;
            model.TaskEvent.BKQInfProductId = BKQEventData.xcm.iprodid;
            model.TaskEvent.BKQEventHistoryId = BKQEventData.xcm.evnhid;
            model.TaskEvent.BKQEventTypeId = BKQEventData.xcm.evntype;
            model.TaskEvent.BKQEventCaseId = BKQEventData.xcm.caseid;
            model.TaskEvent.BKQQuota = BKQEventData.xcm.quotaid;
            model.TaskEvent.BKQLangId = BKQEventData.xcm.langid;
            model.TaskEvent.BKQContactId = BKQEventData.xcm.contid;
            model.TaskEvent.CreatedBy = BKQEventData.xcm.opid;
            model.TaskEvent.ModifiedBy = BKQEventData.xcm.opid;
            model.BKQContact = BKQFramework.Contact.GetById(BKQEventData.xcm.contid);
        }
        else
        {
            return RedirectToActionPermanent("Login", "Login");
        }

1 个答案:

答案 0 :(得分:0)

这就是我如何重构它

  1. 控制器不应该引用太多的服务,我会说 所有服务依赖关系到ApplicationService

  2. 创建ViewModel的代码应与代码一起设置 定义ViewModel。这样可以方便地同时修改ViewModel定义和属性赋值。我想你一个静态函数来创建ViewModel。

  3. 我会考虑使用AutoMapper。如果无法自动映射大多数属性,AutoMapper将不会给您带来任何好处。静态函数方法为您提供静态类型检查,并且比AutoMapper具有更好的调试体验。

    BKQEventCustomData BKQEventData = BKQHelper.ParseBase64EventData(Server.UrlDecode(Request.Url.Query));
    var cutomData = JsonConvert.DeserializeObject<NopOrderData>(BKQEventData.custom.data.ToString());
    
    if (BKQEventData != null)
    {
        AuthenticateRequest(BKQEventData.xcm.clid, BKQEventData.xcm.opid);
        var model = _applicationService.CreateMyViewModel(BKQeventData);
    }
    else
    {
        return RedirectToActionPermanent("Login", "Login");
    }
    
    pubilc class MyApplicationService : IMyApplicationService
    {
        public CreateTaskEventViewModel(BKQeventCustomData)
        {
            var model = new TaskEventViewModel();
            var services =  _placesService.GetPlacesByClientId(BKQProfile.ClientId).Where(p => p.Active);
            var contractors = _contractorService.GetContractorsByClientId(BKQProfile.ClientId);
            var statuses = _statusService.GetStatusByClientId(BKQProfile.ClientId);
    
            return TaskEventViewModel.CreateFromBKQCustomData(model, serivces, contractors, statuses);
        }   
    }
    
    public class TaskEventViewModel
    {
        public static CreateFromBKQCustomData(BKQCustomData bKQCustomData, IEnumerable<Serivce> services, ...)
        {
             var model = new TaskEventViewModel();
             model.PlacesList = new SelectList(services, "PlaceId", "Name");
             ...
    
             model.TaskEvent = TaskEvent.CreateFromBKQEventData(model);
             model.BKQContact = BKQFramework.Contact.GetById(BKQEventData.xcm.contid);
        }
    }