Static Views

Jul 27, 2016 at 8:53 PM
Hello,

Is there any way to have a Controller Action which, rather than creating a new instance of a View, returns an existing instance of one?

For instance, if you had a Customer Search View, it might be more useful for an action which opens that view to always point to the same version of the view, rather than creating new instances each time. Since the content which the View loads will be the same each time (as opposed to an Edit Customer view which would load the data of a specific customer), it seems like a static reference would be more desirable. Is there any way to implement this?

Thanks.
Jul 28, 2016 at 3:55 PM
Hi mcargille ...

I have had similar requirements in a number of projects. As you see in the following code, we iterate through the NormalViews collection of the Shell object comparing our target string to view titles. Here we're using the "title" attribute of Code Framework's SimpleView template and, in the example, assume the title is "Customer Search". If a match is found we get the index of the existing view then Shell.Current.SelectedNormalView is set to that index. If no match is found after comparing all the open views a new view instance is created for our search.

Since we're comparing titles here we have the ability to search for very specific views (e.g. "Patient Profile: Doe, John" vs "Patient Profile: Doe, Jane"). In this scenario the title of a generic "Patient Profile" view is set in the view's model to include the patient's name and, therefore, make it unique. We have multiple instances of the "Patient profile" view but can determine if a specific patient's profile is already open. It is also possible to search for other view properties or content.
            Actions.Add(new ViewAction("Customer Search",  execute: (a, o) =>
                    {
                        if (NotOpen("Customer Search")) Controller.Action("SearchController", "Search") ;   //If not already open, open the view
                    }
            );
Then, elsewhere:
        bool NotOpen (string viewTitle)
        {
            foreach (var item in Shell.Current.NormalViews)
                if (item.ViewTitle == viewTitle)                                 //If already open just switch to that view
                {
                    var idx = Shell.Current.NormalViews.IndexOf(item);
                    Shell.Current.SelectedNormalView = idx;
                    return false;
                }
            return true;            //No instance found
        }
I hope this helps.
Marked as answer by mcargille on 7/28/2016 at 11:56 AM
Jul 28, 2016 at 7:56 PM
That's a really clean solution. Thanks.
Aug 11, 2016 at 3:22 PM
An update for anyone else attempting this: I found you can move the responsibility to the Controller rather than the Views if the static view behavior is always expected for a particular action.

Define the NotOpen function as above in a static class (I called it ControllerHelper). Then define the Controller Action which needs to return a static view as follows:
        public ActionResult Search()
        {
            var result = View(new SearchViewModel());

            if (ControllerHelper.NotOpen(result.ViewTitle))
                return result;
            else
                return null;
        }
So if, for example, this were in the CustomerController class, invoking Controller.Action("Customer", Search") would then always return the existing Customer Search view if one is open, and will open a new one only if there is not yet a view with the corresponding name.