【问题标题】:How can i make data available in my MVC _Layout view如何使数据在我的 MVC _Layout 视图中可用
【发布时间】:2016-03-02 12:00:37
【问题描述】:

我的_Layout 使用 BaseViewModel 在导航栏中呈现用户名,我希望在应用程序中保持一致。我的 HomeController 有一个名为 Login 的操作,它在成功登录后将 UserViewModel 传递给 Dashboard 视图。 UserViewModel 派生自 BaseViewModel,目前仅在仪表板视图中使用。

我的问题是如何使 _Layout 页面使用的 BaseViewModel 在整个应用程序视图中可用。每次页面加载时,我是否必须继续调用我的服务(数据库)来获取这些数据?因为 BaseViewModel 需要的数据仅在 HomeControllerLogin 操作中获取,所以如果我导航到另一个视图,页面会中断,我会在下面收到此错误

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[InventoryManager.Web.Models.ProductViewModel]', but this dictionary requires a model item of type 'InventoryManager.Web.Models.BaseViewModel'.

BaseViewModel.cs

public class BaseViewModel
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

用户视图模型

public class UserViewModel : BaseViewModel
{
    public Guid UserId { get; set; }

    public string Username { get; set; }

    public string Password { get; set; }
}

基础控制器

public class BaseController : Controller
{
    //
    // GET: /Base/

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;
    }
}

HomeController

    public ActionResult Login(LoginViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return ReturnLoginViewOnError(CustomErrorMessages.LOGIN_CREDENTIALS_NOT_PROVIDED);
        }

        var userService = new UserServiceClient();
        var user = userService.GetUser(model.Username, model.Password);

        if (null == user)
        {
            return ReturnLoginViewOnError(CustomErrorMessages.INVALID_USER);
        }

        var userViewModel = Mapper.Map<UserContract, UserViewModel>(user);

        return RedirectToAction("Index", "Dashboard", userViewModel);
    }

【问题讨论】:

  • 您的仪表板视图是否使用model IList&lt;ProductViewModel&gt;
  • 没有,我的仪表板正在使用 UserViewModel。我的产品视图使用 List 。但我仍然希望 BaseViewModel 存在于产品视图中,因为我想在导航栏中显示用户的名字和姓氏@kayess
  • 我(和其他人)已经answered 一个类似的问题。看看它,可能适合您的解决方案。
  • 我添加了一个通用视图模型,您可以将其用于每个视图,请参阅 AppViewModel 类
  • 我不确定这是不是一个好习惯,一旦用户登录,将基础模型添加到会话中,您可以在需要时检索它

标签: c# asp.net-mvc asp.net-mvc-4 layout viewmodel


【解决方案1】:

您可以保留您的UserViewModelBaseViewModel 并使用组合将兼容类型发送到您的View 并避免如下所示的错误。这种方法使用所谓的对象组合

见下文,创建@​​987654324@ 类

public class AppViewModel
{
  public UserViewModel UserViewModel { get; set; }
  public List<ProductViewModel> ProductViewModel { get; set; }
}

// 登录动作方法或任何动作方法

填充AppViewModel 以发送到视图

public class HomeController {
    //Action method
      public ActionResult Login(LoginViewModel model)
      {
        //Do stuff and populate AppViewModel

         UserViewModel userViewModel = new UserViewModel {Username = "username", Password ="secret", FirstName = "John", LastName = "Doe"};
         AppViewModelmodel model = new AppViewModel{UserViewModel = userViewModel };
         return RedirectToAction("Index", "Dashboard", model);
      }
}

// 产品控制器

public class ProductController
{
  public ActionResult Products()
  {
    ProductViewModel productViewModel = new ProductViewModel { /*Initialize properties here*/};
    AppViewModel model = AppViewModel { ProductViewModel  = new List<ProductViewModel>{ new ProductViewModel =  productViewModel }};
    return View(model);
  }
}

// 仪表板视图

// Do include your model namespace
@model AppViewModel 
<div>
   <p> FirstName : @Model.UserViewModel.FirstName</p>
</div>

// 产品视图

// Do include your model namespace
@model AppViewModel 
<div>
   //You get the idea
   <p> Product Name: @Model.ProductViewModel.Select( x => x.ProductName).       </p>
</div>

【讨论】:

  • 我已修改代码以使用 AppViewModel.cs。您将能够在此设计中使用一个视图模型,但需要您更改设计以在需要它的视图中使用一个视图模型。
【解决方案2】:

我通常做的是创建一个LayoutController。使用这个控制器,我可以渲染布局页面上使用的所有持久信息。

public class LayoutController : Controller
{
    private readonly IProvideData _provider;

    public LayoutController(IProvideData provider)
    {
        _provider = provider;
    }

    [ChildActionOnly]
    public ActionResult AccountInformation()
    {
        var model = _provider.GetUserStuff();
        return PartialView("_AccountInformation", model);
    }
}

ChildActionOnly 属性确保动作方法只能作为视图中的子方法调用。在我的_Layout.cshtml 上,我可以使用以下方式渲染此操作:

@{ Html.RenderAction("AccountInformation", "Layout"); }

渲染_AccountInformation部分视图,看起来像:

@model MyApplication.ViewModels.UserInformation
Username: @Model.UserName

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2012-12-19
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2011-10-28
    相关资源
    最近更新 更多