MVC - 如何在每个页面视图中实例化,存储和创建整个应用程序中的类型变量

Mar*_*nox 5 asp.net-mvc global-variables

我正在开发一个MVC应用程序来服务多个域 - 每个域都是一个大公司的分支.

LocalBranch类存储详细信息,如电话,地址,电子邮件,位置坐标等.

我想为每个http请求创建一个这个类的单个实例,并让它在整个应用程序中可用 - 从控制器,视图,一些帮助程序类和其他代码.

有推荐的方法吗?

现在我将它作为a上的属性BaseController并用于ViewBag将其传递给视图.但如果可能的话,我希望它强烈输入视图.

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

如果可能的话,我宁愿避免使用会话变量,因为我们可能会在未来扩展到使用多个服务器,而且我听说这对会话不起作用.

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

Ami*_*ich 6

在每个请求的Web应用程序中维护状态的最佳方法是使用HttpContext类.

您需要将状态(LocalBranch)存储为一个ItemHttpContext:

HttpContext.Current.Items.Add("LocalBranch", GetLocalBranch());
Run Code Online (Sandbox Code Playgroud)

您可以在整个应用程序中获取所有项目,如下所示:

LocalBranch branch = HttpContext.Current.Items["LocalBranch"] as LocalBranch;
Run Code Online (Sandbox Code Playgroud)

Items物业只是一个关键价值Dictionary.值是一个对象.您必须检查空值,这与Session您知道的对象非常相似.
主要区别在于范围.这HttpContext是一个点网络对象,具有http请求的生命周期.

现在使用HttpContext,我向你展示的方式是最简单的方法.

您可以前进两步并使用名为Unity的框架,并为您的对象添加生命周期.
Unity做得更多,终身管理只是一个宝石.

您可以创建自定义HttpContext生命周期,以便为每个请求生成对象.
这样的东西.

他们所需要做的就是:

1.注册具有HttpContext生命周期的LocalBranch类.
2.添加一个静态Current属性,该属性将使用Unity容器并解析正确的实例LocalBranch.
3.使用这样的东西:LocalBranch.Current

顺便说一句,您可以使用Unity dependency injection将对象注入控制器和其他模块.这是一个更好的做法,然后只使用静态Current属性.


sol*_*dau 5

你在这里有两个问题.第一个是"如何根据HttpRequest创建此类的单个实例?" 第二个是"我如何将其用于强类型视图?"

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

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

public class BaseViewModel
{
    public LocalBranch Branch {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

然后,使所有当前视图模型继承此基本类型

public MyViewModel : BaseViewModel
{
    public string SomeValue {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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
    } 
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用过滤器装饰Controller和/或Actions(如果需要,您甚至可以在全局过滤器中设置它).