Sunday, September 27, 2015

Asp.Net MVC Intellisense for ViewBag

Introduction/Problem Statement: If you are a typical MVC developer, you might have used ViewBag or ViewData to pass data from Controller to View at times. Also, it is well understood that ViewBag is a dynamic type and hence you will not get intellisense for this. Again, it is a similar case with ViewData which is a dictionary instead and hence no strongly typed support and needs to deal with magic strings.

Workaround: We can easily create our own workaround for this. Here is a sample -
/// 
/// A class to hold the data which can be used to interact between controller and view.
/// 
public class ViewBagHelper
{
    /// 
    /// Gets the current instance of 
    /// 
    public static ViewBagHelper Items
    {
        get
        {
            if(HttpContext.Current.Items["item"] == null)
            {
                HttpContext.Current.Items["item"] = new ViewBagHelper();
            }

            return HttpContext.Current.Items["item"] as ViewBagHelper;
        }
    }

    // TODO: Add your intended ViewBag/ViewData properties here. Ex: To hold an id, do this
    // public int Id { get; set; }
}

Now anywhere you want to use ViewBag just do this - 

ViewBagHelper.Items.MyItem

Where, MyItem is your item name, which is basically a property of ViewBagHelper class. While using this in the View, make sure that you are using fully qualified name or you added the appropriate namesapce in the MVC's Web.Config file. For example, if my helper resides in the following namespace 'ViewBagIntellisense.Helper', then your razor config section of Web.Config should have this - 
  
    
    
      
        
        
      
    
  
The idea is not new, people often do this to avoid magic strings. For instance, 3 years back I myself asked the stackexchange community to review similar pattern. Well, it is still in unresolved state because the answers were not convincing enough. However, I continued to use this pattern in various projects and it worked well for me. Even you can find it in one of my old article

Downsides: The one potential downside which I can think of is, it shares various state representations across the application. However, still the memory footprint will be considerably low, as reference type properties are get initialized only on need basis and value types are inherently lightweight (Off-course, Unless you create one!). 

Recommendation/Best Practice: It is always good to have a Model/ViewModel to exchange data between controller and view. Use this pattern (Or ViewBag in general) only if you have some cross-cutting scenarios where putting the data in Model/ViewModel doesn't make much sense or you have only one piece of data to transfer.

1 comment: