Donnerstag, 26. Juli 2012

How to deploy custom Masterpage by Code

In our current project we had the advice to deploy a masterpage by a feature.

While deploying the new masterpage to the masterpage-gallery was quite simple (and documented), activating the masterpage for the site(s) was not that straightforward. Most instructions one can find on the web are dealing with that by iterating through all webs and setting the masterpage one by one.

But there is a more simple solution to deal with that, at least when then publishing-feature is activated for the site (what is usually the case if one want to be able to change the masterpage).

Just add below code to the corresponding action of the feature receiver (in my case, the feature-receiver is targeting a Web, but it should also work for feature-receiver targeting the site, then you have to use the RootWeb of the site for the below code)

private const string defaultMasterUrl = "~/_catalogs/masterpage/v4.master";
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPWeb web = properties.Feature.Parent as SPWeb;

            if (web != null && PublishingWeb.IsPublishingWeb(web))
            {
                PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
                publishingWeb.CustomMasterUrl.SetValue(customizedMasterUrl, true);
                publishingWeb.MasterUrl.SetValue(customizedMasterUrl, true);
                publishingWeb.AlternateCssUrl.SetValue(CustomCssUrl, true);
                publishingWeb.Update();
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWeb web = properties.Feature.Parent as SPWeb;
            
                 if (web != null && PublishingWeb.IsPublishingWeb(web))
                {
                    PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
                    publishingWeb.CustomMasterUrl.SetValue(defaultMasterUrl, true);
                    publishingWeb.MasterUrl.SetValue(defaultMasterUrl, true);
                    publishingWeb.AlternateCssUrl.SetValue("", true);
                    publishingWeb.Update();
                }
        }
 You don´t have to set all the properties. Usually you just have to set the CustomMasterUrl-property, as the MasterUrl-Property is only used for non-publishing-pages. I just did it to make sure the masterpage is set. Also setting the AlternateCssUrl is optional. The only thing to reminde with the AlternateCssUrl is that the default-Value is an empty string (not a real url as with the masterpage). So if you want to set the CSS-Class back to the default one, set this propety to "". If you want to switch back to the default Masterpage, you have to set the url stated above.

Montag, 2. Juli 2012

How to ajaxify Visual Webpart using Telerik

First of all, you have to init (or reuse if already existing) a RadAjaxManager on the Webpage. You can do it in the <WebPart>.cs-File or (which I recommend if you want to use it in multiple Webparts) you create a custom Extension of WebPart like i did:

   public class TelerikAjaxifiedWebPart : WebPart
    {
        RadAjaxManager ajaxManager;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            SetUpAjaxManagerOnPage();

            EnsureChildControls();
        }

        protected void SetUpAjaxManagerOnPage()
        {
            RadAjaxManager currentAjaxManager = RadAjaxManager.GetCurrent(Page);

            if (currentAjaxManager == null)
            {
                Page.Form.Controls.AddAt(0, AjaxManager);
                Page.Items.Add(typeof(RadAjaxManager), AjaxManager);
            }
        }

        protected virtual RadAjaxManager AjaxManager
        {
            get
            {
                if (ajaxManager == null)
                {
                    ajaxManager = RadAjaxManager.GetCurrent(Page);

                    if (ajaxManager == null)
                    {
                        ajaxManager = new RadAjaxManager() { ID = "RadAjaxManager1" };
                    }
                }

                return ajaxManager;
            }
        }
    }
 Instead of Deriving from "WebPart" you can now derive from your custom Class and be sure that the RadAjaxManager is there and useable.

Now you simply have to add


            RadAjaxManager manager = RadAjaxManager.GetCurrent(Page);
            if (manager != null)
                manager.AjaxSettings.AddAjaxSetting(RadGrid1, RadGrid1, RadAjaxLoadingPanel1);


in the Page_Load Method of your  <UserControl>.cs file. (The if-Condition just to be sure, usually there shouldn´t be null). You have to add all the controls you want to ajaxify in code (because the markup doesn´t know about the AjaxManager-Control). In the Markup of your userControl you simply have to add your AjaxLoadingPanel you want to use for that control as well as your Controls (like the RadGrid in my example).

As you are using ONE RadAjaxManager for the whole Web-Page, you should not use the RadAjaxManager.DefaultLoadingPanel-Property, instead of that use the Overload of the AddAjaxSetting-Method as I did, which is setting the control firing the AjaxRequest, the one which is getting updated and the LoadingPanel that is used. So you can be sure that the right AjaxLoadingPanel is shown during the AjaxRequest.

Note:
I recommend using the same version of the Telerik-Dll in all of your WebParts (at least all Webparts situated on the same site). I encountered troubles with non-working Javascripts, when they are mixed.