【问题标题】:ASP.Net MVC - Models and User ControlsASP.Net MVC - 模型和用户控件
【发布时间】:2011-01-19 00:25:52
【问题描述】:

我有一个带有母版页的视图。用户控件使用模型:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BudgieMoneySite.Models.SiteUserLoginModel>" %>

此用户控件显示在所有屏幕上(母版页的一部分)。如果用户已登录,它会显示一个特定的文本,如果用户未登录,它会提供一个登录框。

一切正常。

现在,我正在添加我的第一个功能屏幕。所以我创建了一个新视图……嗯,当我选择控制器方法并说“创建视图”时,我为我生成了基本视图代码。

我的控制器有这个代码:

        public ActionResult Transactions()
    {
        List<AccountTransactionDetails> trans = GetTransactions();
        return View(trans);
    }

    private List<AccountTransactionDetails> GetTransactions()
    {
        List<AccountTransactionDto> trans = Services.TransactionServices.GetTransactions();

        List<AccountTransactionDetails> reply = new List<AccountTransactionDetails>();

        foreach(var t in trans)
        {
            AccountTransactionDetails a = new AccountTransactionDetails();
            foreach (var line in a.Transactions)
            {
                AccountTransactionLine l = new AccountTransactionLine();
                l.Amount = line.Amount;
                l.SubCategory = line.SubCategory;
                l.SubCategoryId = line.SubCategoryId;
                a.Transactions.Add(l);
            }
            reply.Add(a);
        }


        return reply;
    }

所以,我的观点是这样生成的:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Collections.Generic.List<BudgieMoneySite.Models.AccountTransactionDetails>>" %>

找到 个事务。

我现在只想显示我将要显示的记录数。

当我运行它时,我得到一个错误:

“传入字典的模型项的类型为‘System.Collections.Generic.List`1[BudgieMoneySite.Models.AccountTransactionDetails]’,但此字典需要‘BudgieMoneySite.Models.SiteUserLoginModel’类型的模型项。 "

看起来用户控件首先被渲染,并且控制器中的模型是我的列表,它正在破坏!

我做错了什么?

【问题讨论】:

    标签: c# asp.net-mvc master-pages


    【解决方案1】:

    LoginModel 不应设置为页面的模型,而只能用于部分视图。您可以使用 RenderAction 显示带有未连接到页面模型的模型的局部视图。以下是我如何实现出现在母版页上的登录状态控件。

    部分视图(Views/Auth/LoginStatus.ascx):

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IUserProfile>" %>
    
    <%    if (Request.IsAuthenticated && Model != null) { %>
        Welcome <b><%= Model.DisplayName %></b>!
        [ <%= Html.ActionLink("Log Off", "LogOff", "Auth") %> ]
    <%
    }
    else {
    %> 
        [ <%= Html.ActionLink("Log On", "Login", "Auth") %> ]
    <%
    } 
    %>
    

    在没有强类型模型的母版页中:

    <% Html.RenderAction("LoginStatus", "Auth"); %>
    

    并在控制器中(AuthController)

        public ActionResult LoginStatus()
        {
            TProfile p = null;
            if (User.Identity.IsAuthenticated)
            {
                p = Data.Profiles.Get(ulong.Parse(User.Identity.Name));
            }
            return View(p);
        }
    

    【讨论】:

    • 谢谢汤姆!这工作......不知何故。我不知道怎么做,所以我现在试着分析一下……但是谢谢!
    【解决方案2】:

    它本身并不是“首先”呈现的,而是所有视图都采用控制器传递的模型,除非另有说明。

    要解决这个问题,您可以创建一个所有视图模型都将从中继承的基类,定义 Master 及其部分视图所需的内容(然后将适当的属性传递给 RenderPartial 重载之一) , 或者你可以使用无类型的 ViewData 包来做类似的事情。

    * 编辑 * 所以我意识到我是按要求回答你的问题,而不是我本来会解决的问题。上面的回答是正确的,如果您想在母版页中处理模型内容,您需要将它们填充到 ViewData 字典中(例如 ViewData["myData"] = mydata;)或者您必须为您的所有内容创建一个基类要继承的模型。

    也就是说,在大多数情况下(尤其是像您作为示例提供的 profiel 之类的东西)我也不这样做。在大多数情况下,我使用渲染操作来代替,它需要来自另一个控制器的局部视图。然后,其他控制器可以向其部分提供适当的任何数据。有些人认为这违反了 MVC,我认为这是一种组合视图并实际上保持逻辑结构完整的好方法,而不是通过要求控制器知道母版页需要什么来混淆水域,即使它无事可做 w /那个控制器的工作。通常的解决方案是也有一个基本控制器,或者使用动作过滤器,但我发现你必须保持更多的臃肿。

    【讨论】:

    • 感谢 Paul - 作为一个新手,我不确定哪种方法更好。另外,您能否提供一个非常基本的示例?我们是否要将模型传递给视图?
    • 不同的人有不同的喜好;事实上,在 MVC 3 中,您甚至可以使用动态作为绕过它的一种方式。作为新手,您应该尝试从阅读 Sanderson 的 APress 的 MVC 书籍开始,它是最好的。我将在上面用其他一些想法进行编辑
    猜你喜欢
    • 2010-09-06
    • 2010-11-28
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2014-06-09
    • 1970-01-01
    相关资源
    最近更新 更多