Asp.net mvc 如何使用IoC、DI和MVC在视图模型上连接列表/集合?

Asp.net mvc 如何使用IoC、DI和MVC在视图模型上连接列表/集合?,asp.net-mvc,dependency-injection,inversion-of-control,Asp.net Mvc,Dependency Injection,Inversion Of Control,我正在与一个MVC项目合作,试图实现IoC和DI。这两个问题对我来说都是新鲜事,所以如果我完全走错了路,或者我的问题没有说清楚,我会提前道歉 假设我有一个视图需要显示一个地址表单,其中一个元素是一个状态下拉列表。(我意识到不太可能在其他内容的上下文之外使用地址,但为了简单起见,假设这里就是这种情况。) 假设这是我的视图模型: public class AddressList { public string Address1 { get; set; } public string

我正在与一个MVC项目合作,试图实现IoC和DI。这两个问题对我来说都是新鲜事,所以如果我完全走错了路,或者我的问题没有说清楚,我会提前道歉

假设我有一个视图需要显示一个地址表单,其中一个元素是一个状态下拉列表。(我意识到不太可能在其他内容的上下文之外使用地址,但为了简单起见,假设这里就是这种情况。)

假设这是我的视图模型:

public class AddressList {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public List<string> States { get; set; }
    public string Zip { get; set; }
}
公共类地址列表{
公共字符串地址1{get;set;}
公共字符串地址2{get;set;}
公共字符串City{get;set;}
公共列表状态{get;set;}
公共字符串Zip{get;set;}
}
谁有责任填写州名单

控制器是否应该这样做,因为它已经被注入了一个服务来获取状态?如果是这样的话,我需要填充地址的每个控制器中是否都有相同的注入和填充逻辑?还是应该去别的地方

此视图模型属于哪一层?如果此视图模型非常特定于我的应用程序中的给定视图,那么它不应该也保留在我的应用程序中,因此不用于传递到用于填充状态的服务中吗

我已经搜索了几个小时,试图找到一个这样做的好例子,但我发现几乎没有什么帮助。所以我想知道这是否是一个错误的方法开始。如果是这样的话,我当然愿意采取不同的做法

我目前正在使用ASP.NETMVC2、Unity和EF4,因此任何使用这些的示例都将非常好。然而,任何例子都可能引导我朝着正确的方向前进

提前谢谢

编辑:抱歉,但我想我可能刚刚偶然发现了我想要的东西——模型绑定:


这是我需要的吗?这对Unity有效吗(我看到这里的示例使用了Castle Windsor)?

您需要的,不必像您的解释那样复杂。首先,在您的模型中,您不必放置状态列表。所以在你的模型中,你应该

public String State { get; set; }
然后在您的视图中——假设您有一个地址列表的强类型视图,那么您有以下状态

<div class="editor-label">
    <%: Html.Label("State") %>
    </div>
        <div class="editor-field">
            <%= Html.DropDownList(
                "State",          
                 new SelectList(Html.StateDropDownList(HttpContext.Current), "State",  
                 "State",  Model.State != null ? Model.State : null), 
                 new { id = "State", width = "80px" })
            %>
         </div>
     <div>
<div>

注意我的扩展方法StateDropDownList,它可以实现如下:;这就是Ioc/DI的作用所在:

public static IEnumerable<State> StateDropDownList(this HtmlHelper htmlHelper, HttpContextBase current)
{
    var stateList = current.Application.Get(Constants.General.StateNames) as IEnumerable<State>;

    if (stateList == null)
    {
        var stateService = ((IIocContainer)current.Application["container"]).Resolve<IStateService>();
        stateList = stateService.GetStates();
        current.Application.Set(Constants.General.StateNames, stateList);
    }

    return stateList;
}
公共静态IEnumerable StateDropDownList(此HtmlHelper HtmlHelper,HttpContextBase当前)
{
var stateList=current.Application.Get(Constants.General.StateNames)作为IEnumerable;
if(stateList==null)
{
var stateService=((IIocContainer)current.Application[“container”]).Resolve();
stateList=stateService.GetStates();
current.Application.Set(Constants.General.StateNames、stateList);
}
返回状态列表;
}
注:IIocContainer可替换为使用中的Ioc的混凝土类型或接口类型。此外,我没有使用StateID,因为您在AddressList模型中实际使用了状态值(字符串),但是,我相信使用StateID会更好,下拉列表将更改为:

<div class="editor-label">
    <%: Html.Label("State Name") %>
    </div>
        <div class="editor-field">
            <%= Html.DropDownList(
                "StateID",          
                 new SelectList(Html.StateDropDownList(HttpContext.Current), "StateID",  
                 "State",  Model.StateID != null ? Model.StateID : null), 
                 new { id = "StateID", width = "80px" })
            %>
         </div>
     <div>
<div>

我相信你们大多数的疑问都已经得到了上述答案,但如果没有,现在让我来回答以下问题:

“谁负责填充州列表? 控制器是否应该这样做,因为它已经被注入了一个服务来获取状态?如果是的话,这个注入和填充逻辑是否会在我需要填充地址的每个控制器中进行?还是应该去其他地方?


--理想情况下,您的数据存储中将此列表作为参考数据的一部分。因此,每次需要列表时,都可以使用StateDropDownList扩展方法来检索它,然后像我上面提到的那样绑定到下拉列表。由于列表可以在许多地方使用,因此您不需要将检索放在特定的控制器中。

与其他应用程序边界数据结构一样,ViewModels最好建模为具有一些行为的数据结构。控制器的职责是加载数据并填充ViewModels

因此,您应该将必要的服务注入控制器,并使用这些服务填充ViewModel

谁的责任是填充 州名单

通常是控制器

控制器应该这样做吗 为它注入了一个服务 去美国?如果是,这是否正确 相同的注入和总体逻辑 我的每个控制器都需要 填充地址?还是应该走 其他地方

是的,控制器


在构造函数中注入服务。是的,每个需要这个的控制器。如果你发现有很多,你应该考虑使用一个带有PIDALVIEW/P>的单一状态控制器,这与DI/IOC无关。这是服务位置,与DI相反。现在,您已经将服务类的耦合替换为容器(服务定位器)的耦合。是的,你是对的,我想补充一点,它与DI/IoC没有任何关系,但我的回答是这样的,因为我相信在大多数情况下,MVC正在成为标准,我相信用户仍然在使用它。谢谢,马克。听起来你觉得这个加载/填充应该在控制器内部完成?如果是的话,你是否不同意上面链接的文章所采用的方法?我倾向于走这条路线,但听起来你(到目前为止,还有另外两个)觉得这个逻辑最好留给控制器,即使这意味着在需要执行相同绑定的多个控制器之间复制相同的逻辑?是的,我已经尝试了所有的方法