Thursday, February 4, 2010

ASP.NET Web PartsAS


ASP.NET Web Parts controls are an integrated set of controls for creating Web sites that enable end users to modify the content, appearance, and behavior of Web pages directly in a browser. The Web Parts control set consists of three main building blocks:  
  1. Personalization,
  2. User interface (UI) structural components, and
  3. Actual Web Parts UI controls.

  1. Personalization: Web Parts use a Personalization Provider.  This is so users that visit the site get a different perspective, depending on their personalization.  One user might want a red background while another might want blue.  This is their personalization, and it is stored in a database. By default, Web Parts are configured to use Sql server 2005 Express edition. For another version of Sql server 2005, there are few things which we must do to make it work smoothly.

First of all, we need to create a personalization database named aspnetdb. By default, Web Parts look for this database to keep the user personalization information. In order to do this, we must use the 'aspnet_regsql.exe' wizard.  Browse out to '%windir%\Microsoft.NET\Framework\' and run this command.  Once the wizard is up, choose to 'Configure SQL Server for application services'.  Select the correct server name (if using a named instance, be sure to include the server and named instance, such as 'fileserver\sql2k5instance').  If using SQL Server authentication, put in your username and password.  Select the database that will serve as your personalization database.  Now database is set up for membership and personalization.
   
  Now add a connection string to Web.config file with the key name ‘localSqlServer’. 
 <connectionStrings>
          <remove name="LocalSqlServer"/>
          <add name="LocalSqlServer" connectionString="Server=G01BR1P264; Database=aspnetdb; Integrated Security=SSPI; MultipleActiveResultSets=true;"providerName="System.Data.SqlClient"/>
    connectionStrings> 
   
  The name of the connection string is important, as Web Parts look by default for a connection string named 'LocalSqlServer'.  The data source is equally important and should reflect our database instance (be sure to include the name if using a named instance).  Since I have set up the 'aspnetdb' database as my personalization database, this will be what I use as the Initial Catalog.  Also, since only SQL Server 2005 Express Edition supports User Instances, I will set this property to 'false'. 
    Apart from these, either you have to user Window Authentication or Form Authentication. 
    Window Authentication: To use Window Authentication, Add the following to the Web.config. 
   <authentication mode="Windows">authentication> 
     Also, open the Inet Manger of your server, point to your website and open properties. Under the Directory security tab click on ‘Edit’ Anonymous access and Authenication control. 

Your browser may not support display of this image.


     Uncheck the Anonymous Access and check mark the integrated Windows authentication.  
Form Authentication: To use Form Authentication, Add the following in the web.config 
<authentication mode="Forms">
<forms name=".ASPXAUTH" loginUrl="Login.aspx" defaultUrl="Home.aspx" cookieless="UseUri" />
      authentication> 
Here loginUrl will be your login page name and defaultUrl will be your Home Page. Cookieless is the option property,  if false, a cookie will be saved to a user machine.
Now we have to user the FormAuthentication class and it’s static member to add the user as authenticated. 
For example: suppose we have another database where we keep the user list and their login credentials. 
Add the connection string information of this database also to web.config. During login process, check the user input against the duser credentials store in a database table. If it is true then redirect user to home page using  
FormsAuthentication.RedirectFromLoginPage(UserName, false); 
This is a static method of the FormAuthentication Class which add the user to authenticated list and redirect to default page mentioned in a web.config.
Now we can whether user has been authenticated or not by 
HttpContext.Current.User.Identity.IsAuthenticated Which return true in case of authenticated user. 
There is one another method which is used to make user log out. 
FormsAuthentication.SignOut(); 
  1. User interface (UI) structural components: These components provide the core structure and services need by the Web Parts Control. Every page which hosts the web part must have these components. One of the most important UI components is WebPartManger, which has a critical task of coordination all web parts on a page. It also tracks and controls the different display modes a page can be in, such as browse, connect, edit, or catalog mode, and whether personalization changes apply to all users or to individual users. Finally, it initiates and tracks connections and communication between Web Parts controls.
The second kind of UI structural component is the zone, act as layout managers on a Web Parts page. They contain and organize controls that derive from thePart class (part controls), and provide the ability to do modular page layout in either horizontal or vertical orientation. Zones also offer common and consistent UI elements (such as header and footer style, title, border style, action buttons, and so on) for each control they contain; these common elements are known as the chrome of a control. Several specialized types of zones are used in the different display modes and with various controls.  
  1. Actual Web Parts UI controls: All the Web Parts controls are derived from the Part Class.


Web Parts controlDescription
WebPartManagerManages all Web Parts controls on a page. One (and only one) WebPartManager control is required for every Web Parts page.
CatalogZoneContains CatalogPart controls. Use this zone to create a catalog of Web Parts controls from which users can select controls to add to a page.
EditorZoneContains EditorPart controls. Use this zone to enable users to edit and personalize Web Parts controls on a page.
WebPartZoneContains and provides overall layout for the WebPart controls that compose the main UI of a page. Use this zone whenever you create pages with Web Parts controls. Pages can contain one or more zones.
ConnectionsZoneContains WebPartConnection controls, and provides a UI for managing connections..
WebPart(GenericWebPart)Renders the primary UI; most Web Parts UI controls fall into this category.For maximum programmatic control, you can create custom Web Parts controls that derive from the base WebPart control.
You can also use existing server controls, user controls, or custom controls as Web Parts controls. Whenever any of these controls are placed in a zone, the WebPartManager control automatically wraps them with GenericWebPart controls at run time so that you can use them with Web Parts functionality.
CatalogPartContains a list of available Web Parts controls that users can add to the page.
WebPartConnectionCreates a connection between two Web Parts controls on a page. The connection defines one of the Web Parts controls as a provider (of data), and the other as a consumer.
EditorPartServes as the base class for the specialized editor controls.
EditorPart controls(AppearanceEditorPart, LayoutEditorPart, BehaviorEditorPart, and PropertyGridEditorPart)Allow users to personalize various aspects of Web Parts UI controls on a page.


Creating Web Parts: Below is the step wise process to create  web parts on a page. 
  1. Drag and drop a WebPartMenuManager control from the Toolbox (under the Web Parts tab) onto the Web Form.
  2. Further we need to create  Web Part Zone which anchors the Web part. We can place any number of Web Part Zone depending on our need.
  3. Now we can add any control, user control or custom control inside the Web part zone.
  4. Web parts pages can also contain web parts that are not visible by default. The user can add these parts to the page through a web part catalog. A web part catalog allows user to define optional content not visible to user by default.
    To provide a catalog on the page, we need to add a special zone control, called the CatalogZone, to a page. In this zone, We can add catalog parts that provide different kinds of controls.
  5. In addition to allowing users to personalize the layout and visibility of web parts on a page, you can also let users edit properties of each web part. Every part has a set of default properties that can be personalized. Each control can also provide additional properties to be personalized.

    To allow editing of control properties, you need to add a special zone control, called the Editor Zone, to the page. To this zone, you can add one or more editor parts. The following editor parts are provided:

    • The Appearance Editor Part control allows users to edit the visual   appearance of a web part.
    • The Behavior Editor Part control allows users to edit behavior properties of a web part.
    • The Layout Editor Part control allows users to edit the layout of a web part.
    • The Property Grid Editor Part control displays a property grid that allows users to edit custom personalize able properties for a web part.
Web Parts also provide various modes to control user interaction. These include the following:
  • Browse: This is the default mode; it is the standard way Web pages are used.
  • Design: Allows users to drag and drop Web Parts within a page. This mode is always available.
  • Edit: Allows users to drag and drop Web Parts, as well as select Edit to control various aspects of a control. There are various Edit-based controls available to provide this functionality. This is an extension of the Design mode.
  • Catalog: Allows users to add additional controls via a defined list. The CatalogZone control provides this functionality.
  • Connect: Allows users to manually establish connections between controls. This feature is available via the Connection Zone control.

We can achieve this by writing code like below respectively: 
    WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode; 
    WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode; 
    WebPartManager1.DisplayMode = WebPartManager.EditDisplayMode ; 
    WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode ; 
    WebPartManager1.DisplayMode = WebPartManager.ConnectDisplayMode ; 
User Role: By default, all authenticated user has the right to change the layout of the page and edit the web parts, which is further persisted in a database.
            If we are using personalization all the changes made will only be visible to that particular user who made those changes, because when user logs in it enters into ” PersonalizationScope.User ” and the changes will not be visible to anyone else. What to do if we have above mentioned scenario in which only one user say “Admin” can make changes and it will be visible to everyone.
  To achieve this functionality Add the following code to Page Load Method 
if(WebpartManager1.Personalization.Scope==PersonalizationScope.User)
{    
this.WebpartManager1.Personalization.ToggleScope();
}
ToggleScope() method will invert this scope if it is User then it will change it to Shared or vice versa.
And add the following line in web.config
<webParts>
.
. //webParts other settings

<authorization> <allow verbs="enterSharedScope" users="*" /> authorization> . .
personalization>
webParts>






Now check if the user is Admin user:
if (User == "admin")
{
   this.WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode;
  //allow user to edit the web parts and page layout
}
else
{
  //loop through the all web parts on a page to disable all editable verbs
       foreach (WebPart part in WebPartManager1.WebParts)
  {
             part.AllowClose = false;
             part.AllowMinimize = false;
             part.AllowEdit = false;
            part.AllowHide = false;
  }
 this.WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode;
//allow user to only view the page
  }
The above code allows the entire user to enter the shared personalization scope and can view the changes made by the Admin User.

Using user control within web parts: We can add any “server control” or “web user control” in a web part. But there is some limitation in using user control. A web part does not allow us to change its properties. To achieve this functionality we need to create the personalization properties for the user control.  
First of all create a class in “App_code” folder which will inherit the “System.Web.UI.UserControl”.  
Now Create what ever properties needed for the user control with “Personalization and Browsable “ attributes. For Example: 
public class BaseUserControl : System.Web.UI.UserControl
{
    private string _myText;
    private string _myColor;

    [Personalizable(), WebBrowsable()]
    public string MyText
    {
        get { return _myText; }
        set { _myText = value; }
    }
    [Personalizable(), WebBrowsable()]
    public string MyColor
    {
        get { return _myColor; }
        set { _myColor = value; }
    } 
Now Inherit this class in a user control to access these properties. For Example, if there is a label in user control, we can set it color and text by writing following code: 
lblName.Text = base.MyText;
lblName.ForeColor = Color.FromName(base.MyColor);
Adding user control properties to editor zone: To enable user to edit the user control properties, we need to add a class which will inherit from a “EditorPart” Class and override its methods. The Method includes 
  1. ApplyChanges()
  2. SyncChanges()
  3. CreateChildControls()
  4. RenderContents(HtmlTextWriter writer)

By using the above method we can add custom editor part to editor zone. Below is the code sample to use to edit the user control properties. The properties defined in the above code i.e, MyColor and MyText is used for better understanding. 
public class CustomEditorPart : EditorPart
{
   //declare control to add to the editor part
      private DropDownList _ddlColor;
      private TextBox _txtMsg;
      public CustomEditorPart()
      {
        //set the title of of the editor part
          this.Title = "Color EditorPart";
      }
    public override bool ApplyChanges()
    {
        //method of a Control Class to determine whether a control contains   any child control, if it doesn’t , it creates the child control.
      EnsureChildControls();
       
      //taking reference of the WebPartToEdit WebPart inside the Editor Part Class
      GenericWebPart oPart = (GenericWebPart)WebPartToEdit; 
    //creating an instance of the BaseUserControl Class created above to declare user control properties
        BaseUserControl control = (BaseUserControl)oPart.ChildControl;
       
 //setting the BaseUserControl Class Properties according to user selection
      control.MyColor = _ddlColor.SelectedItem.Text;
        control.MyText = _txtMsg.Text;
        return true;
    }
    public override void SyncChanges()
    {
        EnsureChildControls();
        GenericWebPart oPart = (GenericWebPart)WebPartToEdit;
        BaseUserControl control = (BaseUserControl)oPart.ChildControl;
       
        String currentColor = control.MyColor;
        String currentText = control.MyText;
        foreach (ListItem item in _ddlColor.Items)
        {
            if (item.Text == currentColor)
            {
                item.Selected = true;
                break;
            }
        }
    }
    protected override void CreateChildControls()
    {
        Controls.Clear();
//adding the items to dropdownlist to allow user to change color
        _ddlColor = new DropDownList();
        _ddlColor.Items.Add("Red");
        _ddlColor.Items.Add("Blue");
        _ddlColor.Items.Add("Green");
        Controls.Add(_ddlColor);
        _txtMsg = new TextBox();
      
        Controls.Add(_txtMsg);
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
     //adding labels to control in web parts 
      writer.Write("Change Text Color");
        writer.Write(" ");
        _ddlColor.RenderControl(writer);
        writer.Flush();
        writer.Write("Modify Text");
        writer.Write(" ");
        _txtMsg.RenderControl(writer);
    }
  }
Now in the code behind of the user control ascx file, first of all we need to inherit from BaseUserControl Class and implement IwebEditable Interface to actually set these changes in action. 
In the Page load Method we need to add the following code to get the initial value for the properties. 
protected void Page_Load(object sender, EventArgs e)
    {
        base.MyColor = Label1.ForeColor.ToString();
        base.MyText = Label1.Text;
       
    } 
In the Page PreRender Method we will add following code to set the value  
protected void Page_Prerender(object sender, EventArgs e)
    {
        if (base.MyColor != null)
        {
            Label1.ForeColor = Color.FromName(base.MyColor);
        }
        if (base.MyText != null)
        {
            Label1.Text = base.MyText;
        }
    }
In the Page Init Method we need to create the instance of GenericWebPart and set the title of the Web part. 
protected void Page_Init(object sender, EventArgs e)
    {
        GenericWebPart gwp = Parent as GenericWebPart;
        if (gwp != null)
        {
            gwp.Title = "Usercontrol webpart2";
        }
    } 
Further we need to implement the IWebEditable Interface Member, which are:
    1. CreateEditorParts()
    2. WebBrowsableObject()

Below is the Code  
public EditorPartCollection CreateEditorParts()
    {
        ArrayList editorArray = new ArrayList();
        CustomEditorPart edPart = new CustomEditorPart();
        edPart.ID = this.ID + "_customPart1";
        editorArray.Add(edPart);
      
 EditorPartCollection editorParts = new EditorPartCollection(editorArray);
        return editorParts;
    }
    public object WebBrowsableObject
    {
        get { return this; }
    } 
By doing so, User will be able to edit the User control properties from the editor zone.  
Note: For each user control we need to define one separate class, as there may be different properties assigned to each user control. 
Communication between two web parts: Connections are a very powerful feature of web parts that allows interchanging data between two web parts. By using connections, developers can discover new opportunities for code reuse and for combining the functionality of isolated controls. A Web Parts connection is a link or association between two server controls that enables them to share data. A connection always involves exactly two controls: one is the provider of data, and the other is the consumer of the data from the provider. A control can be a consumer and a provider, and any type of server control, whether a web part control, a custom control, or a user control, can be designed to participate in connections. To form a connection, the consumer and provider must both recognize the same type of data, which in Web Parts connections is passed by means of an interface instance.
To achieve this functionality, first of all create a interface containing properties need to be shared. For ex: 
public interface IWebPartMessageContract
    {
        string Message { getset;}
    } 
The Provider Web part containing any user control or server control will implement this interface and set the interface properties to share among provider and consumer. 
Suppose we have a user control to filter the records. The user control will implement the interface. We will create the virtual property in a user control and marked as “personalizable”. In our example, provider web part will send the message to consumer web part . 
    [Personalizable()]
      public virtual string Message
        {
            get { return strMessage; }
            set { strMessage = value; }      }
Along with this we require a method that returns the IWebPartMessageContract interface, and should be decorated with the [ConnectionProvider]. 
// This is the callback method that returns the provider.
        [ConnectionProvider("Message Provider""MyWebPartProvider")]
        public IWebPartMessageContract ProvideData()
        {
            return this;
        } 
“MyWebPartProvider” is an ID for provider connection point. This will be used in creating connections. 
On a submit of a button or any other event we can set the properties to send message to consumer web parts. 
private void SendMessage(object sender, EventArgs e)
        {
            if (txtMessage.Text != String.Empty)
            {
                Message = txtMessage.Text;
               
            }
         } 
The Consumer Web Part will receive this message and diplay it to user. For this first of all we have to create a Interface instance. 
private IWebPartMessageContract _provider; 
Consumer Web parts need a method decorated with the ConnectionConsumer attribute. This method needs to accept one parameter of the IWebPartMessageContract data type. 
// This method is identified by the ConnectionConsumer
        // attribute, and is the mechanism for connecting with
        // the provider.
        [ConnectionConsumer("Message Consumer""MyWebPartConsumer")]
        public void GetMessage(IWebPartMessageContract Provider)
        {
            _provider = Provider;
        }
if we are using user control overried the onPreRender Method to set the value of any control. 
    protected override void OnPreRender(EventArgs e) {
    base.OnPreRender(e); if (_publisher != null) {
    lblMessage.Text = _provider.Message;
    }
    } 
After creating a provider and consumer web parts we need to create a connection. There are four steps that you must complete to create a static connection between two Web Parts:
  • Define an interface specifying the methods and properties that are shared between the connected Web Parts.
  • Add the ConnectionProvider attribute to the Web Part used to provide the -shared information.
  • Add the ConnectionConsumer attribute to the Web Part used to consume the shared information.
  • Declare the connections within the “StaticConnections” sub tag of the WebPartManager class.
  Now add Both Provider Web Part and Consumer Web Part into the page. Till now our page is ready with both the consumer and provider Web Part. At the moment there is no connection establish between the Web Part. We are going to do that shortly. 
We will add static connection between these two web parts: 
 ID="WebPartManager1runat="server" >   ID="conn1ConsumerConnectionPointID="MyWebPartConsumerConsumerID="consumer1"  ProviderConnectionPointID="MyWebPartProvider"  ProviderID="provider1" />  
 

Consumer1 is ID corresponds to Consumer Web Part
Provider1 is ID corresponds to Provider Web part
MyWebPartProvider is provider connection point (we have set this ID in our provider web part)
MyWebPartConsumer is consumer connection point (we have set this ID in our consumer web part)
Now run the application. When we will enter some text in provider web part and click on send message button. It can be seen in consumer web part.