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

I am developing an MVC application for serving multiple domains - each of them is a branch of a larger company.

The LocalBranch class stores data such as phone, address, email address, location coordinates, etc.

I want to create one instance of this class for each HTTP request and have it available throughout the application - from inside controllers, views, some helper classes and other code.

Is there a recommended way to do this?

Right now I use it as a property in BaseController and use the ViewBag to pass it to the views. But I would prefer that he be strongly typed in the Views, if possible.

I do not want to put it in the application variable, because we need to serve different values ​​for different domains.

I would prefer to avoid the session variable, if possible, because in the future we can scale to use multiple servers, and I heard that it doesn’t work well with sessions.

Please feel free to update the tags / title if you think there is a clearer way to express what I need. Thanks.

+5
source share
3 answers

You have two questions. First: "How to create one instance of this class for HttpRequest?" The second way: "How to make it available for strongly typed views?"

The first was pretty @ amir-popovich's answer to use dependency injection. However, FWIW I would probably use Ninject instead of Unity (just a preference, really), and I would probably use it differently. I would not use HttpContext and just create a service (which starts using the Ninject OnePerHttpRequest module, passing the domain as an argument to get the correct values).

Then, to add these LocalBranch values ​​to a strongly typed view model, you can first create a base view model that contains this type:

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

Then make all your current view models inherit this base type

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

Then, in your controller, it is enough to simply add these values ​​from the service created from the first step.

 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); } 

However, it is rather tedious to add this to every controller action, so you can instead create a result filter to add it for you:

 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 } } 

Now you can simply decorate your controller and / or actions with a filter (you can even set it in global filters if you want).

+5
source

The best way to maintain your state in a web application for each request is to simply use the HttpContext class.

You need to save your state (LocalBranch) as Item in the HttpContext :

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

You can get the item throughout your application as follows:

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

The Items property is simply the value of the Dictionary key. Value is an object. You will need to check for nulls , and it really looks like a Session object that you know.
The main difference is the area. HttpContext is a point network entity that has an HTTP request lifetime.

Now, using the HttpContext, I have shown that this is the easiest way to do this.

You can go two steps forward and use a framework called Unity and add a lifetime to your objects.
Unity does much more, and lifecycle management is just one stone.

You can create your own HttpContext lifetime that generates objects for each request.
Something like that .

And all you have to do is:

1. Register your LocalBranch class with an HttpContext .
2. Add a static current property that the Unity container will use and allow the correct LocalBranch instance.
3.Use it something like this: LocalBranch.Current

BTW, you can use Unity dependency injection to enter objects into controllers and other modules. This is best practice and then just using the static property of Current.

+6
source

You can embed child actions in a layout or view. You can even cache your output so you don’t have to continue to query the database again.

controller

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

Browse _Info

This bit will be inserted into your other views.

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

Use in _Layout or another view

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

Source: https://habr.com/ru/post/1212033/


All Articles