+1-888-365-2779
Try Now
More in this section
Categories
Bloggers
Blogs RSS feed

Custom widgets migration

by Ivan Georgiev
   Hello everybody. I will give a sneak preview on what's coming in the migration module with this week internal build. In this post I will give an example how you can migrate a custom widget from your 3.7 Sitefinity web site to Sitefinity 4.3. Let’s say we have a simple custom control that shows whether a user is admin or not depending on a given username.

 

IsUserAdmin3xWidget.cs

using System.Security.Principal;
using System.Web.Security;
using System.Web.UI;
using Telerik.Security;
 
namespace MyControls
{
    public class IsUserAdmin3xWidget : Control
    {     
        /// <summary>
        /// Gets or sets the username.
        /// </summary>
        /// <value>The username.</value>
        public string Username { get; set; }
 
        /// <summary>
        /// Checks the valid username.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected virtual bool CheckValidUsername(string username)
        {
            if (string.IsNullOrEmpty(username))
            {
                IPrincipal currentUser = UserManager.GetCurrentUser();
 
                if (currentUser != null)
                {
                    this.Username = currentUser.Identity.Name;
 
                    return true;
                }
 
                return false;
            }
             
            var userManager = new UserManager();
 
            MembershipUser user = userManager.GetUser(username);
 
            if (user == null)
                return false;
 
            return true;
        }
 
        /// <summary>
        /// Determines whether the specified username is admin.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected virtual bool IsAdmin(string username)
        {
            return Roles.IsUserInRole(username, "Administrators");
        }
               
        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("<div>");
 
            if (!this.CheckValidUsername(this.Username))
            {
                writer.Write("<i>Please set a valid user!</i>");
            }
            else
            {
                if (this.IsAdmin(this.Username))
                {
                    writer.Write("<h4>Welcome dear 3.x ADMIN</h4>");
                }
                else
                {
                    writer.Write("<h4>You are NOT 3.x ADMIN. Get out!</h4>");
                }
            }
 
            writer.Write("</div>");
        }
    }
}

 

    For this example we want to migrate this control to a 4.x widget that shows the same thing but if you input a user id. I know that don’t make a lot of sense (I just couldn’t think of a better example :)) but here we want to show a really simple widget migration and also emphasize the “powerful tools” that come out of the box with the migration module.

   The first thing we must do is create a corresponding custom control on the 4.3 web site that we want to migrate to. The main plan is to copy all properties that we want from the 3.7 widget to the 4.3 widget so that the control works as expected. Let’s create a new class library project MyControls4x and add two .cs files IsUserAdminWidget4x.cs and IsUserAdmin4xWidgetBuilder.cs

 

 project structure

 

   Our corresponding 4.3 widget is going to do the same thing as the 3.7 widget but it is going to have a different interface just to make things different. The main difference is that User ID instead of a Username is expected. Remember that the corresponding widget in 4.3 can be a totally different control but in this example we’ll keep it simple.

 

IsUserAdminWidget4x.cs

namespace MyControls4x
{
    public class IsUserAdminWidget4x : Control
    {
        /// <summary>
        /// Gets or sets the user id.
        /// </summary>
        /// <value>The user id.</value>
        public Guid UserId { get; set; }
        /// <summary>
        /// Gets or sets the name of the provider.
        /// </summary>
        /// <value>The name of the provider.</value>
        public string ProviderName { get; set; }
        /// <summary>
        /// Gets or sets the error message.
        /// </summary>
        /// <value>The error message.</value>
        public string ErrorMessage { get; set; }
 
        /// <summary>
        /// Determines whether the specified user id is admin.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        protected virtual bool IsAdmin(Guid userId)
        {
            if (string.IsNullOrEmpty(this.ProviderName))
                this.ProviderName = "OpenAccessMembership37Provider";
 
            UserManager userManager = UserManager.GetManager(this.ProviderName);
 
            User user = userManager.GetUser(userId);
 
            if (user != null)
            {
                if(RoleManager.GetManager("AppRoles").GetRolesForUser(userId).Any(r => r.Name == SecurityConstants.AppRoles.Administrators))
                {
                    return true;
                }
            }
 
            return false;
        }
 
        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("<div style='border: solid 1px #ccc;'>");
 
            if (string.IsNullOrEmpty(this.ErrorMessage))
            {
 
                if (this.UserId == Guid.Empty)
                {
                    writer.Write("<i>Please set a user!</i>");
                }
                else
                {
                    if (this.IsAdmin(this.UserId))
                    {
                        writer.Write("<h4>Welcome dear 4.x ADMIN</h4>");
                    }
                    else
                    {
                        writer.Write("<h4>You are NOT 4.x ADMIN. Get out!</h4>");
                    }
                }
            }
            else
            {
                writer.Write(string.Format("<h4>Error: {0}</h4>", this.ErrorMessage));
            }
 
            writer.Write("</div>");
        }
    }
}

 

   In order to have full control over the widget migration we must plug in into the widget migrating process itself. We must create a widget builder that knows how to deal with our 3.7 widget. After that we must register the builder in the migration module configuration and that’s it.

IsUserAdmin4xWidgetBuilder.cs

namespace MyControls4x.Builders
{
    public class IsUserAdmin4xWidgetBuilder : WidgetBuilderBase
    {
        public override Control ResolveControl(MigrationWidget widget)
        {
            return new IsUserAdminWidget4x();
        }
 
        public override Control Build(MigrationWidget widget)
        {
            IsUserAdminWidget4x myControl = (IsUserAdminWidget4x)base.Build(widget);
 
            MigrationControlProperty usernameProp = widget.Properties.SingleOrDefault(p => p.Name == "Username");
 
            if (usernameProp != null)
            {
                myControl.ProviderName = "OpenAccessMembership37Provider";
 
                UserManager userManager = UserManager.GetManager(myControl.ProviderName);
 
                User user = userManager.GetUser(usernameProp.Value);
 
                if (user != null)
                {
                    myControl.UserId = user.Id;
                }
                else
                {
                    myControl.ErrorMessage = "Can not find user " + usernameProp.Value;
                }
            }
 
            return myControl;
        }
        
    }
}

 

   First we must inherit from WidgetBuilderBase in order to benefit from the built-in functionality that copies all the properties of our 3.7 widget to the corresponding properties of our 4.3 widget (let’s say you don’t want to copy manually style properties like width, height, color and so on). Of course you can decide not to this, it’s up to you. Anyway the Properties property of the MigrationWidget object contains all the properties of the 3.7 widget and you can do whatever you want to do with them. Here we must override two methods

 

Control ResolveControl(MigrationWidget widget);
Control Build(MigrationWidget widget);

 

   The ResolveControl methods must return our 4.3 widget type.  In the Build method we can call
base.Build(widget). This one is copying all the properties from the 3.7 widget object into our new control. After that we can override some of these values if we want to or assign some properties of the 4.3 widget  that are different from these in the 3.7 widget (UserId, ProviderName, ErrorMessage).

   Now we must reference the MyControls4x.dll in the sitefinity web application so that out widget type can be resolved during the migration. Let’s register the builder from Administration -> Settings -> Advanced -> MigrationModule -> Widget builders. First input the 3.7 widget type and then the 4.3 widget builder type.

 

 register builder

 We are ready to go. Our widget works with users and roles, so don’t forget to select them from the migration page.

Leave a comment