Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
106
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

1078 CHAPTER 31 PORTALS WITH WEB PART PAGES

}

}

public DateTime SubmittedDate

{

get

{

//Get the NoteDate value from the grid's data source

//...

}

}

#endregion

// Rest of the implementation

...

Within the property procedures, you need to add the appropriate code for retrieving the values from the data source you have bound to the GridView in the WebPart’s original version. Updating the data in the property’s set procedure means updating the value in the GridView’s data source and then using, for example, a SqlCommand or a SqlDataAdapter for updating the values on the database. Retrieving the SubmittedDate from the GridView’s data source might look like this:

public DateTime SubmittedDate

{

get

{

EnsureChildControls();

if (CustomerNotesGrid.SelectedIndex >= 0)

{

int RowIndex = CustomerNotesGrid.SelectedRow.DataItemIndex;

DataTable dt = (DataTable)CustomerNotesGrid.DataSource; return (DateTime)dt.Rows[RowIndex]["NoteDate"];

}

else

{

return DateTime.MinValue;

}

}

}

You can verify whether an item has been selected in the GridView. (To do this, you need to enable selection on the GridView.) If an item is selected, you retrieve the DataItemIndex, which then can be used as an index for accessing the DataRow of the DataTable, which is bound to the GridView. You can read the value from the DataRow and return it.

The next thing your provider WebPart has to support is a method marked with the [ConnectionProvider] attribute. This method returns the actual implementation of the communication contract interface, which is the WebPart in this case. Therefore, you need to implement it as follows:

[ConnectionProvider("Notes Text")]

public INotesContract GetNotesCommunicationPoint()

{

return (INotesContract)this;

}

CHAPTER 31 PORTALS WITH WEB PART PAGES

1079

That’s it! Your provider WebPart is ready to use. Next you need to implement the consumer WebPart, which is much easier.

Creating the Consumer Web Part

The consumer WebPart retrieves information from the provider WebParts for its own purposes. In this example, you just display the text for the currently selected note in the CustomerNotesPart that you have implemented as the provider.

Because this solution does not contain this WebPart yet, you have to start from scratch. Just add a new class that inherits from WebPart. The WebPart uses the CreateChildControls for creating a label that displays the date, a text box that displays the notes text, and a button that updates the notes text.

public class CustomerNotesConsumer : WebPart

{

private Label NotesTextLabel; private TextBox NotesContentText; private Button UpdateNotesContent;

protected override void CreateChildControls()

{

NotesTextLabel = new Label(); NotesTextLabel.Text = DateTime.Now.ToString();

NotesContentText = new TextBox();

NotesContentText.TextMode = TextBoxMode.MultiLine;

NotesContentText.Rows = 5;

NotesContentText.Columns = 20;

UpdateNotesContent = new Button();

UpdateNotesContent.Text = "Update";

UpdateNotesContent.Click += new EventHandler(UpdateNotesContent_Click);

Controls.Add(NotesTextLabel);

Controls.Add(NotesContentText);

Controls.Add(UpdateNotesContent);

}

void UpdateNotesContent_Click(object sender, EventArgs e)

{

// Update code needs to be implemented later

}

}

Next, you have to add a simple method that is called by the ASP.NET web part framework automatically if the WebPart is connected to another WebPart. This method accepts the other connection point (which is the provider) as a parameter and needs to be marked with the [ConnectionConsumer] attribute so that the runtime knows this is the method to be called for passing in the provider.

private INotesContract _NotesProvider = null;

[ConnectionConsumer("Customer Notes")]

public void InitializeProvider(INotesContract provider)

{

_NotesProvider = provider;

}

1080 CHAPTER 31 PORTALS WITH WEB PART PAGES

With the provider initialized, the WebPart of course can consume information from the provider by just calling properties (or methods) defined in the communication contract. For example, in the PreRender event you can initialize your controls, whereas in the button’s event procedure you can update the notes content by setting the Notes property appropriately:

void UpdateNotesContent_Click(object sender, EventArgs e)

{

if (_NotesProvider != null)

{

_NotesProvider.Notes = NotesContentText.Text;

}

}

protected override void OnPreRender(EventArgs e)

{

//Don't forget to call base implementation base.OnPreRender(e);

//Initialize control

if (_NotesProvider != null)

{

NotesContentText.Text = _NotesProvider.Notes; NotesTextLabel.Text =

_NotesProvider.SubmittedDate. ToShortDateString ();

}

}

Of course, you have to validate whether the provider has been initialized. If it hasn’t been, the WebPart is not connected with any other WebPart, and therefore you cannot access any information. However, with this code in place you are basically finished. You have created a consumer WebPart and a provider WebPart, and communication between those two takes place through the communication contract interface. Next you can connect these WebParts either manually or dynamically at runtime.

Static Connections Between WebParts

The simple way to connect WebParts is through static connections. How can you do that? Well, let’s think about the roles of the different controls involved in web part pages again. The WebPartManager knows about all the web parts and manages features such as personalization. WebPartZones are areas on your web page that can contain WebParts, while the WebParts are independent controls. If you think about it one moment, you definitely will recognize that the WebPartManager might be a good starting point for taking a closer look at connection points. You are right: static connection points are configured through the WebPartManager as follows:

<asp:WebPartManager runat="server" ID="MyPartManager"> <StaticConnections>

<asp:WebPartConnection ID="SimpleConnection" ProviderID="MyCustomerNotes" ConsumerID="MyNotesConsumer" />

</StaticConnections>

</asp:WebPartManager>

The ID values used for the ProviderID and ConsumerID are just the ID values of the WebParts as they have been added to the WebPart zone. You can find these WebParts in the zones of your WebPart page, as you can see in the following code fragment:

CHAPTER 31 PORTALS WITH WEB PART PAGES

1081

<table width="100%">

...

<asp:WebPartZone runat="server" ID="MainZone" > <ZoneTemplate>

<uc1:Customers ID="MyCustomers" runat="server" OnLoad="MyCustomers_Load" />

<apress:CustomerNotesPart

ID="MyCustomerNotes" runat="server" />

</ZoneTemplate>

</asp:WebPartZone>

...

<asp:WebPartZone runat="server" ID="HelpZone> <ZoneTemplate>

<apress:CustomerNotesConsumer ID="MyNotesConsumer" runat="server" />

<asp:Calendar runat="server" ID="MyCalendar" OnLoad="MyCalendar_Load" />

<asp:FileUpload ID="MyUpload" runat="server" /> </ZoneTemplate>

</asp:WebPartZone>

...

</table>

When configuring this connection point, you will recognize that the consumer WebPart always displays information from the selected entry of the CustomerNotes WebPart.

Dynamically Configuring Connection Points

If you don’t want to connect WebParts statically but want the user to have the possibility of connecting WebParts at runtime, you cannot use the WebPartManager’s StaticConnections configuration. But providing dynamic configuration of connection points is nearly as simple as configuring static connection points. All you need to add to your page is a special zone called ConnectionsZone, as follows:

<asp:ConnectionsZone ID="MyConnections" runat="server"> <ConnectVerb Text="Connect Now..." />

<CancelVerb Text="Don't connect" /> <DisconnectVerb Text="Release connection" />

</asp:ConnectionsZone>

The child tags of the ConnectionsZone are optional and allow you to customize the default user interface created for editing the connections. When having added such a zone onto your web part page, you can switch to the Connect mode (what is not possible otherwise). If you want to edit connections for a WebPart in the running web application at runtime, you need to perform the following tasks as the user of the web page:

1.Switch to the Connect mode.

2.Select the consumer web part, and select Connect from the WebPart’s menu.

3.Now the connection editor appears in the previously added ConnectionsZone. Here you can select a provider and click the Connect button.

4.The WebParts are connected now. You can release the connection by clicking the Release button.

Figure 31-16 shows the ConnectionsZone in action.

1082 CHAPTER 31 PORTALS WITH WEB PART PAGES

Figure 31-16. ConnectionsZone in action

Multiple Connection Points

A WebPart provider can make multiple connection points available, while a WebPart consumer can consume multiple provider connection points. In that case, every connection point requires a unique ID on both the consumer side and the provider side. On the provider side, you specify the connection point ID in the [ConnectionProvider] attribute, as follows:

[ConnectionProvider("Notes Text", "MyProviderID")] public INotesContract GetNotesCommunicationPoint()

{

return (INotesContract)this;

}

You can specify an ID for consumer end points in the same way if a WebPart is a consumer of multiple providers, as follows:

[ConnectionConsumer("Customer Notes", "MyConsumerID")] public void InitializeProvider(INotesContract provider)

{

_NotesProvider = provider;

}

These IDs have to be unique within the WebPart. This means other WebParts can define connection points with the same ID. When configuring static connections for WebParts that support multiple connection points, you have to specify those through additional ProviderConnectionPointID and ConsumerConnectionPointID parameters, as follows:

CHAPTER 31 PORTALS WITH WEB PART PAGES

1083

<asp:WebPartManager runat="server" ID="MyPartManager"> <StaticConnections>

<asp:WebPartConnection ProviderID="MyCustomerNotes"

ProviderConnectionPointID="MyProviderID"

ConsumerID="MyCustomerNotesConsumer" ConsumerConnectionPointID="MyConsumerID" />

</StaticConnections>

</asp:WebPartManager>

In the case of dynamic configuration, the user can select the connection point to connect to based on the name specified as first parameter in the previously used [ConnectionProvider] and [ConnectionConsumer] attributes.

Authorizing Web Parts

When you have all your WebParts on your page, you might want to make some available to specific groups of users. Fortunately, the ASP.NET 2.0 Web Part Framework includes a way to specify such authorization information for web parts. All you need to do is catch one specific event of the WebPartManager class called AuthorizeWebPart. Within this event procedure, you can encapsulate logic for deciding whether a user is authorized to view a web part.

The following example shows how to display the CustomerNotes WebPart only if the user browsing to the page is member of the local Administrators group:

protected void MyPartManager_AuthorizeWebPart(

object sender, WebPartAuthorizationEventArgs e)

{

//Ignore authorization in Visual Studio Design Mode if (this.DesignMode)

return;

//Authorize a web part or not

Type PartType = e.Type;

if (PartType == typeof(CustomerNotesPart))

{

if (User.Identity.IsAuthenticated)

{

if (User.IsInRole("BUILTIN\\Administrators")) e.IsAuthorized = true;

else

e.IsAuthorized = false;

}

else

{

e.IsAuthorized = false;

}

}

}

Because authorization takes place on types of WebParts and not on individual instances of WebParts, you get the type of the WebPart to be authorized from the WebPartManager in the event arguments. You then can make authorization decisions based on the type of the WebPart as demonstrated previously. As soon as you set the IsAuthorized property of the WebPartAuthorizationEventArgs structure passed in to false, the WebPartManager will not display WebParts of this type— neither on the page nor in other situations such as a PageCatalogPart of a CatalogZone.

1084 CHAPTER 31 PORTALS WITH WEB PART PAGES

Final Tasks for Personalization

Finally, you should keep in mind a couple of final tasks for personalization. You can configure personalization properties on a per-page level through the WebPartManager, as follows:

<asp:WebPartManager runat="server" ID="MyPartManager"> <Personalization Enabled="true" ProviderName="YourProvider" />

</asp:WebPartManager>

If you want to configure personalization settings for the whole application, you have to do that through the <webParts> configuration element in the web.config application configuration, as follows:

<webParts>

<personalization defaultProvider="MyProvider"> <authorization>

<allow roles="BUILTIN\Administrators"/> <deny roles="BUILTIN\Guests" />

</authorization>

<providers>

<add name="MyProvider" type="System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider" connectionStringName="CustomSqlConnection" />

</providers>

</personalization>

</webParts>

This code also shows that you can even configure the specific users for which personalization is enabled or disabled. You do this through the <authorization> element; this element works the same way as the <authorization> element you learned about in Chapter 23.

Clearing Personalization

How can you delete personalization information from the store? To do this, you can use the Personalization property of the WebPartManager class; this gives you access to the personalization provider, the settings, and the functions for resetting personalization information. You can do

this as follows:

if (MyPartManager.Personalization.HasPersonalizationState) MyPartManager.Personalization.ResetPersonalizationState();

You can then include functionality in your application for resetting personalization in this way. This could be an administration page, for example.

Summary

In this chapter, you learned how to create real-world web part pages. Such pages include requirements such as personalization as well as a modularized structure through web parts that enable the user to select exactly the information that should be displayed. You also learned what WebPartManagers, WebPartZones, and WebParts are and what their tasks are.

Then you learned about important advanced features such as connecting web parts and authorizing web parts. You also know how to add custom properties to WebParts that will be stored on a per-user or shared basis, and you created custom editors for editing those properties.

The ASP.NET 2.0 Web Parts Framework provides you with a huge set of functionality. You never have to implement your own portal framework, as it is already included with the framework. And, as it is part of the .NET Framework, you get this all for free!

P A R T 6

■ ■ ■

Web Services

C H A P T E R 3 2

■ ■ ■

Creating Web Services

For years, software developers and architects have struggled to create software components that can be called remotely over local networks and the Internet. In the process, several new technologies and patched-together proprietary solutions were created. Although some of these technologies have been quite successful running back-end systems on internal networks, none has met the challenges of the Internet—a wide, sometimes unreliable, network of computers running on every type of hardware and operating system possible.

This is where XML web services enter the scene. To interact with a web service, you simply need to send an XML message over HTTP. Because every Internet-enabled device supports HTTP, and virtually every programming language has access to an XML parser, there are few limits on what types of applications can use web services. In fact, most programming frameworks include higher-level toolkits that make communicating with a web service as easy as calling a local function.

This chapter provides an overview of web services and the problems they solve. If you are new to web services, you’ll learn how to create and consume them in ASP.NET. However, you won’t dive into the lower-level details of the underlying protocols just yet. Instead, you’ll get started using a web service and then learn to extend it in the next chapter.

WEB SERVICE CHANGES IN .NET 2.0

If you’ve programmed with web services in .NET 1.x, you’re probably wondering what has changed in .NET 2.0. From a practical point of view, surprisingly little is new—in fact, the underlying infrastructure is completely the same. However, you will find a number of useful refinements, many of which deal with how web services work with complex types (custom data classes that are used to send or retrieve information to a web method). The changes include the following:

Support for property procedures: If you have a web service that uses a custom type, .NET creates a copy of that class in the client. In .NET 1.x, this automatically generated class is built out of public properties. In

.NET 2.0, it uses property procedures instead. This minor switch doesn’t change how the web service works, but it allows you to use the class in data binding scenarios.

Type sharing: .NET now recognizes when two web services use the same complex type and generates only one client-side class. Best of all, because both proxy classes use the same types, you can easily retrieve an object from one web service and send it directly to another.

Custom serialization: You can now plug into the serialization process for custom classes to take complete control over their XML representation. Although this could be done in ASP.NET 1.x, it was undocumented and unsupported.

1087