XSLT Transformation in ASP.net MVC framework

In my last post I talked about using a partial view to render hierarchical data, however XSL transformation looks more appropriate for such cases. ASP.Net has XML control which can display XML document using XSL Transformations. I will show you how similar thing can be achieved in ASP.NET MVC Framework.

The Model

I have a very simple Tab class which can have a collection of sub-tab. this class can be used to create infinite level of tab hierarchy. I have added XmlAttributes to my properties so that when class is serialized those properties are sterilized as attributes.

public class  Tab {

    [XmlAttribute(
"id" )]
    
public int  ID {  get; set;  }
    
    [XmlAttribute(
"name" )]
    
public string  Name {  get; set;  }

    [XmlAttribute(
"alias" )]
    
public string  Alias {  get; set;  }

    
public  List<Tab> Tabs {  get; set;  }
}
 

The Controller

I have a single controller called TabController it has TabXSLT action, it does two things 1) Gets list of tabs from by calling service and then serializes it to XML and 2) Passes that XML to view.

public class  TabController : Controller {
    [ControllerAction]
    
public void  TabXSLT() {
        List<Tab> tabs 
TabService.GetTabs() ;
        
XmlSerializer serilizer 
            new 
XmlSerializer( typeof (List<Tab>)) ;

        
MemoryStream stream  = new  MemoryStream() ;
        
stream.Seek( 0 , SeekOrigin.Begin) ;
        
        
serilizer.Serialize(stream, tabs) ;
        
XmlDocument doc  = new  XmlDocument() ;
        
stream.Seek( 0 , SeekOrigin.Begin) ;
        
doc.Load(stream) ;
        
ViewData[ "tabs" doc ;
        
RenderView( "TabXSLT" ) ;
    
}
    
}
 

View extension for XSLT

MVC Framework does not have concept of the control, Instead UI Helpers and ViewExtensions will enable you to wrap common functionality. I have used view extension in my case to inject additional method in view which will allow me render transformed XML inside my view.

public static class  XSLTViewExtensions {
    
    
public static void  RenderXML( this  ViewPage page
        , XmlDocument xmlDocument
        , 
string  XSLTPath,
        Dictionary<
string , string > xslArgParams) 
    {
        ViewContext context 
page.Html.ViewContext ;
        
XsltArgumentList xslArgs  = new  XsltArgumentList() ;
        if 
(xslArgParams ! = null ) {
            
foreach  ( string  key  in  xslArgParams.Keys) {
                xslArgs.AddParam(key, 
null ,xslArgParams[key]) ;
            
}
        }
        XslCompiledTransform t 
= new  XslCompiledTransform() ;
        
t.Load(XSLTPath) ;
        
t.Transform(xmlDocument, xslArgs, 
            context.HttpContext.Response.Output)
;
    
}

}
 

The View

I have the TabXSLT.aspx view in /Views/Tab folder. Inside my view I am calling extension method by passing XML data that I got from controller and path to XSLT file.

< %@  Page Language ="C#"  
         Inherits
="System.Web.Mvc.ViewPage"  
         MasterPageFile
="~/Views/Shared/Site.Master"  % >

< %@  Import Namespace ="ExperimentsWithMVC.Models"  % >
< %@  Import Namespace ="System.Collections.Generic"  % >
< %@  Import Namespace ="System.Web.Mvc"  % >
< %@  Import Namespace ="System.Xml"  % >
< asp:Content  ID ="Content2"  
             ContentPlaceHolderID
="MainContentPlaceHolder"  
             runat
="server">
    
< h2 > Tabs with XSLT </ h2 >
    
< %  this.RenderXML((XmlDocument)ViewData[ "tabs"]
           , Server.MapPath(
"~/content/tabs.xsl"),null);%>

</ asp:Content >
 

The XSLT

< ?xml  version ="1.0"  encoding ="utf-8"?>
< xsl:stylesheet  version ="1.0"  
                xmlns:xsl
="http://www.w3.org/1999/XSL/Transform"   >
  
< xsl:output  omit-xml-declaration ="yes"   />
  
  <
xsl:template  match ="/">
    
< xsl:apply-templates > </ xsl:apply-templates >
  
</ xsl:template >

  
< xsl:template  match ="Tab">
    
< li >
      
< xsl:value-of  select ="@name"/>
      <
xsl:apply-templates  select ="Tabs"> </ xsl:apply-templates >
    
</ li >
  
</ xsl:template >

  
< xsl:template  match ="Tabs">
    
< ul >
      
< xsl:apply-templates  select ="Tab"   />
    </
ul >
  
</ xsl:template >

  
< xsl:template  match ="ArrayOfTab">
    
< ul >
      
< xsl:apply-templates  select ="Tab"   />
    </
ul >
  
</ xsl:template >
</ xsl:stylesheet >
 

The result

Result is nested unordered list as shown below, each item can have sub item up to nth level.

Parting Thoughts

I have used extension method to inject additional method in my current ViewPage class but it might be more appropriate to group similar UI helper methods in static class, for example you can have AJAXHelper, HTMLHelper, XMLHelper etc.

4 Comments

Comments have been disabled for this content.