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

时间:2013-10-04 23:06:07

标签: c# asp.net-mvc wcf asp.net-mvc-4 razor

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

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

我想知道这是一个好的设置,还是我应该在我的模型中放置我的Web服务调用?是否有关于Web服务调用的最佳实践指南?它们应该严格地从控制器中调用,还是无所谓?

提前致谢!

2 个答案:

答案 0 :(得分:2)

除非会对性能产生重大影响,否则理想的逻辑设置将是在模型中进行。

通常的说法是“让你的控制器保持轻盈,你的模型很重。” (我不知道谁先说了这个。)

控制器不应填充模型。它应该只获取模型的一个实例并将其提供给视图。它最多应该做一些路由逻辑(确定要发送哪个视图,或用重定向响应等),基本上,控制模型和视图/ 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变得不可变。因为它永远不会修改那些数据并且只提供它,所以没有理由为控制器可以使用该属性设置一个setter。

这里的想法是模型尽可能独立且自给自足。或者尽可能封装。它代表了商业概念本身。如果该业务概念的一部分是存在于另一个系统上的数据,则该模型将其封装起来。控制器有责任了解Widget获取SomeProperty数据的实际位置。它只知道Widget公开了那些数据。 Widget获取的位置取决于Widget

答案 1 :(得分:1)

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

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

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