首页 > 解决方案 > 使用 MVC 从 URL 构建基于 Id 的布局 ViewModel

问题描述

我需要为我的布局的 Web 应用程序构建一个 ViewModel,我已经尝试过这个解决方案,但它不是基于来自 URL 的 URL 的 Id 来生成布局的 ViewModel。

我试过这个,但我首先遇到了不存在的空控制器错误,然后我尝试将 id 作为参数包含在内,但我收到错误“对象引用未设置为对象的实例”。因为没有设置 LayoutColorRGB。

public MobileController(int id)
{
    Event model = db.Events.Where(s => s.Id == id).FirstOrDefault();

    LayoutVM = new LayoutVM()
    {
        EventId = model.Id,
        LayoutColorRGB = model.LayoutColorRGB,
        SponsorLogoLink = model.SponsorLogoLink,
        SponsorLogoURL = model.SponsorLogoURL
    };

    ViewData["LayoutVM"] = LayoutVM;
}

标签: c#.netasp.net-mvcmodel

解决方案


有很多情况需要根据请求上下文提取数据并在布局页面上显示一些东西。例如:

  • 您可能想要显示登录的用户信息
  • 您可能想要显示访问者或在线访问者的数量
  • 您可能希望显示当前语言并让用户更改语言。
  • 您可能希望从数据库加载站点菜单或侧边栏或页脚

为此,您可以考虑以下几点:

  • 局部视图:您可以为每个局部视图具有特定模型的那些部分创建一些小的局部视图,并将它们呈现在布局页面中。

  • 使用上下文获取数据:Request您可以通过从、ViewContext、和其他上下文对象中RouteData提取信息来初始化模型。ValueProvider

  • 通过 HTML 助手访问数据:您可以创建一个HtmlHelper从上下文获取数据并在布局或部分视图中使用助手。

  • 通过依赖注入访问数据:您可以定义一些用于提取数据的服务,然后将这些数据注入到布局页面。在服务中,您将使用上下文对象初始化模型。如果您使用的是 ASP.NET CORE,这是一个不错的选择。

  • 作为基本控制器的属性访问数据:您可以在基本控制器中拥有一个属性,并在控制器的构造函数中或在OnActionExecuting. 然后在布局中,通过转换ViewContext.Controller为基本控制器的类型来获取属性并读取属性。

  • ViewBag 访问数据:可以在基控制器的构造函数中初始化模型实例,也可以在基控制器的OnActionExecuting方法中初始化模型实例,然后将其放入 ViewBag 中。然后您可以轻松地在视图中使用它。

  • 布局页面:不要忘记您可以定义不同的布局页面并根据您的要求使用不同的布局。您可以在操作中或在 中设置布局_ViewStart

例子

尝试在每个请求中解析 id 意味着您需要将 id 作为所有请求的一部分,或者您需要知道在没有 id 的情况下应该做什么。考虑到这一事实并为一个最小的示例保持简单,我将定义以下模型和基本控制器,并尝试在基本控制器的OnActionExecuting方法中解析 id,然后将从该基本控制器派生出所有需要此类行为的控制器。

您可以使用控制器方法的一个ActionFilter或全局操作过滤器来执行相同的操作。OnActionExecuting

使用以下代码:

  • 如果您浏览/home/index,您将在页面底部看到一个红色条。
  • 如果您浏览/home/index/1,您将在页面底部看到一个蓝色条
  • 如果您浏览/home/index/2,您将在页面底部看到一个绿色条

布局模型

public class LayoutViewModel
{
    public int? Id { get; set; }
    public string Color { get; set; }
}

基本控制器

public class BaseControllr : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //Get the id from route
        var id = int.TryParse(ValueProvider.GetValue("id")?.AttemptedValue, out var temp)
            ? temp : default(int?);
        var model = new LayoutViewModel();

        //Your logic to initialize the model, for example
        model.Id = id;
        if (model.Id == null)
            model.Color = "FF0000";
         else if (model.Id%2==0)
            model.Color = "00FF00";
        else
            model.Color = "0000FF";

        //Set ViewBag
        ViewBag.MainLayoutViewModel = model;
        base.OnActionExecuting(filterContext);
    }
}

家庭控制器

public class HomeController : BaseControllr
{
    public ActionResult Index(int? id)
    {
        return View();
    }
} 

_Layout.cshtml

然后在 中_Layout.cshtml,在结束标记之前添加以下代码<body/>进行测试:

@{ 
    string color = ViewBag.MainLayoutViewModel?.Color;
    int? id = ViewBag.MainLayoutViewModel?.Id;
}
<div style="background-color:#@color;">
    Id:@id
</div>

推荐阅读