Saturday, November 9, 2013

Simple Custom MVC Helper


In last post we have seen Extension method concept,Here in this post we will see  Extension method usages in creation of custom  MVC HTML Helper.Though I have quite few other example of custom Helper like dropdown from enumeration or Datetime picker widget, i am taking example code syntax Highlighting as it need simple 'pre' tag in HTML.
     In ASP.NET MVC Framework, Html Helper extension methods are located in System.Web.Mvc.Html namespace. To have our own custom Html Helper method we can write Extension Methods for HtmlHelper class.
Here I am going to create very simple syntax highlighter extension for MVC. I am starting with Empty MVC 4 Web Application.
First I am adding a folder called Utility; in that folder I add a class “CustomHelper.cs”.
 [Code: CustomHelper.cs]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace CustomHtmlHelper.Utility
{
    public static class SyntaxHighlighterExtension
    {
        public static MvcHtmlString SyntaxHighlighter(this HtmlHelper htmlHelper,string WidgetId, string Code)
        {
             StringBuilder sb = new StringBuilder();
             sb.Append("<pre name='code' class='c-sharp'>");
             sb.Append(Code);
             sb.Append("</pre>");
             return MvcHtmlString.Create(sb.ToString());
        }
    }
}
Secondly we need to have syntax highlighter JQuery plugin. I referred resources at http://code.google.com/p/syntaxhighlighter/  & downloaded available code and extracted the plugin into my JS folder. After adding the plugin files my folder structure look as below.

Now add a Default controller.In controllers Index action what we are doing is passing ViewData["CsharpCode"] containing some simple C# code to view for rendering.
[Code: DefaultController.cs]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CustomHtmlHelper.Controllers
{
    public class DefaultController : Controller
    {
        //
        // GET: /Default/

        public ActionResult Index()
        {
            ViewData["CsharpCode"] = @"private void MyTaskWorker(string[] files)
{
  foreach (string file in files)
  {
    // a time consuming operation with a file (compression, encryption etc.)
    Thread.Sleep(1000);
  }
}";
            return View();
        }

    }
}

Now Add a folder Shared inside view folder, into it add a view file “SiteMaster.cshtml
[Code: SiteMaster.cshtml]
<!DOCTYPE html>
<html>
<head>
    <link type="text/css" rel="stylesheet" href="~/JS/JQueryPlugins/SyntaxHighlighter/Styles/SyntaxHighlighter.css"/>
    <script src="~/JS/JQueryPlugins/SyntaxHighlighter/Scripts/shCore.js"></script>
    <script src="~/JS/JQueryPlugins/SyntaxHighlighter/Scripts/shBrushCSharp.js"></script>
    <script src="~/JS/JQueryPlugins/SyntaxHighlighter/Scripts/shBrushXml.js"></script>

   
    <title>@ViewBag.Title</title>
    <style type="text/css">
         #RightMenu ul li {
            display:inline;
            background-color:red;
           
        }
        #RightMenu ul li a {
            padding-left:10px;
            color:white;
        }
    </style>
</head>
<body style="margin: auto; width: 1024px; height: 768px;">
    <div id="MainContainer" style="border: 1px solid black; width: auto; height: auto; margin: 5px auto auto;">
        <div id="header" style="border: 1px solid black; width: auto; height: 110px;">
             <div id="LeftLogo" style="border: 1px solid black; width: 120px; float: left; height: 100%;">
                <div style="text-align: center; vertical-align: middle; padding-top: 5px;">side menu..</div>
            </div>
            <div id="RightMenu" style="border: 1px solid black; height: 100%;">
                <div style="height:70px;">

                </div>
                <ul style="list-style-type: none;text-align:center;">
                    <li>
                        <a href="#">Home</a>
                    </li>
                    <li>
                        <a href="#">About Us</a></li>
                    <li>
                        <a href="#">Services</a>
                    </li>
                    <li>
                        <a href="#">Technology</a> 
                    </li>
                    <li>
                        <a href="#">Outsourcing</a> 
                    </li>
                    <li>
                        <a href="#">Quality</a> 
                    </li>
                    <li>
                        <a href="#">Career</a> 
                    </li>
                    <li>
                        <a href="#">Blogs</a> 
                    </li>
                    <li>
                        <a href="#">Partner</a> 
                    </li>
                    <li>
                        <a href="#" title="Contact Us">Contact Us</a> 
                    </li>
                </ul>
            </div>
               
        </div>
        <div id="content" style="border: 1px solid black; width: auto; height: 620px;">
            <div id="LeftMenu" style="border: 1px solid black; width: 120px; float: left; height: 100%;">
                <div style="text-align: center; vertical-align: middle; padding-top: 5px;">side menu..</div>
            </div>
            <div id="RightContent1" style="border: 1px solid black; height: 100%;">
                @RenderBody()
            </div>
        </div>
        <div id="footer" style="border: 1px solid black; width: auto; height: 50px;">
            <div style="text-align: center; vertical-align: middle; padding-top: 5px;">footer..</div>
        </div>
    </div>

    <script type="text/javascript">
        dp.SyntaxHighlighter.ClipboardSwf = '/JS/JQueryPlugins/SyntaxHighlighter/Scripts/clipboard.swf';
        dp.SyntaxHighlighter.HighlightAll('code');
    </script>
</body>
</html>

SiteMaster.cshtml is our master page (Layout page in MVC).
Now add a view file _ViewStart.cshtml into View folder
[Code: _ViewStart.cshtml]
@{
    Layout = "~/Views/Shared/SiteMaster.cshtml";
}

Underscore in name of this file is indicator of its private nature, it is used to assign master page i.e. Layout in MVC terminology based on condition at runtime. In our case we are assigning same Layout Page to all pages.

Now add a view for our Default controller Index action. Code in this file is as below.
[Code: Index.cshtml]
@using CustomHtmlHelper.Utility
@{
    ViewBag.Title = "Index";
}
<div style="text-align:center;vertical-align:middle;padding-top:5px;">from content page..</div>
@Html.SyntaxHighlighter("MyWidgetId",ViewData["CsharpCode"].ToString());


Using directive is needed to access our newly defined MVC Helper for SyntaxHighlighting.
The line below Makes call to our custom MVC helper it passes string send in ViewData from Controller action to our extension method.
@Html.SyntaxHighlighter("MyWidgetId",ViewData ["CsharpCode"].ToString());\

Below is our custom MVC Html Helper at work
Main idea behind between this custom html helper is to generate simple html of type below.
<pre name='code' class='c-sharp'>
   some c# snipet
</pre>
Layout Page used in this project is preliminary ,My  focus is this code is on Custom MVC HTML Helper method and not on Layout.On some latter post we will touch the concept of layout in MVC.
Complete code of this application is can be downloaded from here

No comments:

Post a Comment