Adding Markup to a SharePoint Page

How many times have you had the need to add ASP.NET markup – HTML and server-side control declarations – in a SharePoint page? Yes, there is the Script Editor Web Part and the Content Editor Web Part, but none of these allow you to enter server-side control declarations, just plain HTML, CSS and JavaScript.

So, enter the Markup Editor Web Part!

This web part allows you to enter any markup including server-side controls in a nice configurable web part. Without further delay, here is the code:

   1: [ToolboxItemAttribute(false)]
   2: public class MarkupEditorWebPart : WebPart, INamingContainer
   3: {
   4:     public MarkupEditorWebPart()
   5:     {
   6:         this.ExportMode = WebPartExportMode.All;
   7:     }
   8:  
   9:     [Category("Markup")]
  10:     [Personalizable(true)]
  11:     [WebBrowsable(true)]
  12:     [WebDescription("The markup to render")]
  13:     [DefaultValue("")]
  14:     public String Markup
  15:     {
  16:         get;
  17:         set;
  18:     }
  19:  
  20:     protected override void CreateChildControls()
  21:     {            
  22:         if (String.IsNullOrWhiteSpace(this.Markup) == false)
  23:         {                
  24:             if (SPContext.Current.FormContext.FormMode == SPControlMode.Edit)
  25:             {
  26:                 var edition = String.Empty;
  27:  
  28:                 if (this.WebPartManager.SelectedWebPart == this)
  29:                 {
  30:                     edition = String.Concat(" contenteditable=\"true\" oninput=\"document.querySelector('input[id$=\\'", this.ID, "_ctl03_Markup_EDITOR\\']').value = this.innerHTML.replace(/&lt;/g, '<').replace(/&gt;/g, '>')\"");
  31:                 }
  32:                 
  33:                 this.Controls.Add(new LiteralControl(String.Concat("<div style=\"border: dashed 1px; width: 500px; height: 300px; overflow: auto;\"", edition, ">", this.Markup.Replace("<", "&lt;").Replace(">", "&gt;"), "</div>")));
  34:             }
  35:             else
  36:             {
  37:                 var control = null as Control;
  38:  
  39:                 try
  40:                 {
  41:                     control = this.Page.ParseControl(this.Markup.Replace("&lt;", "<").Replace("&gt;", ">"), true);
  42:                 }
  43:                 catch (Exception ex)
  44:                 {
  45:                     control = new LiteralControl(String.Concat(ex.GetType().Name, ": ", ex.Message, "<br/>", ex.StackTrace));
  46:                 }
  47:  
  48:                 if (control != null)
  49:                 {
  50:                     control.ID = "content";
  51:                     this.Controls.Add(control);
  52:                 }
  53:             }
  54:         }
  55:     }

It will detect if you are in edit mode and display the markup contents as HTML instead of actually rendering the controls. Also, if the web part is being edited, it will allow you to change the markup inline and will persist the edition. If there is an exception, due to invalid markup code, it will instead display the exception message and stack trace.

The magic happens in the ParseControl method, which takes a string containing markup and translates it into server-side controls (HTML is also translated, mind you). It implements INamingContainer to prevent control ID clashes. If you wish, you can register your own registrations, for example, the following is valid markup:

   1: <my:MarkupWebPart runat="server" Markup="&lt;%@ register assembly=&quot;My.Assembly&quot; namespace=&quot;My.Namespace&quot; tagPrefix=&quot;my&quot; %&gt;&lt;my:MyControl runat=&quot;server&quot; /&gt;"/>

Translated markup:

   1: <%@ register assembly="My.Assembly" namespace="My.Namespace" tagPrefix="my" %>
   2: <my:MyControl runat="server"/>

Of course, it is better to use the built-in property editor or the inline version:

image

And the result:

image

As always, hope you find this useful! Winking smile


                             

4 Comments

  • You might wonder why Microsoft does not allow this by default. And also why you have to register your controls as save before they can be added to a page... consider someone to enter the following (pseudo) contents for your web part.

    <script runat="server">
    public MyButtonClick(object sender, eventArgs e) {
    SPSecurity.RunwithElevatedPriviliges(()=>{
    // Make me a site collection admin code...
    });
    }
    </script>
    <asp:button runat="server" click="MyButtonClick">Make me an admin!</asp:button>

    So... hackers will love you for deploying such web part!

  • Hi, Wesley!
    Quite true! :-)
    Just because I explain how it CAN be done, it doesn't mean that it SHOULD be done!
    But, alas, that code won't work, because SharePoint pages are not compiled on demand, meaning, you cannot add methods on demand.
    Thanks for commenting, keep coming by!

  • Good to know that it will not allow to execute any code...

  • Great article… Thanks for your great information, the contents are quiet interesting. Let be explain more on this topic of adding markup to a SharePoint Page.

Add a Comment

As it will appear on the website

Not displayed

Your website