Nibble

Archive for the 'api' Category


Storing parseable xml data in a datatype 6

As a follow up on the creating custom umbraco datatypes post I’ll show how to store parseable xml data in a datatype.

By default all propertry values get saved inside a cdata section(in the /data/umbraco.config file, wich has all published content).

Like in this example, a property with the alias test will look like this.

<data alias=”test”><![CDATA[1051;1052;1054]]></data>

But in some cases you would want to override this behavior, especially when you want to store xlm data.

Like the related links datatype in umbraco v4. This will store it’s links as child nodes of the data node.

<data alias=”links”>
        <links>
          <link title=”Same page” link=”http://www.google.com” type=”external” newwindow=”1″ />
          <link title=”Other page” link=”1051″ type=”internal” newwindow=”0″ />
        </links>
</data>

To do this the first step is to create a new class that inherits from umbraco.cms.businesslogic.datatype.DefaultData and overrides the ToXMl method.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
 
namespace umbraco.editorControls.relatedlinks
{
    public class RelatedLinksData : umbraco.cms.businesslogic.datatype.DefaultData
    {
        public RelatedLinksData(umbraco.cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) { }
 
        public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument data)
        {
            if (this.Value != null) {
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(this.Value.ToString());
                return data.ImportNode(xd.DocumentElement, true);
            } else {
                return base.ToXMl(data);
            }
        }
 
    }
}

 

Final step is to alter the class that implements the umbraco.interfaces.IDataType interface (the one with the guid) so that the new class is used instead of the default one. So just change

public override umbraco.interfaces.IData Data
        {
            get
            {
                if (_baseData == null)
                    _baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this);
                return _baseData;
            }
        }

   

To (depending on how the class is named, in this case it’s RelatedLinksData)

public override umbraco.interfaces.IData Data
        {
            get
            {
                if (_baseData == null)
                    _baseData = new RelatedLinksData(this);
                return _baseData;
            }
        }

Creating custom umbraco datatypes 23

A couple of months ago I did a blog post about Creating custom datatypes using the umbraco usercontrol wrapper , I mentioned in that post that there was also an other way of creating a custom datatype. So in this post I’ll try to show you how to create a datatype using the 3 classes way. One of the main differences between this approach and the wrapper is that you’ll be able to have settings for your datatype.

I made a very basic datatype, the char limit datatype I’ll just show how I created that one.

First step would be to create a new project in visual studio (I tend to start a new class library, but web application should also be fine) and reference the necessary umbraco assemblies (so make sure you have those, just download v4).

Here is how the solution explorer looks when the char limit solution is opened.

customdatatype

The umbraco assemblies that needs to be referenced are businesslogic, cms, interfaces, umbraco.Datalayer and umbraco.editorControls (you can find these in the bin directory of umbraco).

As you can notice in the solution explorer the projects contains 3 files.

  • charLimitDataEditor.cs
  • charLimitDataType.cs
  • charLimitPrevalueEditor.cs

These are 3 classes (that’s wy I call it the 3 classes way) implementing the necessary umbraco interfaces.

I’ll start by showing the contents of charLimitDataType.cs

using System;
using System.Collections.Generic;
using System.Text;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType
    {
        private umbraco.interfaces.IDataEditor _Editor;
        private umbraco.interfaces.IData _baseData;
        private charLimitPrevalueEditor _prevalueeditor;
 
        public override umbraco.interfaces.IDataEditor DataEditor
        {
            get
            {
                if (_Editor == null)
                    _Editor = new charLimitDataEditor(Data, ((charLimitPrevalueEditor)PrevalueEditor).Configuration);
                return _Editor;
            }
        }
 
        public override umbraco.interfaces.IData Data
        {
            get
            {
                if (_baseData == null)
                    _baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this);
                return _baseData;
            }
        }
        public override Guid Id
        {
            get { return new Guid(“71518B4E-B1A5-11DD-A22C-8AAA56D89593″); }
        }
 
        public override string DataTypeName
        {
            get { return “Char Limit Textarea”; }
        }
 
        public override umbraco.interfaces.IDataPrevalue PrevalueEditor
        {
            get
            {
                if (_prevalueeditor == null)
                    _prevalueeditor = new charLimitPrevalueEditor(this);
                return _prevalueeditor;
            }
        }
    }
}

 

This is basicly where you give the datatype it’s name and unique id. The name will show up in the rendercontrol dropdown of the edit datatype page.

customdatatype2

Each datatype needs to have a guid, when creating a new datatype make sure you change this to a unique one.

Next is the charLimitPrevalueEditor.cs file

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using umbraco.DataLayer;
using umbraco.BusinessLogic;
using umbraco.editorControls;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue
    {
        #region IDataPrevalue Members
 
        // referenced datatype
        private umbraco.cms.businesslogic.datatype.BaseDataType _datatype;
 
      
        private TextBox _txtLimit;
 
        public charLimitPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType)
        {
 
            _datatype = DataType;
            setupChildControls();
 
        }
 
        private void setupChildControls()
        {
            
            _txtLimit = new TextBox();
            _txtLimit.ID = “txtLimit”;
            _txtLimit.CssClass = “umbEditorTextField”;
 
 
            Controls.Add(_txtLimit);
 
        }
 
 
 
        public Control Editor
        {
            get
            {
                return this;
            }
        }
 
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!Page.IsPostBack)
            {
                
                if (Configuration.Length > 0)
                {
 
                    _txtLimit.Text = Configuration;
 
                }
                else
                {
                    _txtLimit.Text = “100″;
                }
 
 
            }
 
 
        }
 
        public void Save()
        {
            _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), DBTypes.Ntext.ToString(), true);
 
 
            string data = _txtLimit.Text;
 
            SqlHelper.ExecuteNonQuery(“delete from cmsDataTypePreValues where datatypenodeid = @dtdefid”, 
                    SqlHelper.CreateParameter(“@dtdefid”, _datatype.DataTypeDefinitionId));
            SqlHelper.ExecuteNonQuery(“insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,”)”, 
                    SqlHelper.CreateParameter(“@dtdefid”, _datatype.DataTypeDefinitionId), SqlHelper.CreateParameter(“@value”, data));
 
        }
 
        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteLine(“<table>”);
            writer.Write(“<tr><th>Character Limit:</th><td>”);
            _txtLimit.RenderControl(writer);
            writer.Write(“</td></tr>”);
            writer.Write(“</table>”);
        }
 
        public string Configuration
        {
            get
            {
                object conf =
                   SqlHelper.ExecuteScalar<object>(“select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid”,
                                           SqlHelper.CreateParameter(“@datatypenodeid”, _datatype.DataTypeDefinitionId));
 
                if (conf != null)
                    return conf.ToString();
                else
                    return “”;
 
            }
        }
 
        #endregion
 
        public static ISqlHelper SqlHelper
        {
            get
            {
                return Application.SqlHelper;
            }
        }
    }
}

This class is used to setup the datatype settings (something you can’t do when using the wrapper method). In this case it shows a textbox wich will be used to set the character limit. On save it will store this value (using the datalayer) in the database.

customdatatypes3

Last one is charLimitDataEditor.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using umbraco.interfaces;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitDataEditor : System.Web.UI.UpdatePanel, umbraco.interfaces.IDataEditor
    {
 
        private umbraco.interfaces.IData _data;
           
        private string CharLimit;
 
        private TextBox txtCharLimit;
        private Label lblLimitInfo;
 
        public charLimitDataEditor(umbraco.interfaces.IData Data, string Configuration)
        {
            _data = Data;
 
            if (Configuration.Length > 0)
            {
                CharLimit = Configuration;
            }
            else
            {
                CharLimit = “100″;
            }
        }
 
        public virtual bool TreatAsRichTextEditor
        {
            get { return false; }
        }
 
        public bool ShowLabel
        {
            get { return true; }
        }
 
        public Control Editor { get { return this; } }
 
        public void Save()
        {
 
            this._data.Value = txtCharLimit.Text;
            
        }
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
 
 
            txtCharLimit = new TextBox();
 
            txtCharLimit.Text = _data.Value.ToString();
            txtCharLimit.TextMode = TextBoxMode.MultiLine;
            txtCharLimit.Rows = 10;
            txtCharLimit.Columns = 40;
            txtCharLimit.CssClass = “umbEditorTextFieldMultiple”;
            txtCharLimit.Attributes.Add(“onkeyup”, string.Format(“limitChars(this, {1}, ‘{0}’)”, “charlimitstatus” + base.ClientID, CharLimit));
 
           
 
 
            lblLimitInfo = new Label();
            
            lblLimitInfo.Attributes.Add(“id”, “charlimitstatus” + base.ClientID);
            
 
            base.ContentTemplateContainer.Controls.Add(txtCharLimit);
 
            base.ContentTemplateContainer.Controls.Add(new LiteralControl(“<br/>”));
            base.ContentTemplateContainer.Controls.Add(lblLimitInfo);
 
 
            string functionlimit = “function limitChars(textarea, limit, infodiv)”;
            functionlimit += “{”;
            functionlimit += “var text = textarea.value;”;
            functionlimit += “var textlength = text.length;”;
            functionlimit += “var info = document.getElementById(infodiv);”;
 
            functionlimit += “if(textlength > limit)”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You cannot write more then ‘+limit+’ characters!’;”;
            functionlimit += “textarea.value = text.substr(0,limit);”;
            functionlimit += “return false;”;
            functionlimit += “}”;
            functionlimit += “else”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You have ‘+ (limit - textlength) +’ characters left.’;”;
            functionlimit += “return true;”;
            functionlimit += “}”;
            functionlimit += “}”;
 
            ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), “limitChars”, functionlimit, true);
 
        }
      
    }
}

This one is used for the actual datatype dataeditor, so the control you will get in the content section of umbraco.

customdatatypes4

This class inherits from the updatepanel class and implements the umbraco.interfaces.IDataEditor. So on init you need to add the controls, in this case a textbox and a literal (for the info text on character limit) and fetch the saved data. And in the save method you can set what value needs to be saved.

Feel free to experiment with the sourcecode.

Download sourcecode

Creating members programmatically 46

Maybe you want to import a number of members or create a custom registration form. You can use the umbraco api to create, update and delete members

I’ll first create a ‘demo’ member type and add 2 properties.

image

Address (alias address) and City (alias city) both of the type textstring.

Owkey now I am ready to write some c# code that will create a new member.

Before I can access the umbraco member api I need to reference cms.dll and businesslogic.dll (these can be found in the bin folder of umbraco).

Now I’ll add a new usercontrol to my project where a member can register. With a couple of textboxes and a button.

image

So the code I need to execute on the click event of the button is:

first add this at the top

using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.propertytype;

And on the click event:

if (Member.GetMemberFromEmail(txtEmail.Text) == null)
{
                MemberType demoMemberType = new MemberType(1040); //id of membertype ‘demo’
                Member newMember = Member.MakeNew(txtName.Text, demoMemberType, new umbraco.BusinessLogic.User(0));
 
                newMember.Email = txtEmail.Text;
                newMember.Password = txtPassword.Text;
                newMember.LoginName = txtUsername.Text;
 
                newMember.getProperty(“address”).Value = txtAddress.Text; //set value of property with alias ‘address’
                newMember.getProperty(“city”).Value = txtCity.Text; //set value of property with alias ‘city’
 
                newMember.Save();
}
else
{
                //member exists
}

 

First I check if there is no other member with the email address, if the email address is not used yet I can make a new member.

Demo project: download