I have spent the better part of a week now trying to encapsulate a jqGrid control into something that could be cleanly and easily reused from various ASP.NET views.  In some ways, I think I have met those goals, but in others, I think I have failed miserably.  On the plus side, actually creating a grid is quite easy:

   1: <%=Html.JQGrid("treeTabel",
   2:                 new JQGridOptions 
   3:                     { Caption="Components",
   4:                       DataUrl = Html.BuildUrlFromExpression<SandboxController>(c => c.JQGridTreeViewData((int)ViewData["EstimateId"], null)), 
   5:                       PagerId="PagerId", 
   6:                       IsTreeGrid = true,
   7:                       CellEditEnabled = true,
   8:                     },
   9:                 new[]
  10:                     {
  11:                         new JQGridColumn("id", "ID") { Visible = true, IsExpandColumn = true, Editable = false},
  12:                         new JQGridColumn("ComponentId", "ComponentId") { Visible = false, Editable = false},
  13:                         new JQGridColumn("Name", "Component"),
  14:                         new JQGridColumn("HistoricalCost", "Historical"), 
  15:                         new JQGridColumn("EstimatedCost", "Estimated"), 
  16:                         new JQGridColumn("TargetCost", "Target"),
  17:                         new JQGridColumn("Risk", "Risk") { EditType = "select" ,EditOptions = new[] { "Unassigned:Unassigned", "Low:Low", "Medium:Medium", "High:High"}}, 
  18:                     }) %>

That simple (well, sort-of simple), type-safe code produces this horrible mass of HTML and JavaScript:

   1: <script type='text/javascript'>
   1:  
   2: jQuery(document).ready(function(){
   3: jQuery('#treeTabel').jqGrid({
   4: url: '/Sandbox/JQGridTreeViewData/2',
   5: datatype: 'json',
   6: height: '475px',
   7: colNames:['ID','ComponentId','Component','Historical','Estimated','Target','Risk'],
   8: colModel:[
   9: {name:'id',index:'id',sortable:false,width:1},
  10: {name:'ComponentId',index:'ComponentId',sortable:false,width:1,hidden:true},
  11: {name:'Name',index:'Name',editable:true,sortable:false,width:1},
  12: {name:'HistoricalCost',index:'HistoricalCost',editable:true,sortable:false,width:1},
  13: {name:'EstimatedCost',index:'EstimatedCost',editable:true,sortable:false,width:1},
  14: {name:'TargetCost',index:'TargetCost',editable:true,sortable:false,width:1},
  15: {name:'Risk',index:'Risk',editable:true,sortable:false,width:1,edittype:'select',editoptions:{value:'Unassigned:Unassigned;Low:Low;Medium:Medium;High:High'}}
  16: ],
  17: pager: jQuery('#PagerId'),
  18: rowNum:25,
  19: rowList: [10,25,50,100],
  20: imgpath: '/Content/jQueryPlugins/JQGrid/themes/steel/images',
  21: width:(document.body.clientWidth)*(7/10),
  22: shrinkToFit: true,
  23: caption: 'Components',
  24: loadonce: false,
  25: treeGrid: true,
  26: ExpandColumn: 'id',
  27: treeGridModel: 'adjacency',
  28: cellEdit: true,
  29: cellsubmit: 'clientArray'
  30: }).navGrid('#PagerId',{edit:false,add:false,del:false,search:false,refresh:false})
  31: ;});

</script>

   2: <table id='treeTabel' class='scroll'></table>
   3: <div id='PagerId' class='scroll' style='text-align:center;'></div>

Obviously that’s a step up.  But when you look under the covers, things are anything but clean and neat.  Basically, I have several methods that build up a bunch of JavaScript strings, then spit them back out.  It reminds me *so* much of old-school PHP, where you have this awful mix of presentation markup and PHP code interwoven together into a blanket that looks like someone threw up on it.  Here’s an excerpt:

   1: if (options.IsTreeGrid)
   2: {
   3:     JQGridColumn expandColumn = columns.FirstOrDefault(c => c.IsExpandColumn);
   4:  
   5:     if (expandColumn == null)
   6:     {
   7:         throw new InvalidOperationException("IsTreeGrid is true, but no column found with IsExpandColumn set to true.");
   8:     }
   9:  
  10:     js.AppendLine("treeGrid: true,");
  11:     js.AppendFormat("ExpandColumn: '{0}',", expandColumn.Name).AppendLine();
  12:     js.AppendLine("treeGridModel: 'adjacency',");
  13: }
  14:  
  15: //If cell editing is enabeled, the changed rows are stored client-side,
  16: //and it is the responsibility of the page to provide a mechanism
  17: //for posting the data back.
  18: if (options.CellEditEnabled)
  19: {
  20:     js.AppendLine("cellEdit: true,");
  21:     js.AppendLine("cellsubmit: 'clientArray',");
  22: }

So, I’m torn.  Overall, I think the ASP.NET MVC approach is much, much better than the WebForms approach, but… is this it?  Is this really the best we can do?  There has to be a better way to do things like this.  There has to be a way to keep languages separate.  There has got to be a cleaner way to encapsulate and reuse "controls" in ASP.NET MVC.  I just haven’t found it yet.