p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   BOOK: Professional Web Parts and Custom Controls ASP.NET ISBN: 0-7645-7860-X (http://p2p.wrox.com/forumdisplay.php?f=225)
-   -   Chapter 10 fixes (http://p2p.wrox.com/showthread.php?t=45750)

.MAttButler July 26th, 2006 09:20 PM

Chapter 10 fixes
I'm going to be working through the book and making the fixes. I got the code and text for the book last night and the first thing I looked at and fixed was the " Exception Details: System.ArgumentException: A ConsumerConnectionPoint has already been added with ID 'default'.
Parameter name: connectionPoints" exception. This means that the declaration of the three callback methods in ConsumerPart.vb lacked a unique ID. The overload used in the book left the default name in place by only passing in a string for the displayName eg:

<WebControls.WebParts.ConnectionConsumer("IBookInf o Consumer")> _
    Public Sub IBookInfoConsumer(ByVal bk As IBookInfo)

In the corrected code below we've used the overload that assigns an ID, too:

<ConnectionConsumer("IBookInfo Consumer", "MyUniqueIBookInfoConsumerName")>....

Below is the ConsumerConnectionPointCollection constructor and we can see on line 16 the Contains() test being run to see if there is a duplicate key (representing as ConsumerConnectionPoint) already in the HybridDictionary. If it returns true then code throws the exception that we finally see (line 17). Again, the code below is framework code and isn't something we'd need to deal with, it's just here to illustrate the "why" behind the exception. I make a habit of looking several layers below the root cause of an error or exception just so I can understand what consequences each line of code I write has within the framework:

1. Public Sub New(ByVal connectionPoints As ICollection)
2. If (connectionPoints Is Nothing) Then
3 Throw New ArgumentNullException("connectionPoints")
4 End If
5 Me._ids = New HybridDictionary(connectionPoints.Count, True)
6 Dim V_0 As Object
7 For Each V_0 In connectionPoints
8 If (V_0 Is Nothing) Then
9 Throw New ArgumentException(SR.GetString("Collection_CantAdd Null"), "connectionPoints")
0 End If
11 Dim V_1 As ConsumerConnectionPoint = TryCast(V_0,ConsumerConnectionPoint)
12 If (V_1 Is Nothing) Then
13 Throw New ArgumentException(SR.GetString("Collection_Invalid Type", New Object() { "ConsumerConnectionPoint" }), "connectionPoints")
14 End If
15 Dim V_2 As String = V_1.ID
16 If Me._ids.Contains(V_2) Then
17 Throw New ArgumentException(SR.GetString("WebPart_Collection _DuplicateID", New Object() { "ConsumerConnectionPoint", V_2 }), "connectionPoints")
18 End If
19 MyBase.InnerList.Add(V_1)
20 Me._ids.Add(V_2, V_1)
21 Next
22 End Sub

Here is the code for the ConsumerPart.vb class that correct this particular problem. It is not in it's final form, I still haven't gone through it in detail:

Imports System.ComponentModel
Imports System.Web.UI

<ToolboxData("<{0}:ConsumerPart runat=server></{0}:ConsumerPart>")> Public Class ConsumerPart
    Inherits System.Web.UI.WebControls.WebParts.WebPart

    Private ibk As IBookInfo
    Dim typ As Object
    Dim strTitle As String
    Dim pcSchema As PropertyDescriptorCollection

    'This method should have used the constuctor that accepts a string to set the ID like this:
    <WebControls.WebParts.ConnectionConsumer("IBookInf o Consumer", "MyUniqueIBookInfoConsumerName")> _
    Public Sub IBookInfoConsumer(ByVal bk As IBookInfo)
        Dim strProviderValue As String
        Dim bolSuccess As Boolean

        ibk = bk

        strProviderValue = "10345329"
        bk.ISBN = strProviderValue
        bolSuccess = bk.SortData("Desc")

    End Sub

    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)

        If ibk Is Nothing Then
            writer.Write("<b>No book information available.</b>")
            writer.Write("ISBN: <b>" & ibk.ISBN & "</b>")
        End If

    End Sub

    Private Sub ConsumerPart_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        Me.Title = "Consumer"
    End Sub

    Dim ifld As WebControls.WebParts.IWebPartField
    'This method should have used the constuctor that accepts a string to set the ID like this:
    <WebControls.WebParts.ConnectionConsumer("IWebPart Field Consumer", "MyUniqueIWebPartFieldConsumerName")> _
    Public Sub IWebPartFieldConsumer(ByVal fld As WebControls.WebParts.IWebPartField)

        ifld = fld
        ifld.GetFieldValue(AddressOf ReceiveData)

    End Sub

    Sub ReceiveData(ByVal BookTitle As Object)
        Dim pd As PropertyDescriptor

        pd = ifld.Schema
        If pd.PropertyType.Name = "String" Then
            strTitle = BookTitle.ToString
        End If

    End Sub

    'This method should have used the constuctor that accepts a string to set the ID like this:
    <WebControls.WebParts.ConnectionConsumer("IWebPart Parameters Consumer", "MyUniqueIWebPartParametersConsumerName")> _
    Public Sub IWebPartParametersConsumer( _
                      ByVal prm As WebControls.WebParts.IWebPartParameters)
        Dim pdc As PropertyDescriptorCollection
        Dim iprm As WebControls.WebParts.IWebPartParameters

        iprm = prm

        pdc = TypeDescriptor.GetProperties(Me)

        If iprm.Schema.Count = pdc.Count Then
            iprm.GetParametersData(AddressOf ReceiveData)
        End If
    End Sub

    Sub ReceiveData(ByVal BookInfo As IDictionary)
        Dim entry As DictionaryEntry

        For Each entry In BookInfo.Keys
            Select Case entry.Key.ToString
                Case "BookTitle"
                    Me.BookTitle = entry.Value.ToString
                Case "BookAuthor"
                    Me.BookAuthor = entry.Value.ToString
            End Select

    End Sub

    Property BookTitle() As String
            Return "Custom Controls and Web Parts"
        End Get
        Set(ByVal value As String)

        End Set
    End Property

    Property BookAuthor() As String
            Return "Peter Vogel"
        End Get
        Set(ByVal value As String)

        End Set
 End Property

End Class

jminatel July 27th, 2006 02:00 PM

Thanks a ton for taking this on Matt. For those of you who have been waiting so long to get some answers on these code issues, I apologize again. I've now got Matt to agree to going through and checking and posting fixes for all of this for Wrox in place of the original author.

Jim Minatel
Senior Acquisitions Editor
Wiley Technology Publishing
WROX Press
Blog: http://wroxblog.typepad.com/
Jim's Book of the week: No book this week - Donate to the Red Cross!

.MAttButler September 3rd, 2006 08:02 PM

I've posted Chapter 10 at http://100days.net/wrox/

The way the author wrote the code it makes it very tricky to navigate the examples for this chapter. Make sure you're connecting to the Transform providers and consumer when you're working with those examples, make sure the connections are disconnected when you're done with them, etc. It's finicky. Let me know if you all have any questions. This is the VB.NET version, the C# code will be along at some point.

Chapter 12 has one more tweak that needs to be dealt with and I'll post that shortly.

All times are GMT -4. The time now is 12:11 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.