MVC - 如何在整个应用程序中实例化、存储并使类型化变量可用,每次页面视图一次

MVC - How to instantiate, store and make a typed variable available throughout the application, once per page view

我正在开发一个 MVC 应用程序来服务多个域——每个域都是一家大公司的分支机构。

A LocalBranch class 存储详细信息,例如 phone、地址、电子邮件、位置坐标等

我想为每个 http 请求创建这个 class 的单个实例,并使其在整个应用程序中可用 - 从控制器、视图、一些助手 classes 和其他代码。

有推荐的方法吗?

现在我将它作为 BaseController 上的 属性 并使用 ViewBag 将其传递给视图。但如果可能的话,我更希望在视图中使用强类型。

我不想把它放在应用程序变量中,因为我们需要为不同的域提供不同的值。

如果可能的话,我宁愿避免使用 session 变量,因为我们将来可能会扩展到使用多个服务器,而且我听说这与 sessions 不兼容。

如果您认为有更清晰的方式表达我所追求的内容,请随时更新标签/标题。谢谢。

您可以将子操作嵌入到您的布局或视图中。您甚至可以缓存它的输出,这样您就不会一直重新查询数据库。

控制器

[ChildActionOnly]
[OutputCache(Duration=500, VaryByParam="*")]
public ActionResult Info()
{
    var localBranch = db.GetLocalBranch();
    return PartialView("_Info", localBranch);
}

_信息视图

此位将插入到您的其他视图中

@model LocalBranch
<span>@Model.address</span>
<span>@Model.phone</span>

在 _Layout 或其他视图中使用

<p>lorem ipsum...</p>
@Html.Action("Info")

在 Web 应用程序中按请求维护状态的最佳方法是简单地使用 HttpContext class.

您需要将您的状态 (LocalBranch) 存储为 Item 中的 HttpContext:

HttpContext.Current.Items.Add("LocalBranch", GetLocalBranch());

您可以像这样在整个应用程序中获取项目:

LocalBranch branch = HttpContext.Current.Items["LocalBranch"] as LocalBranch;

Items 属性 只是一个键值 Dictionary。该值是一个对象。您必须检查 nulls,这与您知道的 Session 对象非常相似。
主要区别在于范围。 HttpContext 是一个具有 http 请求生命周期的点网对象。

现在按照我向您展示的方式使用 HttpContext 是最简单的方法。

您可以向前迈出两步,使用名为 Unity 的框架并为您的对象添加生命周期。
Unity 做得更多,生命周期 management 只是一个 gem.

您可以创建自定义 HttpContext 生命周期,为每个请求生成对象。
类似于this

你需要做的就是:

1.Register 你的 LocalBranch class 具有 HttpContext 生命周期。
2.Add 静态 Current 属性,它将使用 Unity 容器并解析 LocalBranch.
的正确实例 3.Use 是这样的:LocalBranch.Current

顺便说一句,您可以使用 Unity 的 dependency injection 将对象注入控制器和其他模块。这是比使用静态 Current 属性.

更好的做法

你这里有两个问题。第一个是 "How do I create a single instance of this class per HttpRequest?" 第二个是 "How do I make this available to strongly typed views?"

@amir-popovich 几乎已经回答了第一个问题,即使用依赖注入。但是,FWIW 我可能会使用 Ninject 而不是 Unity(真的只是偏好),我可能会以不同的方式实现它。我不会使用 HttpContext,而只是构建一个服务(使用 Ninject 的 OnePerHttpRequest 模块实例化,将域作为参数传递以获得正确的值)。

然后,为了将这些 LocalBranch 值添加到您的强类型视图模型中,您可以首先创建一个包含此类型的基本视图模型:

public class BaseViewModel
{
    public LocalBranch Branch {get;set;}
}

然后,让您当前的所有视图模型都继承此基类型

public MyViewModel : BaseViewModel
{
    public string SomeValue {get;set;}
}

然后在您的控制器中,很容易从您在第一步中创建的服务中添加这些值

public ActionResult SomeAction()
{
    var vm = new MyViewModel();
    vm.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject

    //do other stuff

    return View(vm);
}

但是,将其添加到每个控制器操作会变得非常乏味,因此您可以改为创建一个结果过滤器来为您添加它:

public class LocalBranchResultFilter : FilterAttribute, IResultFilter 
{
    public void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //This method gets invoked before the ActionResult is executed.
        filterContext.Controller.ViewData.Model.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject
    } 
}

现在,您可以用过滤器装饰您的控制器 and/or 操作(如果需要,您甚至可以在全局过滤器中设置它)。