ASP.NET MVC 4 | C# | .NET 4.5 | 剃刀
我有返回下拉列表数据的网络服务。这些数据存储在我的模型中,然后由我的视图显示。目前,我正在控制器中进行 Web 服务调用,并将数据分配给模型,然后再将其传递给视图。
我想知道这是否是一个好的设置,或者我是否应该将我的网络服务调用放在我的模型中?是否有关于 Web 服务调用的最佳实践指南?是否应该从控制器严格调用它们,还是无关紧要?
提前致谢!
ASP.NET MVC 4 | C# | .NET 4.5 | 剃刀
我有返回下拉列表数据的网络服务。这些数据存储在我的模型中,然后由我的视图显示。目前,我正在控制器中进行 Web 服务调用,并将数据分配给模型,然后再将其传递给视图。
我想知道这是否是一个好的设置,或者我是否应该将我的网络服务调用放在我的模型中?是否有关于 Web 服务调用的最佳实践指南?是否应该从控制器严格调用它们,还是无关紧要?
提前致谢!
除非对性能产生重大影响,否则理想的逻辑设置是在模型中进行。
通常的引用是,“保持你的控制器轻而你的模型重”。(不知道是谁先说的。)
控制器不应填充模型。它应该只获取模型的一个实例并将其提供给视图。最多它应该做一些路由逻辑(确定发送哪个视图,或者用重定向响应等),基本上,控制模型和视图/UI之间的交互。
所以不是这样的:
public ActionResult Index()
{
var model = WidgetFactory.Create();
model.SomeProperty = DataService.GetPropertyInfo();
return View(model);
}
你应该这样做:
public ActionResult Index()
{
var model = WidgetFactory.Create();
return View(model);
}
在模型上有这个:
public SomeType SomeProperty
{
get
{
return DataService.GetPropertyInfo();
}
}
或者这个,如果在获取数据时有开销:
private SomeType _someProperty = null;
public SomeType SomeProperty
{
get
{
if (_someProperty == null)
_someProperty = DataService.GetPropertyInfo();
return _someProperty;
}
}
就模型而言,这具有SomeProperty
不可变的额外好处。由于它从不修改该数据并且只提供它,因此没有理由为控制器可以使用的该属性设置一个设置器。
这里的想法是模型尽可能自包含和自给自足。或者尽可能封装。它本身就代表了业务概念。如果该业务概念的一部分是存在于另一个系统上的数据,则模型会封装它。Widget
实际了解 a获取数据的位置不是控制器的责任SomeProperty
。它只知道 aWidget
公开了该数据。在哪里Widget
得到它取决于Widget
。
只要您的 Controller 更精简且可测试,您可以选择任何您喜欢的方法。请注意,您还想确保您的视图模型简单而愚蠢。您不想在视图模型中放置太多行为。
您的视图模型可以像这样简单。我宁愿在我的视图模型中没有太多的行为或对服务的调用。
public class MyViewModel
{
public IEnumerable<SelectListItem> CustomerList { get; set; }
}
我会创建一个简单的扩展方法或帮助类,将我的域数据转换为 DropDownList 视图模型,即 SelectListItem
internal static class ListHelper
{
internal static MyViewModel ConvertToMyViewModel(this IEnumerable<Customer> customers)
{
//Assign customers to CustomerList;
//MyViewModel.CustomerList
return new MyViewModel();
}
}
请注意,您以后可能会发现自己在想要隐蔽时重复类似的代码。您始终可以创建通用版本,因此方法是可重用的。但关键是您的扩展/辅助方法可以帮助您进行转换。它只做转换,但没有别的。
将您的服务注入控制器。如果您使用任何一种,请利用您最喜欢的二元注入框架。您的控制器是可测试的。
public class HomeController : Controller
{
private readonly IWebService _webServiceInfo;
public HomeController(IWebService webServiceInfo) {
_webServiceInfo = webServiceInfo;
}
public ActionResult Index() {
var customers = _webServiceInfo.GetCustomers();
var viewModel = customers.ConvertToMyViewModel();
return View(viewModel);
}
}