views:

526

answers:

4

I have a unique scenario where I want a base controller to grab some data and store it in a list. The list should be accessible from my views just as ViewData is. I will be using this list on every page and would like a cleaner solution than just shoving it in the ViewDataDictionary.

After attempting to come up with a solution, I thought I would create a custom ViewPage with a property to hold my list. My custom ViewPage would inherit from System.Web.MVC.ViewPage. However, I do not know where MVC passes the viewdata from the controller off to the view. More importantly, how do I get it to pass my list down to the view?

Thanks for the help.

EDIT....

Sorry for the confusion. I was trying to keep the question as simple as possible to avoid any confusion. Obviously, that did not work :)

I'm implementing my own session management in an .net mvc project. When a request comes in, my base controller checks to see if a session cookie was sent along with the request in the OnActionExecuting method. If a session cookie was sent, my controller hits the database and retrieves the user's session information. The session information (userid, etc..) is put into a List object and stored in a property called "Sess".

I want to be able to access elements in the Sess list from my views like this: <%= Sess[0] %>

So, how and where do I get my controller to hand off the Sess list to my views?

I realize that this is not how custom session management is typically implemented in .net. However, this would be the simplest and cleanest solution for my project.

Thanks to everyone who has helped so far!

A: 

Why don't you want to use ViewData? Is it just because you don't want to have a line of code in every single action that puts some data in the ViewDataDictionary?

You can use an action filter and put that data before each action executes, like for example

public class AddSomeDataToViewDataAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //filterContext.Controller.ViewData.Add("SomeConstant")(data);
    }
}

Then, you just put this attribute in every Controller or in a base controller.

Edit: You can make a couple of extension methods like

public static void Add<T>(this IDictionary<string, object> dictionary, T anObject)
{
    var key = typeof(T).Name;
    dictionary.Add(key, anObject);
}

public static T Get<T>(this IDictionary<string, object> dictionary)
{
    var key = typeof(T).Name;
    return (T)dictionary[key];
}

Then you add the data like this:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    //filterContext.Controller.ViewData.Add<YourListType>(data);
}

And in the View, you get the data like this:

ViewData.Get<YourListType>();

Regards.

uvita
I don't want to have to cast ViewData["Session"] as a list each time in my views.
josh
Ok, I edited my answer.
uvita
A: 

Question not clear: To answer part of it, you can use a property on a base ViewModel. You need to set that property in the constructor of the base ViewModel. Your instance objects need to call the constructor of the base ViewModel explicitly if any values need to be passed down to it for whatever work it is doing... This constructor calling is all normal C# so there are plenty of examples on the web.

I agree that if this is for menus, RenderAction does seem like a much easier way to implement the functionality. I tried the base ViewModel method for menus and then switched to using RenderAction on a controller that is specifically responsible for navigation.

The lack of dynamic navigation examples for ASP.NET MVC sites is surprising as it seems like such a basic requirement.

Cymen
A: 

You have to describe your problem better.

And, well, except action filter or Controller.OnActionExecuted override, you can use Html.RenderAction.

queen3
+2  A: 

In general, I'd recommend being explicit about what your views are allowed to access. Thus I'd recommend that you put this data in ViewData from your controller, and then pull it out of ViewData from the view. That keeps the line of communication between your controller and view in one place and simple.

However, if you really want to access the Session from the view, you can.

<%: ViewContext.HttpContext.Session["key"] %>

One thing you could do is have your own custom view page class that derives from System.Web.Mvc.ViewPage and change the Inherits declaration at the top of the page to point to your view page.

<%@ Page ... Inherits="YourNamespace.YourViewPage" %>

Your custom view page could have whatever properties you need.

Haacked