SharePoint

5 Comments

In mine last post about my own UserControl WebPart, I ended the article with creating a simple editor part. The only thing I didn't show, was how you really could use an editor part to personalize / customize its WebPart. In this article I will show the code and than explain why I coded it this way. So here is the code of the WebPartEditor, which gives a list of all available user controls in de UserControls directory.

using System;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace My.WebParts.Editors
{
    public class WebPartEditor : BaseEditorPart
    {
        public WebPartEditor()
        {
            this.ID = "WebPartEditor";
            this.Title = "Web Part Properties";
        }
 
        private string[] _errorMessages = null;
        private string[] _propertyDisplayNames = null;
        private string[] _propertyDescriptions = null;
 
 
        protected override void CreateChildControls()
        {
            this.Controls.Clear();
 
            UserControlWebPart part = this.WebPartToEdit as UserControlWebPart;
            this._errorMessages = new string[1] { null };
            this._propertyDisplayNames = new string[1] { "User control to display" };
            this._propertyDescriptions = new string[1] { "UserControl" };
 
            if (string.IsNullOrEmpty(part.UserControlPath) || (!Directory.Exists(HttpContext.Current.Server.MapPath(part.UserControlPath))))
            {
                TextBox userControlTextBox = new TextBox();
                userControlTextBox.ID = part.ID + "UserControlWebPartInput";
                userControlTextBox.AutoPostBack = true;
                userControlTextBox.TextChanged += new EventHandler(userControlTextBox_TextChanged);
 
                userControlTextBox.Text = part.UserControl;
                this.Controls.Add(userControlTextBox);
            }
            else
            {
                DropDownList userControlList = new DropDownList();
                userControlList.ID = part.ID + "UserControlWebPartSelect";
                userControlList.AutoPostBack = true;
                userControlList.SelectedIndexChanged += new EventHandler(userControlList_SelectedIndexChanged);
 
                DirectoryInfo directory = new DirectoryInfo(this.Page.Request.MapPath(part.UserControlPath));
                FileInfo[] files = directory.GetFiles("*.ascx");
 
                if (files.Length > 0)
                {
                    userControlList.DataSource = files;
                    userControlList.DataTextField = "Name";
                    userControlList.DataValueField = "Name";
                    userControlList.DataBind();
                    userControlList.Items[0].Selected = true;
 
                    if (!string.IsNullOrEmpty(part.UserControl))
                    {
                        ListItem item = userControlList.Items.FindByValue(part.UserControl.Substring(part.UserControlPath.Length + 1));
                        if (item != null)
                        {
                            userControlList.Items[0].Selected = false;
                            item.Selected = true;
                        }
                        else
                        {
                            this._errorMessages[0] = string.Format("The file {0} does not exist.", part.UserControl);
                        }
                    }
 
                    if (string.IsNullOrEmpty(part.SelectedUserControl))
                    {
                        part.SelectedUserControl = part.UserControlPath + "/" + userControlList.SelectedValue;
                    }
                }
 
                this.Controls.Add(userControlList);
 
            }
        }
 
        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (this.Page != null)
            {
                this.Page.VerifyRenderingInServerForm(this);
            }
            this.EnsureChildControls();
 
            WebControl[] propertyEditors = new WebControl[] { (WebControl)this.Controls[0] };
            RenderPropertyEditors(writer, this._propertyDisplayNames, this._propertyDescriptions, propertyEditors, this._errorMessages);
        }
 
        private string RequestUserControl(string id, string path)
        {
            if (Array.IndexOf<string>(this.Page.Request.Form.AllKeys, this.UniqueID + "$" + id + "UserControlWebPartInput") > -1)
            {
                return this.Page.Request.Form[this.UniqueID + "$" + id + "UserControlWebPartInput"];
            }
            else
            {
                if (this.Page.Request.Form[this.UniqueID + "$" + id + "UserControlWebPartSelect"] == "None")
                {
                    return null;
                }
                else
                {
                    return path + "/" + this.Page.Request.Form[this.UniqueID + "$" + id + "UserControlWebPartSelect"];
                }
            }
        }
 
        void userControlList_SelectedIndexChanged(object sender, EventArgs e)
        {
            UserControlWebPart webPart = this.WebPartToEdit as UserControlWebPart;
 
            webPart.SelectedUserControl = RequestUserControl(webPart.ID, webPart.UserControlPath);
        }
 
        void userControlTextBox_TextChanged(object sender, EventArgs e)
        {
            UserControlWebPart webPart = this.WebPartToEdit as UserControlWebPart;
 
            webPart.SelectedUserControl = RequestUserControl(webPart.ID, webPart.UserControlPath);
        }
 
        public override bool ApplyChanges()
        {
            UserControlWebPart webPart = this.WebPartToEdit as UserControlWebPart;
 
            this._errorMessages = new string[1] { null }; 
            webPart.UserControl = RequestUserControl(webPart.ID, webPart.UserControlPath);
            webPart.SelectedUserControl = webPart.UserControl;
            webPart.LoadUserControl();
 
            return true;
        }
 
        public override void SyncChanges()
        {
        }
 
    } 
}

In the AboutEditor I only added the method RenderContents, which is responsible for rendering the about info as content. Nothing fancy in the code and everything looked rather simple. In this control I will not only add the method RenderContents but also CreateChildControls. The last method is needed, because I'm not only rendering content, I'm creating events as well. As I said before "To know how you should create a good WebPart you must be very confident with the Web load- and event handlers model." Because this is hard to explain, I'm not discussing these principles here.

The first thing which is different comparing to the other editor part. It doesn't inherit from EditorPart but it inherits from BaseEditorPart. This class is an abstract class and has some default implementations for rendering properties. Another difference is the reference between the WebPart and the EditorPart. This can be accomplished by the following line of code.

UserControlWebPart part = this.WebPartToEdit as UserControlWebPart;

CreateChildControls
This method will create the child controls for the editor part. In this method I will detect if the given user controls directory exists and display the user control files in it in a combobox. When it can't find the directory it will give the user a textbox to type the full path to the user control. I used the CreateChildControls method because I want to some eventhandling as well. In this method I add to either of the selected choice an event which will be called after the value of the user control to display changes.

RenderContents
For the rendering I wrote my self a method named RenderPropertyEditors which is stored in the base class BaseEditorPart. This method handles all properties and depending on their type it will be rendered as TextBox (String, DateTime), DropDownList (Enum) or a RadioButton (Boolean). By doing this I can reuse the code for my other editor part which will be displaying the properties of a user control.

RequestUserControl
This method requests the form which UserControl is given or selected by the user. This depends on if the user types the user control in a textbox or selects it from a combobox.

ApplyChanges
Saves the values in an EditorPart control to the corresponding properties in the associated WebPart control. When the values are applied, it loads the selected user control. I set the WebBrowsable property of the UserControl property to false and added a new property SelectedUserControl. The UserControl property will be stored, so the next time the WebPart is rendered it uses te stored UserControl. The SelectedUserControl is only used for the editor parts. By doing so I can eventually reload the selected UserControl for accessing its properties without rendering it to the browser. 

[WebBrowsable(false), Personalizable(true)]
public string UserControl
{
  get
  {
    return this._userControl;
  }
  set
  {
    this._userControl = value;
  }
}
 
[WebBrowsable(false)]
public string SelectedUserControl
{
  get
  {
    string editorUserControl = ViewState["EditorUserControl"] as string;
    if (string.IsNullOrEmpty(editorUserControl))
    {
      return UserControl;
    }
    else
    {
      return editorUserControl;
    }
  }
  set
  {
    ViewState["EditorUserControl"] = value;
  }

When using this WebPart in my test portal it will give the image below.


UserControl in ASP.NET 2.0 Portal using my own UserControl WebPart

As you can see in the image, I now have create my an editor part which customizes  / personalizes a WebPart.

Summary
Hopefully you're even more impressed as I am, because it's so simple to create such a powerfull EditorPart. Microsoft did a great job and made it possible with the ASP.NET 2.0 Framework to create simple but cool WebParts. In the next part I'm going to create another editor part which will display the properties of the user control.

2 Comments

In this fourth article about my own UserControl WebPart I will explain how a WebPart can use its own editor parts. Editor parts are very handy when it comes to customizing / personalizing and categorizing the WebPart. In this blog I will only show you how to add an editor part and how to use it to display some common info about the WebPart.

When implementing a editor part you have to do the following steps.

Step 1 Create a class which inherits from EditorPart

namespace My.WebParts.Editors
{
    public class AboutEditor : System.Web.UI.WebControls.WebParts.EditorPart
    {
 
    }
}

Step 2 Implements its methods

namespace My.WebParts.Editors
{
    public class AboutEditor : System.Web.UI.WebControls.WebParts.EditorPart
    {
        public override bool ApplyChanges()
        {
            return true;
        }
 
        public override void SyncChanges()
        {
        }
 
    }
}

Since I don't use the editor part to edit my WebPart I'm not obligated to add any code to the ApplyChanges (Saves the values in an EditorPart control to the corresponding properties in the associated WebPart control.) and SyncChanges (Retrieves the property values from a WebPart control for its associated EditorPart control.) methods.

Step 3 Create a useful editor part

using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
 
namespace My.WebParts.Editors
{
    public class AboutEditor : EditorPart
    {
        public AboutEditor()
        {
            this.ID = "AboutEditor";
            this.Title = "About";
        }
 
        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.WriteLine("UserControl WebPart");
            writer.WriteBreak();
            writer.WriteLine("Version " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
            writer.WriteBreak();
            writer.WriteBreak();
 
            writer.WriteLine("Created by: ");
            writer.AddAttribute(HtmlTextWriterAttribute.Href, "http://bloggingabout.net/blogs/mglaser");
            writer.AddAttribute(HtmlTextWriterAttribute.Target, "_blank");
            writer.RenderBeginTag(HtmlTextWriterTag.A);
            writer.Write("Mike Glaser");
            writer.RenderEndTag();
            writer.WriteBreak();
            writer.WriteBreak();
 
            writer.AddAttribute(HtmlTextWriterAttribute.Href, "http://www.class-a.nl");
            writer.AddAttribute(HtmlTextWriterAttribute.Target, "_blank");
            writer.RenderBeginTag(HtmlTextWriterTag.A);
            writer.Write("www.class-a.nl");
            writer.RenderEndTag();
        }
 
        public override bool ApplyChanges()
        {
            return true;
        }
 
        public override void SyncChanges()
        {
        }
 
    }
}

Step 4 Extend your WebPart class to implement the IWebEditable interface

public class UserControlWebPart : WebPart, IWebEditable

Step 5 Implement the CreateEditorParts method and use the editor part

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
 
using My.WebParts.Editors;
 
namespace My.WebParts
{
    public class UserControlWebPart : WebPart, IWebEditable
    {
        public UserControlWebPart()
        {
            this._userControlPath = "/UserControls";
        }
 
        private UserControl _control;
        private string _userControlPath;
        private string _userControl = string.Empty;
 
        [WebBrowsable(false), DefaultValue("/UserControls")]
        public string UserControlPath
        {
            get
            {
                return this._userControlPath;
            }
            set
            {
                this._userControlPath = value;
            }
        }
 
        [WebBrowsable(true), Personalizable(true)]
        public string UserControl
        {
            get
            {
                return this._userControl;
            }
            set
            {
                this._userControl = value;
            }
        }        
 
        protected internal void LoadUserControl()
        {
            if (!string.IsNullOrEmpty(this._userControl))
            {
                base.CreateChildControls();
                this.Controls.Clear();
                this._control = (UserControl)Page.LoadControl(this._userControlPath + "/" + this._userControl);
 
                this.Controls.Add(this._control);
            }
        }
 
        protected override void CreateChildControls()
        {
            try
            {
                LoadUserControl();
            }
 
            catch (Exception ex)
            {
                ex.ToString();
            }
        }
 
        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            List<EditorPart> editors = new List<EditorPart>();
            editors.Add(new AboutEditor());
            return new EditorPartCollection(editors);
        }
 
   }
}

When using this WebPart in my test portal it will give the image below.


UserControl in ASP.NET 2.0 Portal using my own UserControl WebPart

As you can see in the image, I now have create my first editor part.

Summary
I only showed how to use an editor part, but I didn't show how to customize / personalize a WebPart using this editor part. In the next parts I will create the two other editor parts. One article will be about selecting the user control, the other about displaying properties of it.

Since my colleagues Dennis and Alex are writing articles by the minute, it was time for me to do the same. Dennis is writing some very interesting articles about WCF (Windows Communication Foundation) and Alex is doing the same about Unit Testing in Visual Studio .NET 2005.

Unfortunately I wasn't able to write about my own UserControl WebPart for a long time. One thing was, I had to so much other stuff (training, consult, family & friends), it didn't give me much spare time. An other thing was, I wasn't able to copy my code formatted, as I like it, from my SharePoint development environment running on a VPC. I had to spend some time on this problem too.

In this third part I'm going to write about creating an ASP.NET 2.0 WebPart which dynamically loads a UserControl and can be used in a SharePoint or an ASP.NET 2.0 Portal. Before I start I will mention I haven't coded any .NET language for over a year now. So if you have any improvements or comments, please let me know. As I described in my first article about WebParts, to use an ASP.NET 2.0 WebPart in SharePoint you don't have to do a lot of things. One thing which is really important is to make sure you will inherit from the correct WebPart.

using System;
 
namespace Sample.TestWebParts
{
    public class Class1 : System.Web.UI.WebControls.WebParts.WebPart
    {
    }
}

When doing so you could stop here, but it is nice when your WebPart becomes rendered it shows some information. In this example I'll show code which displays 'Superb' as a text when the WebPart hits the page.

using System;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
 
namespace Sample.TestWebParts
{
    public class Class1 : WebPart
    {
        protected override void CreateChildControls()
        {
            Label control = new Label();
            control.Text = "Superb";
 
            this.Controls.Add(control);
        }
 
    }
}

or

using System;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
 
namespace Sample.TestWebParts
{
    public class Class1 : WebPart
    {
        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("Superb");
        }
    }
}

To know how you should create a good WebPart you must be very confident with the Web load- and event handlers model. Because this is hard to explain, I'm not discussing these principles here. I hope you understand this is the reason why I want to build my own UserControl WebPart. With this WebPart you can concentrate on business problems instead of technical problems. In mine last article I explained how I like to use a UserControl and where it should be stored. So for displaying it dynamically you can use this code.

using System;
using System.ComponentModel;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
 
namespace My.WebParts
{
    public class UserControlWebPart : WebPart
    {
        public UserControlWebPart()
        {
            this._userControlPath = "/UserControls";
        }
 
        private UserControl _control;
        private string _userControlPath;
        private string _userControl = string.Empty;
 
        [WebBrowsable(false), DefaultValue("/UserControls")]
        public string UserControlPath
        {
            get
            {
                return this._userControlPath;
            }
            set
            {
                this._userControlPath = value;
            }
        }
 
        [WebBrowsable(true), Personalizable(true)]
        public string UserControl
        {
            get
            {
                return this._userControl;
            }
            set
            {
                this._userControl = value;
            }
        }        
 
        protected internal void LoadUserControl()
        {
            if (!string.IsNullOrEmpty(this._userControl))
            {
                base.CreateChildControls();
                this.Controls.Clear();
                this._control = (UserControl)Page.LoadControl(this._userControlPath + "/" + this._userControl);
 
                this.Controls.Add(this._control);
            }
        }
 
        protected override void CreateChildControls()
        {
            try
            {
                LoadUserControl();
            }
 
            catch (Exception ex)
            {
                ex.ToString();
            }
        }
 
   }
}

When using this WebPart in my test portal it will give the image below.


UserControl in ASP.NET 2.0 Portal using my own UserControl WebPart

As you can see in the image, all properties which where supplied by the UserControl are disappeared. I have to write my own editor part, which supply the properties by reflection.

Summary
I enjoyed writing some extra info about my own UserControl WebPart. In the next part I will explain how to use editor parts and how they fill into my WebPart.

2 Comments

You had to wait some time, but the team finally delivered the Visual Studio 2005 extensions for Windows SharePoint Services 3.0. This tools are for developing custom SharePoint applications: Visual Studio project templates for Web Parts, site definitions, and list definitions; and a stand-alone utility program, the SharePoint Solution Generator.

This Community Technology Preview (November CTP) of the Visual Studio 2005 Extensions for Windows SharePoint Services contains the following tools to aid developers in building SharePoint applications:

Visual Studio 2005 Project Templates

  • Web Part
  • Team Site Definition
  • Blank Site Definition
  • List Definition

Visual Studio 2005 Item Templates (items that can be added into an existing project)

  • Web Part
  • Custom Field
  • List Definition (with optional Event Receiver)
  • Content Type (with optional Event Receiver)
  • Module

 

SharePoint Solution Generator

  • This stand-alone program generates a Site Definition project from an existing SharePoint site. The program enables developers to use the browser and Microsoft Office SharePoint Designer to customize the content of their sites before creating code by using Visual Studio.

4 Comments

As discussed in my first post Building my own UserControl WebPart part I I'll extend the class model for the UserControl WebPart project. Besides the methods, all fields and properties will be added to those classes too. In this part I discuss why they are added and where they are used for. At the end a screendump is added of the sample ASP.NET 2.0 portal using a UserControl as a WebPart. This UserControl will be the sample UserControl to use in my solution during all my parts.

 
Class Diagram 

All classes are described below:

UserControlWebPart

  • Properties
    • public string UserControlPath
      Path to the UserControl folder.
    • public string UserControl 
      FileName of the UserControl to load.
    • protected internal Hashtable UserControlProperties
      Stores values of the UserControl properties in a Hashtable. This property is protected internal cause it needs to be called from EditorPart controls.
    • object IWebEditable.WebBrowsableObject
      Gets a reference to the WebPart control to enable it to be edited by custom EditorPart controls.
  • Methods
    • protected override void CreateChildControls
      Composition-based implementation to create any child controls. This method will call LoadUserControl.
    • protected internal void LoadUserControl
      Loads the UserControl dynamically to the page. This methods is protected internal cause it needs to be called from EditorPart controls when properties changes.
    • EditorPartCollection IWebEditable.CreateEditorParts
      A collection of custom EditorPart controls associated with this WebPart control.

AboutEditor

  • Methods
    • protected override void RenderContents
      Renders information about this WebPart control.

BaseEditorPart

  • Methods
    • public void RenderPropertyEditors
      Renders all properties of the UserControl in grid formatted table.

WebPartEditor

  • Methods
    • protected override void CreateChildControls
      Composition-based implementation to create any child controls. Creates a DropDownList when the UserControlPath exists, else TextBox.
    • protected override void RenderContents
      Renders the properties of the EditorPart control using RenderPropertyEditors of the base class.
    • void userControlList_SelectedIndexChanged
      Handles the SelectedIndexChanged event when an user changes the value of the DropDownList. Reloads the selected UserControl to show the properties.
    • void userControlTextBox_TextChanged
      Handles the TextChanged event when an user changes the value of the TextBox. Reloads the given UserControl to show the properties.
    • public override bool ApplyChanges
      Stores the selected UserControl.

UserControlEditor

  • Properties
    • private ArrayList EditorControls
      A list of all EditorControls of all editable properties.
  • Methods
    • protected override void CreateChildControls
      Composition-based implementation to create any child controls.
    • protected override void RenderContents
      Renders the properties of the EditorPart control using RenderPropertyEditors of the base class.
    • private Control CreateEditorControl
      Creates a TextBox, DropDownList or CheckBox depending on the type of the property.
    • private object GetEditorControlValue
      Gets the value given by the user in the WebEditorZone.
    • private PropertyDescriptorCollection GetEditableProperties
      Checks whether a property in the UserControl contains the WebBrowsable attribute.
    • private string GetDescription
      Gets the description of a property using the WebDescription attribute.
    • private string GetDisplayName
      Gets the displayname of a property using the WebDisplayName attribute.
    • public override bool ApplyChanges
      Stores all property values in UserControlProperties Hashtable.

Constructors and methods not used are not mentioned.

In ASP.NET 2.0 you can use a web user control (ascx) as web part because of the ASP.NET 2.0 GenericWebPart class. If the class implements the IWebPart interface it has some extra properties used in webpart Editor. The GenericWebPart control exists to provide a run-time wrapper for server controls that are not WebPart controls, so that such controls can be used in Web Parts pages and applications.

 
UserControl in ASP.NET 2.0 Portal using the GenericWebPart

Unfortunately, this GenericWebPart is not available SharePoint 2007. That's why I build my own UserControl WebPart. This WebPart Control needs to be more dynamic than the GenericWebPart class, cause it needs to load UserControls from in- or external Assemblies using in-line code or code-behind files.


UserControl in ASP.NET 2.0 Portal using the My UserControl WebPart

What I like to accomplish is to dynamically load this usercontrol and still are able to modify all UserControl properties which has WebBrowsable attribute.


UserControl in ASP.NET 2.0 Portal using the GenericWebPart

In the next part I'll will complete the aboutEditor and add code to the UserControlWebPart to dynamically load a control and add the editors to the Editor Zone.

22 Comments

Yesterday I was rewriting my two-day Reporting Services 2005 course to a three-day course. The previous times I gave this course I ran out of time and couldn’t explain every module in depth. So I decided to extend the course and add an extra module about Implementing Business Logic with MDX. This new module contains information about using Analysis Services Cubes to create reports. I’ll focus on matrix and graphics data regions as well. Besides adding a new module I was adding some content to the other ones. When I was extending the Programming Reports module I found out about SQL Server 2005 SP2.

As you know, we already have SharePoint Web Parts, and they work well. However, Microsoft will include much deeper integration with WSS/OS in SP2. Some limitations of the current WebParts are:

  • Separate content stores;
  • Different security models;
  • Different management UI;
  • No filter web parts.

The reporting team did a great job to fully integrate Reporting Services into WSS/OS. After installing SP2, you can run Reporting Services in "native mode" (like it’s today), or "SharePoint integration mode". The integration mode will enable publishing, viewing, and management of rich reports.

 
Integration Architecture

Management
SQL Server 2005 SP2 is installed on a report server along with the SharePoint Object Model (farm install). The Reporting Services feature pack is installed in WSS “v3” and the Report Server web service URL is registered with WSS farm. To create a new Report Server database in “SharePoint Integration mode” you can use the Reporting Services Configuration Tool. In SP2, the tool has been modified to include some additional UI to do this work.

Note: Unfortunately it’s not possible to migrate from existing SQL Server 2005 Reporting Services (SSRS) installations.

Using “SharePoint Integration mode”, most of the objects you're used to store in reportserver database are instead stored in SharePoint database. Some functionality like scheduling, subscriptions, snapshots and caching are still stored in the reportserver database. Lets say they implemented every feature of Reporting Services in SQL Server 2005 Express in WSS.

All other objects like reports, data sources, and report models are published to SharePoint document libraries. When a report is selected in WSS, the report viewer Web Part calls the report server API to process and render the report. Users can manage properties and subscribe to reports through WSS UI which calls the RS SOAP API. New report server delivery extension allows for rendered reports to be delivered to WSS document libraries (including Report Center). Another nice thing is all cool features of SharePoint like versioning, collaboration and workflows are now available to all objects.

Note: Report Manager (Web UI / Management Studio) is not supported in “SharePoint Integration Mode” and it's not possible to run SSRS in both modes at the same time.

Another major change is security. All permissions are set within WSS and will give you a consolidated place to manage security. For Example when using Team Foundation Server you now have to set rights in TFS, SharePoint and Reporting Services. I hope tools like this will fully integrate with SharePoint as well. The design tools (Report Designer, Report Builder, Model Designer) are also updated to work with WSS.

Note: It looks like data-driven subscriptions is cut out. Normally this is really powerful feature. So I hope the Microsoft team is aware of this and will soon add it to the “SharePoint Integration mode”.

SharePoint User Interface
Viewing reports while in integrated mode is like any normal webpage in SharePoint. You can use the Report Viewer WebPart to show a report in full page view or on Web Part Pages. This WebPart wraps the ReportViewer ASP.NET Viewer Control and handles report rendering calls to report server. Besides handling it will give you all the properties by using its own EditorPart and verbs. The properties can be devided by:

  • Report: ReportPath, HyperlinkTarget
  • View: AutoGenerateTitle, AutoGenerateDetailLink, ToolBarMode, ParametersMode, ParametersAreaWidth, DocumentMapMode, DocumentMapAreaWidth
  • Parameter: Default Values

At last is will also support Filter Consumer and Row Consumer interfaces for specifying report parameter values via filter Web Parts. This way you can slice Excel Workbooks and Reports on a single Web Part page. Superb.


Document Library UI


Viewing Reports (Full Screen)


Report Properties (Parameters)

   
Report Viewer Web Part

Other important changes
Integration will give you new report server SOAP and WMI interfaces endpoints.
The SOAP Proxy is now installed in WSS to support firewall deployment.
Most API’s are mapped to SharePoint object model calls. For example, ListChildren returns items in the content database.
File Extensions are mapped into Report Server types (Report / Data Source / Model / Resource)
Reporting Services security role definitions are replaced with SharePoint principles. CreateRole, DeleteRole, GetRoleProperties, SetRoleProperties are all removed

Summary
I think the the team did a great job. They have said they will deliver a version with no differences between the native and the integrated mode, but it won’t happen in SP2. The integrated mode will be very populair with customers deciding to use SharePoint and are using less complex solutions. More complex solutions using subscriptions and lots of administration will still use native mode.

2 Comments

Today I started creating my own UserControl WebPart project. I decided to start from sratch en use the Class Desinger of Visual Studio to model the diagram. I've created five classes where four of them are used for editing the WebPart. Ofcourse I modeled an AboutEditor which inherits from System.Web.UI.WebControls.WebParts.EditorPart to create a top part where the name, version and the author of the control is added.


The other two editors are used to display the properties of the WebPart itself and the UserControl selected / given by the user. Both of the editors inherits form the base class BaseEditorPart which will render the properties and their display names.


Class Diagram


The UserControlWebPart class which inherits from System.Web.UI.WebControls.WebParts.WebPart is used to load the UserControl selected / given by the user. It's very easy to load a control dynamically. The following method will do the trick.

protected override void CreateChildControls()
{
    try
    {
        base.CreateChildControls();
        this.Controls.Clear();
        this._control = (UserControl)Page.LoadControl(this.UserControl);
    }
    catch (Exception ex)
    {
        ex.ToString();
    }
}


Besides this, it will also implement the System.Web.UI.WebControls.WebParts.IWebEditable interface. This interface enables you to associate custom EditorPart controls with a server control--such as a WebPart control, a user control, or a custom server control. The EditorPart controls are contained with an EditorZone control, and this zone with its editing controls provides end users with a user interface (UI) for modifying properties, appearance, and behavior on the associated WebPart control.


In the next part I'll will model the public methods in the classes. I also give a screendump of the sample ASP.NET 2.0 portal using a UserControl. This UserControl will be the sample UserControl to use in my solution during all my parts.

6 Comments

I recently checked a couple of blogs about using dynamically loaded User Controls. Some of the blogs mentioned SmartPart v2 (aka SonOfSmartPart) to load ASP.NET 2.0 User Controls. This WebPart is completely targeted to SharePoint 2003, but it will remain working in MOSS 2007. When creating new Web Parts, you have the option of creating Web Parts that inherit from System.Web.UI.WebControls.WebParts.WebPart (recommended) or Microsoft.SharePoint.WebPartPages.WebPart (inherits from). The Windows SharePoint Services WebPart class exists primarily for the purpose of backward compatibility (Web Parts continue to work in Windows SharePoint Services 3.0 without modification), and to provide a small set of features that are not available in the other class.


Besides the targeting it's also not possible to use this Web Part in a ASP.NET 2.0 Portal. I know it's really easy to drag and drop a User Control in ASP.NET 2.0 Portal, but I also want to have this ability in MOSS 2007. Furthermore I like to have an option to add User Controls dynamically (not included in my Portal project). Scott Guthrie has written some astonishing info in one of his blogs about whether it will be possible to host Web Parts built as ASP.NET 2.0 User Controls within SharePoint 2007. He checked with the SharePoint team, and they told him that this will be a supported scenario via an additional component you add to SharePoint and that they'll have a Whitewater and sample on how to-do this published later this year.


I couldn't imagine this option wasn't available in MOSS 2007 and that the SharePoint team will give a additional component only later this year. As Joris Poelmans wrote in his blog Usercontrols (ascx), webparts and SharePoint 2007, it isn't that hard to dynamically load a User Control. Reading this blog I decided to write my own SmartPart fully ASP.NET 2.0 compatible. I heard some rumors that Jan Tielens is writing a Revival of SmartPart too, but I couldn't wait that long.


I'm starting a series of posts about my own UserControl WebPart. The goal of the series is to create a DLL which is public to everyone who wants to use it. While other articles sometimes are too long, I want to keep them very short. That way you're able to read them before your workday begins or perhaps just before you shut down. 🙂


From every post I'll refer to this post and I'll keep an index here so you can easily find your way.

Complete index


  1. part I (Startup project)
  2. part II (Class Diagram and test UserControl project)
  3. part III (WebPart project)
  4. part IV (About EditorPart, displaying a info about the WebPart)
  5. part V (WebPart EditorPart, selecting a UserControl)
  6. part VI (UserControl EditorPart, discovering properties of UserControl)
  7. part VII (Consumer / Provider)

I try to keep you informed and eventually will post my UserControl WebPart as a DLL.