New version of SmartPart, now with "AJAX Connections"

As you may know, last week I released a version (still in beta) of the SmartPart which supports the ASP.NET AJAX extensions. For more information about this version of the SmartPart, see my previous blog post.

This weekend I've been working on functionality to support "AJAX connection" in the SmartPart. First of all; connectable web parts are web parts that can exchange data. Think for example about a web part which displays a list of invoices, and another one that displays a list of invoice lines. If you select an invoice in the first one, the second one can display the lines of the selected invoice. So with connectable web parts you can create those typical parent/child and parent/details relationships. You can create connectable web parts in SharePoint 2003 and in ASP.NET 2.0/SharePoint 2007, so it's not a new functionality.

So why are the connections in the new version of the SmartPart (Return of SmartPart v1.2 BETA) so special? Well if you combine web part connections with a little bit of AJAX-magic you have web parts that can exchange data without postbacks! Think about selecting the invoice and displaying the corresponding invoice lines in another web part, all without postbacks. Actually you could do that trick without this new version, but I've added some helper and wrapper classes to make your life as a web part developer a little bit easier!

Let's start with a really basic example: the DemoProvider and the DemoConsumer user controls. The first one has an UpdatePanel (the ASP.NET AJAX control handling the partial-page rendering), a TextBox and a Button. The second one just has an UpdatePanel and a TextBox. The scenario should be like this: the user enters some text in the first text box, clicks the button and the text is transferred to the second text box, all without postbacks.

 

public partial class DemoProvider : System.Web.UI.UserControl,
                             
SmartPart.IConnectionProviderControl
{
  protected void Page_Load(object sender, EventArgs e)
  {
}

  public string ProviderMenuLabel
  {
    get { return "Send test data to" }
  }

  public object GetProviderData()
  {
    return new SmartPart.AJAXConnectionData(
      TextBox1.Text, Button1, "Click");
  }
}

The code above is the code for the DemoProvider user control, notice that the class implements the IConnectionProviderControl interface of the SmartPart which is also used for normal connections. The special thing happens on the GetProviderData method; a new instance of the AJAXConnectioNData class is created. This object contains first of all the value that should be send to the consumer (TextBox1.Text). The second parameter is the control that will cause the UpdatePanel to refresh, the third parameter is the name of the control's event which will cause the refresh. (This constructor can only have one control as a trigger control, but the class can hold more than one.) The ProviderMenuLabel property returns the value which will be displayed in the web UI of SharePoint when the connection is made. That's it! Now let's take a look at the code for the DemoConsumer user control:

public partial class DemoConsumer : System.Web.UI.UserControl,
                                 
SmartPart.IConnectionConsumerControl
{
  protected void Page_Load(object sender, EventArgs e)
  {
}

  public string ConsumerMenuLabel
  {
    get { return "Receives test data from" }
  }

  public void SetConsumerData(object data)
  {
    SmartPart.AJAXConnectionData ajaxData = data as SmartPart.AJAXConnectionData;
    if (ajaxData != null)
    {
      ajaxData.RegisterTriggerControls(UpdatePanel1);
      if (ajaxData.Data != null)
        TextBox1.Text = ajaxData.Data.ToString();
    }
  }
}

The class implements the normal IConnectionConsumer control of the SmartPart and once again the special thing happens in the SetConsumerDate method. This method receives the instance of the AJAXConnectionData class which was constructed by the provider. First the code checks if the data received is an AJAXConnectionData instance, if so the RegisterTriggerControls method is called with the UpdatePanel to use as a parameter. This method will add every control of the AJAXConnectionData instance as a trigger control for the UpdatePanel, so the two UpdatePanels of the two user controls can trigger eachother. You could do this manually as well, but I provided this functionality since it will be the same for in like 99% of all the cases. Finally the Data property is used to fill the TextBox's Text property. Done!

I could show the result with some screenshots, but you have to see them in action to get the idea. That's why I've recorded a small screencast of the two user controls. The second part of the screencast shows some other controls which get data from the AdventureWorks database. I already put them on a site, so you can see the Categories web part connected to the Subcategories web part, which is connected to the Products web part. You can download the source code for these demos from CodePlex.

Downloads:

29 Comments

  • Do you know why my user controls say PartialCachingControl

  • I need to have a custom toolpart to show some values from the database in a dropdown. Can you give an example of how to do this with the return of smartpart, I have been searching for sometime and could not find any example that creates a custom toolpart and setting the custom attribute to the custom toolpart value using smartpart.

    It would be really helpful if i could get an example of doing this, since we are planning to use the smartpart and do our webpart using user controls.

  • I need to have a custom toolpart to show some values from the database in a dropdown. Can you give an example of how to do this with the return of smartpart, I have been searching for sometime and could not find any example that creates a custom toolpart and setting the custom attribute to the custom toolpart value using smartpart.

    It would be really helpful if i could get an example of doing this, since we are planning to use the smartpart and do our webpart using user controls.

  • I have the same problem as Deepa.
    I need to custom toopart to show values from the database by dropdown.
    Besides, I can't use the DemoProvider, DemoConsumer
    When I plug them on my sharepoint, it will be an error as following:
    "An unexpected error has occurred.
    Web Parts Maintenance Page: If you have permission, you can use this page to temporarily close Web Parts or remove personal settings. For more information, contact your site administrator. "

    What's wrong ?? Coulde you please give me a advise?
    Thanks

  • Please provide some instructions for those of us who just don't get it.
    How do I get a usercontrol which accesses a SQL database to work in smartpart.
    In VS2005 my control works. In MOSS 2007 Smartpart correctly runs your test control. When I add my data access control control.ascx and contol.ascx.vb to my USerControl\folder I can add it to smartpart, but then Sharepoint errors.

    I can create a custom control with no connection to my database and that works correctly. As soon as I add a database connection - its a no go.

    What am I missing.

  • Same problem as Fred once I make a connection to the data base it bombs I have added the connection string to the web config in the wss virdir but it still doesnt see it or something is there another place I need to add the key for the connection string? anybody got any Ideas?

  • How about adding support for browsable Enum usercontrol properties?

  • When I statically add the AJAXSmartPart to a page layout using the following code:





    I get the following error message:

    "The control with ID 'UpdatePanel1' requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it."

    So it looks like AJAXSmartPart forgets to add a ScriptManager when it is added statically. When I manually add a ScriptManager to the page layout code it works fine. Also when I add a second AJAXSmartPart using the normal approach (i.e. add it as a webpart to a WebPartZone), that second one seems to add the ScriptManager and they will both work. Looks like a bug, doesn't it?

  • How can I tell if the webpart is in "edit mode"? The SmartPart interface doesn't expose the internal WebPartManager object, so I cannot query it from the user control.

  • Hi Jan,
    I'm still using the old SonOfSmartpart and have just migrated our Sharepoint 2003 content to MOSS2007. During the migration tests I came up with a security issue. It seems that every user who wants to configure the smartparts user control needs NTFS access rights on the usercontrols folder on the server. Is that correct? Is there a workaround for that, e.g. using an IIS-Guest account? I have only integrated Windows authentication enabled and don't want anonymous access.
    Thanks
    René

  • Question for you: Does the smart part set EnablePageMethdod=true on the ScriptManager? When trying to use the AjaxControlToolkit with a pageMethod it does not work.

    Thanks,
    David

  • I have the same question as David. I am trying to use the AutoComplete from the ajaxtoolkit to call an external web service. That was not working (access denied errors. - by the way if you have any comments on how to call a web service on a different server - that would be helpful.) But for the pageMethod, how can you set the EnablePageMethod = true?

  • I'm trying to get this simple provider and consumer demo provided to work on a webpage before testing it out on SharePoint. I am not getting any events trigger when i click send data. (In other words, Consumer textbox is not gettign any events).

    This is what i'm doing.
    In default.aspx, i include both the consumer and provider controls.
    It's as simple as that. Do i need to subscribe to any events? I have no problem compiling it.

    Thanks.

  • Hi Jan,

    First, let me say congradulations on your being a new dad!

    Now, I'm using your newest SmartPart version (the beta) and what I'm trying to do is add your smartpart to a web part page during the FeatureActivation event of a feature. Here's what I have so far and I'm not getting any errors, but my Users control is not getting loaded. Any ideas?

    SPFile page = site.GetFile( "sem/SystemAdmin.aspx" );
    SPLimitedWebPartManager mgr = page.GetLimitedWebPartManager( PersonalizationScope.Shared );

    SmartPart.SmartPart smart = new SmartPart.SmartPart();
    smart.UserControl = "My.Assembly,My.Assembly.Users";
    mgr.AddWebPart( smart, "centerWebPartZone", 0 );

  • I am using the latest version of smartpart with MOSS 2007. It works well Jan !! Thanks. I can connect to database only when i set the impersonate=false in the web.config of wss virtual folder. By default its true for moss 2007 and when its true, the sqlconnection.Open fails !!!

    Any idea? Please help.. I am burning my head for past several days on this guys..

  • Can you please suggest me, how to implement cross page connections using the smartpart. Currently I am using: Return of the SmartPart Version 1.2.0.0
    Looking at the methods SetConsumerData and GetProviderData, I am not sure you can really achieve this. Any help would be greatly appreciated.

    Thanks,

  • Is it possible to get teh current logon user to personalize the user control.
    Thanks

  • This is a great tool to develop custom webparts. Although, I am having problems with connecting the web parts. I get some error and Sharepoint asks me if I want to go to the web parts maintenance page to disable the web part. I have two web parts, one being the provider and the other a consumer. When I add the provider, it all works fine and data is shown. I can also add the consumer and it shows up on the page. However, when I go to connect them, I get the error. I am using the 1.2 beta version. I also tried creating a simple webpart as a consumer with just a text box and no extra code other than the one the methods that need to be implemented for the consumer web part. Please let me know if this is a known issue, or if anyone has any solution for this. Thanks,

  • Jan,

    thanks for this very useful utiliy - I really fills a spot where MS needs to improve. I would like to use it in a project, but without the sourcecode I will not be able (allowed) to.

    Is there anyway we could get a hold to your sources (URL?) ?

    Thanks,
    Erich

  • I can not see the "Connections" menu item on the Smartpart. Has anyone faced this issue?

    Thanks in advance
    Kiran

  • Hi

    I have a basic question. Can we create cross-page connections using smartpart?

    Thanks
    Kiran

  • Hi

    I have one smart(having user control) part which is a producer on PageNo1.

    Secondly, I have another smartpart(having user control) on PageNo.2 which is a consumer for smart part on PageNo1.

    Now, the problem is that I am finding "Connections" link coming disabled showing tooltip something as "Connection type not compatiable with other parts of the web page."

    Now the catch is it works prefectly fine when both producer and consumer are on the same page, but does not work if put on different pages.

    My second big concern is that on "Submit" click, I want to move to next page and then show the consumer data fetched from producer on PageNo1.

    Please Suggest. It is too critical for my application.

  • Hi,
    I'm trying to use a Web User Control created in IronPython in a SmartPart, and get an "'IronPython' is not a supported language"
    error. The same control works when called directly.

    Thanks a lot for any ideas what the cause could be.

  • Is there a way to get this to work in VB?
    I've tried and get:
    error BC30154: Class 'VBConsumer' must implement 'ReadOnly Property ConsumerMenuLabel() As String' for interface 'SmartPart.IConnectionConsumerControl'. Implementing property must have matching

    This works beautifully in C# on my WSS 3.0 website (SmartPart 1.2 beta).

    Thanks!

  • Okay -- I got some basic AJAX Connection with SmartPart 1.2.0 beta here for VB. Here's the VB Code:

    ---------------------Provider page: ------------------------
    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    Imports SmartPart

    Partial Public Class VBProvider
    Inherits System.Web.UI.UserControl
    Implements SmartPart.IConnectionProviderControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

    End Sub


    ReadOnly Property IConnectionProviderControl_ProviderMenuLabel() As String Implements SmartPart.IConnectionProviderControl.ProviderMenuLabel
    Get
    Return "Send data to"
    End Get
    End Property


    Function IConnectionProviderControl_GetProviderData() As Object Implements SmartPart.IConnectionProviderControl.GetProviderData
    ' Build a new AJAXConnectionData object and return it.
    ' Parameters:
    ' - value to send
    ' - control which triggers the connection
    ' - event of the control which will trigger the connection
    Return New SmartPart.AJAXConnectionData(TextBox1.Text, Button1, "Click")
    End Function


    End Class



    ----------------------Consumer page:-------------------------
    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    Imports SmartPart

    Partial Class VBConsumer
    Inherits System.Web.UI.UserControl
    Implements SmartPart.IConnectionConsumerControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

    End Sub

    ReadOnly Property IConnectionConsumerControl_ConsumerMenuLabel() As String Implements SmartPart.IConnectionConsumerControl.ConsumerMenuLabel
    Get
    Return "Receives test data from"
    End Get
    End Property

    Sub IConnectionConsumerControl_SetConsumerData(ByVal data As Object) Implements SmartPart.IConnectionConsumerControl.SetConsumerData
    Dim ajaxData As SmartPart.AJAXConnectionData = data '= data as SmartPart.AJAXConnectionData

    ' Check if the received data was of the correct type
    If Not ajaxData Is Nothing Then
    ' Register the trigger controls, so the UpdatePanel get's updated async.
    ajaxData.RegisterTriggerControls(UpdatePanel1)

    ' Check if there was any data received, if so: set the value.
    If Not ajaxData.Data Is Nothing Then
    TextBox1.Text = ajaxData.Data.ToString()
    End If
    End If
    End Sub

    End Class

    -----------------------------------------------------
    Okay, hope it helps somebody. Now I'm off to see if I can plug in some SQL db...

  • I can't for the life of me get a DropDown control to work as the provider for a web part. The control will render until I try to "connect" it to a Consumer part. The code works great when I use it in a GridView but not with a DropDown. Any Ideas anyone?

    Bill

    public partial class DemoProvider : System.Web.UI.UserControl,
    SmartPart.IConnectionProviderControl
    {
    protected void Page_Load(object sender, EventArgs e)
    { }

    #region

    public string ProviderMenuLabel
    {
    get { return "Send ID data to" }
    }

    public object GetProviderData()
    {
    return new SmartPart.AJAXConnectionData(
    DropDownList1.SelectedValue, Button1, "Click");
    }

    #endregion

    }

  • Hello Jan,

    With an installation of the .Net Framework 3.5 on a WSS3.0 Server, given that the framework contains ASP.NET AJAX, do the configuration steps of Ajax on the server change?

    Thanks

  • I follow this article step by step but it doesn't work, help me please

  • Hi Jan

    Things like calendars and collapsing panels are working fine in may Smart Parts. Connectivity between parts without Ajax is too.

    But when I drop in your demo provider and demo consumer, configured so that the provider sends data to the consumer, nothing happens...

    Similarly a simple control with two text boxes and a button where the button click sends text box 1's text to text box 2 works fine in an aspx page, but not in SharePoint.

    Any clues?

    Thanx!

Comments have been disabled for this content.