In this tip, I suggest a method of passing data to master pages and user controls. However, before I make recommendations, I first explore several alternatives to the same problem.
Using Action Filter So, try to solve the problem of transferring data to the master page or view the other way. In this section, we create an action filter to replace the view data that is converted to view. The idea is that you can direct your controller actions with one or more action filters to control which view data is passed from the controller to which view.
The action filter, named [Partial] is contained in Listing 3. Listing 3 – ActionFilters PartialAttribute.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | using System; using System.Reflection; using System.Web.Mvc; namespace Solution2.ActionFilters { public class PartialAttribute : ActionFilterAttribute { private string _partialClassName; public PartialAttribute(string partialClassName) { _partialClassName = partialClassName; } public override void OnActionExecuting(ActionExecutingContext filterContext) { var viewData = (filterContext.Controller as Controller).ViewData; ExecutePartial(_partialClassName, viewData); } private void ExecutePartial(string partialName, ViewDataDictionary viewData) { // Get partial type var partialType = Type.GetType(partialName, true, true); var partial = Activator.CreateInstance(partialType); // Execute all public methods var methods = partialType.GetMethods(); foreach (MethodInfo method in methods) { var pams = method.GetParameters(); if (pams.Length > 0 && pams[0].ParameterType == typeof(ViewDataDictionary)) method.Invoke(partial, new object[] { viewData }); } } } } |
When you add the [Partial] filter action to the controller action, the action filter adds additional data to the view data. For example, you can use the [Partial] attribute to add movie genres to view data so that categories are valid in the master page. You can also use the [Partials] attribute to add feature films to view data so that this data is valid in FeaturedMovie user control.
The [Partial] property takes a class name, initializes the class, and executes all public methods of the class (each takes the ViewDataDipedia parameter). The controller in Listing 4 illustrates how you can use the [Partial] filter action to fix the view data returned by different controller actions.
Listing 4 – HomeController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | using System.Linq; using System.Web.Mvc; using Solution2.ActionFilters; using Solution2.Models; namespace Solution2.Controllers { [Partial("Solution2.Partials.Master")] public class HomeController : Controller { [Partial("Solution2.Partials.Featured")] public ActionResult Index() { return View(); } public ActionResult Category(int id) { var dataContext = new MovieDataContext(); var movies = from m in dataContext.Movies where m.CategoryId == id select m; return View("Category", movies); } } } |
Notice that the HomeContoder class itself is oriented with [Partial] action filter. Because the [Partial] action filter is applied to the class, the action filter will execute whenever any HomeContoder action method is called. Apply the [Partial] attribute at the meaningful level when providing view data to the master page.
The [Partial] attribute adds movie genres to view data. [Partial] implements the methods of Solution2.Partials.Master class contained in Listing 5.
Listing 5 – Master.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System.Linq; using System.Web.Mvc; using Solution2.Models; namespace Solution2.Partials { public class Master { public void AddViewData(ViewDataDictionary viewData) { var dataContext = new MovieDataContext(); var categories = from c in dataContext.MovieCategories select c; viewData["master"] = categories; } } } |
The AddViewData () method adds categories to the key named master in the view data dictionary. The categories are taken from the data view in the master page and displayed.
The [Partial] attribute can only be applied to certain action methods and not to other action methods. For example, the Index () method in Listing 4 includes an [Partial] property that implements the Solution2.Partials.Featured class. This class adds data for FeatureMovies user control.
So, is there something wrong with this solution for data transfer from controller to master page or user control? The advantage of this approach over the previous approach is that we tried to push the database data access logic back to the controller. The view data is modified when a controller action is called.
Also, this solution is unique. By using the [Partial] property, you can put multiple view data layers into the view data dictionary. For example, if you discover that you need to add a new user control to certain pages and a new user control needs a different set of data, you can simply add a new [Partial] attribute for the correct controller actions. and add new data for view data dictionary.
Unfortunately, this solution is not verifiable. Action filters are not executed when you call action methods in unit tests. Therefore, we need to look for another strategy. (Continue)