我需要重构和整理下面的控制器,它是我的第一个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");
}
答案 0 :(得分:0)
这就是我如何重构它
控制器不应该引用太多的服务,我会说 所有服务依赖关系到ApplicationService
创建ViewModel的代码应与代码一起设置 定义ViewModel。这样可以方便地同时修改ViewModel定义和属性赋值。我想你一个静态函数来创建ViewModel。
我会考虑使用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);
}
}