从 Web 服务 - 模型与控制器检索下拉列表数据

本文关键字:控制器 检索 下拉列表 数据 模型 Web 服务 | 更新日期: 2023-09-27 18:34:10

ASP.NET MVC 4 |C# | .NET 4.5 |剃刀

我有返回下拉列表数据的 Web 服务。此数据存储在我的模型中,然后由我的视图显示。目前,我正在控制器中进行 Web 服务调用,并在将数据传递到视图之前将数据分配给模型。

我想知道这是否是一个很好的设置,或者我是否应该在我的模型中放置我的 Web 服务调用?是否有任何关于 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从何处获取其数据以进行SomeProperty。 它只知道Widget公开了该数据。 Widget从哪里得到取决于Widget.

只要

您的控制器更精简且可测试,您可以选择任何您喜欢的方法,就很少有方法可以做到。请注意,您还希望确保视图模型简单而愚蠢。您不希望在视图模型中放置太多行为。

您的视图模型可以如此简单。我不希望在我的视图模型中有太多的行为或对服务的调用。

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

请注意,您以后可能会发现自己在想要隐蔽时重复类似的代码。您始终可以创建泛型版本,因此方法可重用。但关键是您的扩展/帮助程序方法可帮助您转换。它只进行转换,但不进行其他转换。

将您的服务注入控制器。利用您的 faviourite 双元注入框架(如果您使用任何框架(。您的控制器是可测试的。

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