Click here to Skip to main content
15,881,413 members
Articles / Web Development / ASP.NET
Article

ASP.NET MVC : Create Toolbar Control

Rate me:
Please Sign up or sign in to vote.
1.20/5 (2 votes)
27 Aug 2008CPOL3 min read 30.9K   1.1K   18   2
Creating Toolbar control in ASP.NET MVC

Introduction

Many applications need a Toolbar kind of functionality including application created using ASP.net MVC . I thought of epxerimenting this with ASP.net MVC.

Background

Think about a application (ex CRM) with different models (ex Customer, Order, Products) but similiar actions ( ex add, save, delete). From user experience point of view , it is desirable that performing an action on those models is same throughout a application hence "Toolbar"
I am not going to discuss much about in general MVC pattern or specific to ASP.net MVC rather I would focus on design of Toolbar control and decision i made.

Design consideration

  • Control should encapsulate all required HTML , Java script , Style sheet
  • Rendering View should only be concerned with providing controller information and actions require binding with ToolBar
  • It is not neccessary that all actions in controller required binding with Toolbar

Implementation

Control implementation is inspired by Seth juarez post.

One of design consideration is that not all controller's action required binding with Toolbar, how do we achieve this.

I had two options:

  1. While creating control in a view I pass list of actions to bind with ToolBar
  2. Create a custom attribute for action methods, apply this attirbut in controller. While redering a control, control check for this attribute and create required Tool bar Item.

I went for 2 option because i can reuse my Tool bar item defination across many views and i dont have to pass manually actions i want to use while creating a Toolbar.

so lets create custom Attribute ToolBarItemAttribute

C#
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false,Inherited=false)]
public sealed class TooBarItemAttribute:Attribute
{
public string ToolTip { get; set; }
}

I created custom attribute with single property tooltip which later would be used to show user friendly Text for controller's action. Attribut usage is set to method because we want to make sure that this attribute can only be applied on Methods.

Creeating ToolBar Control

Tool Bar control is nothing more than series of buttons encapsulated in HTML <form> tag. In order to change action of <form> element at Client side we need a Java script which modify action peoperty of form element depending on button pressed. We need to inject this Javascript when control is being rendered so let us create RenderJavaScript

C#
private string RenderJavaScript()
{
StringBuilder JavaScript = new StringBuilder();
JavaScript.AppendFormat(@"<script language=""javascript"" type=""text/javascript"">{0}",Environment.NewLine);
JavaScript.AppendFormat(@" function OnToolBarClick(action){0}",Environment.NewLine);
JavaScript.AppendFormat(@" {{{0}", Environment.NewLine);
JavaScript.AppendFormat(@" var form = document.getElementById(""{1}_Form"");{0}", Environment.NewLine, _formname);
JavaScript.AppendFormat(@" form.action = action;{0}",Environment.NewLine);
JavaScript.AppendFormat(@" form.submit();{0}",Environment.NewLine);
JavaScript.AppendFormat(@" }}{0}", Environment.NewLine);
JavaScript.AppendFormat(@"</Script>{0}", Environment.NewLine);
return JavaScript.ToString();
}

second we need a function to create Action URL

private string GetActionUrl(string actionName)
{
string controllerName = _controllerType.Name;

if (controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
{
controllerName = controllerName.Remove(controllerName.Length - 10, 10);
}
RouteValueDictionary values = new RouteValueDictionary();
values = values ?? new RouteValueDictionary();
values.Add("controller", controllerName);
values.Add("action", actionName);
VirtualPathData vpd = RouteTable.Routes.GetVirtualPath(_helper.ViewContext, values);
return (vpd == null) ? null : vpd.VirtualPath;

}

Third we need a function to render ToolBar Items. This function iterate through all the method of controllers which has ToolBarItemAttirbut Set and zero paramenter length.In button, we set our javascript function on onclick event to change main form action property. This function call GetActionURL

private void WriteToolBarItems()
{
var methods = from method in _controllerType.GetMethods() 
where method.GetCustomAttributes(typeof(TooBarItemAttribute),false).Length > 0 & method.GetParameters().Length == 0
select method;
StringBuilder sb = new StringBuilder();

sb.AppendFormat(@"<div>{0}", Environment.NewLine);
if (methods.Count() == 0)
sb.AppendFormat(@"<span><strong>{0} doesn't have any action with Attribute ToolBarItem<Strong></span>",_controllerType.Name);

foreach (MethodInfo method in methods)
{
sb.AppendFormat(@"<span>{0}", Environment.NewLine);
sb.AppendFormat(@"<button onclick=""OnToolBarClick('{1}')"" value=""{2}"">{2}</button>{0}",Environment.NewLine,GetActionUrl(method.Name),GetActionToolTip(method));
sb.AppendFormat(@"</span>{0}", Environment.NewLine);
}

sb.AppendFormat(@"</div>{0}", Environment.NewLine);
_context.Response.Write(sb.ToString());

}

There are some more function in ToolBar control to finish markup and not worth mentioning, you can check those in code.

Finally we have constructor which play very important role to create control. Htmlhelper give us access to response context, controller type to retieve and setup actions, formname of auto created form element, and alignment (Top, Bottom) of ToolBar with respect to other form child control you may create

public ToolBar(HtmlHelper helper, Type controllerType, string formName, ToolBarAlignment alignment):
this(helper,controllerType,formName,FormMethod.Post,alignment)
{

}

private ToolBar(HtmlHelper helper,Type controllerType,string formName,FormMethod formMethod, ToolBarAlignment alignment)
{
_helper = helper;
_context = helper.ViewContext.HttpContext;
_controllerType = controllerType;
_formname = formName;
_formMethod = formMethod;
_toolBarAlignment = alignment;
WriteStartTag();
if (_toolBarAlignment == ToolBarAlignment.Top)
WriteToolBarItems(); 
}

Using the code

This code require ASP.NET Prview 4 and visiual sudio 2008

using this ToolBar is two step process

1 Apply ToolBarItemAttriibute to methods in controller whose action you want to bind with toolbar

public class CustomerController:Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        [TooBarItem(ToolTip="Add Customer")]
        public ActionResult Add()
        {
           string CustomerName = this.ReadFromRequest("CustomerName");
           ViewData["CustomerName"] = CustomerName;
           return View();
        }
}
2 Using ToolBarHelper create Toolbar in your view
C#
<%using(Html.ToolBarControl(typeof(MVCToolBarExp.Controllers.CustomerController),"formWithToolBar",ToolBarAlignment.Top)) %>
<%{%>
<div><span>Customer Name:</span><%=Html.TextBox("CustomerName") %></div>
<%} %>

Attached source code contain ToolBar control source as well as dumy test project. Let me know your views and any alternative way of implementation

Download MVCToolBarExp.zip - 375.26 KB

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionGood code, but error on "string CustomerName = this.ReadFromRequest("CustomerName");" Pin
downmoon20085-Jun-09 4:24
downmoon20085-Jun-09 4:24 
GeneralNice Pin
Seth Juarez17-Oct-08 18:49
Seth Juarez17-Oct-08 18:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.