如何使用MVC中的存储库模式创建动态的多个部分视图

rah*_*kim 5 model-view-controller model renderpartial partial-views asp.net-mvc-3

我试图有一个通用的主页,根据传递给控件的参数,将显示不同的内容(模块).

例如,用户可以从菜单中选择肯塔基州,肯塔基州的ID是1.家庭控制器获取id(1)并确定该状态的可能模块(简单的数据库调用).也许有一个公告模块和国家的联系人模块.公告模块可能有几个项目,但它只有一个模块.每种类型的模块都会有部分视图.

这是我的基本设置.

public interface IModuleRepository
{
    IList<MenuItemModule> GetMenuItemModules(int menuItem);
    IList<Announcements> GetAnnouncements(int modID);
    IList<News> GetNews(int modID);
    IList<Contacts> GetContacts(int modID);
}



//business object
public class MenuItemModule
{

    private int _MenuItemID;
    private int _ModuleID;
    private int _ModuleDefID;
    private string _Src;
    private int _ModuleOrder;

//get, set properties for these...

}

//announcements entity
public class Announcements
{
    private int _ID = -1;
    private int _MenuItemID = -1;
    private int _ModuleID = -1;
    private string _Description = string.Empty;

//get set props ...
}
Run Code Online (Sandbox Code Playgroud)

在我的家庭控制器......

public class HomeController : Controller
{


    private IModuleRepository modRepository;

    public HomeController(IModuleRepository modRepository)
    {
        this.modRepository = modRepository;
    }


    public ViewResult Item(string ItemID)
    {

        //returns a list of menuitemmodules for the page.  This gives me the Src or name of each
        //module on the page, i.e. Announcements, news, contacts, etc. 
        var modules = modRepository.GetMenuItemModules(Convert.ToInt32(ItemID)); 


        return View(modules);

   }

}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几种不同的模型来返回,但我总是遇到一些限制.如果我将menuitemmodules传递给我的Item.aspx,那么我可以这样做:

   foreach (var mod in Model)           
   {               
        Html.RenderPartial(mod.Src, a);      //needs an announcement object though    
   } 
Run Code Online (Sandbox Code Playgroud)

这使它有点动态,因为我有Src,它基本上就像"公告",我可以创建一个announcements.ascx部分来处理模块.但我发现很难通过我的menuitemmodule和一个公告实体.

我也搞乱了传递一个更复杂的对象,然后使用If语句测试每个Src.随着我增加应用程序中可能的模块数量,这将在未来使扩展变得困难.

我怎样才能解决我的问题?我希望我提供了足够的信息.我喜欢这里的基本想法 - http://www.mikesdotnetting.com/Article/105/ASP.NET-MVC-Partial-Views-and-Strongly-Typed-Custom-ViewModels但这似乎只适用于静态模块页面.

我确实尝试了一个名为ModuleViewModel的复合视图模型.这是尝试:

public class ModuleViewModel
{
    public IList<Announcements> announcements { get; set; }
    public IList<MenuItemModule> mods { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

如果我将该模型传递给Item.aspx,我可以做这样的事情(但我必须做错事,因为看起来不对劲.)

   foreach (var mod in Model)           
   {

       if (mod.announcements.Count > 0)
       {
           Html.RenderPartial("Announcements", mod.announcements);
       }


   } 
Run Code Online (Sandbox Code Playgroud)

再次,可扩展性将困扰我.我想在项目页面上有这样的东西:

   foreach (var mod in Model)           
   {

           Html.RenderPartial(mod.Src, mod);          

   } 
Run Code Online (Sandbox Code Playgroud)

这将是正确的局部视图并将其传递给正确的模型.

rah*_*kim 0

经过一个多星期的折腾,我终于弄清楚 MVC 如何动态地完成我想要的事情。我决定为其他 MVC 新手发布我的解决方案。希望以下内容能够消除我的误解(尽管就我对 MVC 的理解而言,我不能说这是最好的方法。)

为了清楚起见,我将包括之前的代码片段和修改:

 public interface IModuleRepository
 {
      IList<MenuItemModule> GetMenuItemModules(int menuItem);
      IList<Announcements> GetAnnouncements(int modID);
      IList<News> GetNews(int modID);
      IList<Contacts> GetContacts(int modID);
 }



//business object
public class MenuItemModule
{

    private int _MenuItemID;
    private int _ModuleID;
    private int _ModuleDefID;
    private string _Src;
    private int _ModuleOrder;

//get, set properties for these...

}

//announcements entity
public class Announcements  : MenuItemModule
{
    private int _ID = -1;
    private string _Description = string.Empty;

//get set props ...
}
Run Code Online (Sandbox Code Playgroud)

我还添加了另一个类:

public class AnnouncementModule : MenuItemModule
{
    private IList<Announcements> _Announcements;
    //get set prop
}
Run Code Online (Sandbox Code Playgroud)

...我为视图创建了一个模型

public class HomeItemViewModel
{
    public MenuItemModule[] MenuItemModules { get; set; } //collection of menuitemmodules
}
Run Code Online (Sandbox Code Playgroud)

在我的家庭控制器中...

    var menuItemModules = modRepository.GetMenuItemModules(ItemID);

    if (menuItemModules.Count > 0)
    {
        AnnouncementModule aMod;
        MenuItemModule[] mods = new MenuItemModule[menuItemModules.Count()];

        int i = 0;

        //loop through each MenuItemModule assign to the appropriate model
        foreach (MenuItemModule mod in menuItemModules)
        {
            if (mod.Src == "Announcements")
            {
                aMod = new AnnouncementModule();
                aMod.Announcements = modRepository.GetAnnouncements(mod.ModuleID);

                //now add this to the menuitemmodule collection
                mods[i] = aMod;
            }

            if (mod.Src == "Contacts")
            {
                //...
            }

            i++;
        }

    }


    var viewModel = new HomeItemViewModel
    {
        MenuItemModules = mods
    };

    return View(viewModel);
Run Code Online (Sandbox Code Playgroud)

然后我按照建议在视图中使用 DisplayFor 。该视图被强类型化为 HomeItemViewModel。

<%: Html.DisplayFor(m => m.MenuItemModules) %>
Run Code Online (Sandbox Code Playgroud)

这会迭代集合并根据类型调用该模板。在此示例中,它调用AnnouncementModule.ascx,它是强类型化的AnnouncementModule。

foreach (var a in Model.Announcements)
{
    //a.Description will give us the description of the announcement
}
Run Code Online (Sandbox Code Playgroud)

我意识到有更灵活的方法来编码控制器,并且我计划进行重构,但是这个框架应该提供解决我发布的问题的基础知识。