1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional C# 2008 phần 8 potx

185 281 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Advanced WPF
Trường học University of Science and Technology
Chuyên ngành Computer Science
Thể loại bài viết
Năm xuất bản 2008
Thành phố Hanoi
Định dạng
Số trang 185
Dung lượng 3,75 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

As with the ElementHost class used to host a WPF control inside Windows Forms, now you need a wrapper that is a WPF control to host a Windows Forms control.. This assembly contains a con

Trang 1

< StopStoryboard BeginStoryboardName=”beginMoveEye” / >

< /EventTrigger >

< /DockPanel.Triggers >

to allow you to control the animation with a stop request

public partial class Window1 : System.Windows.Window {

public Window1() {

InitializeComponent();

startAnimationButton.Click += OnStartAnimation;

stopAnimationButton.Click += OnStopAnimation;

} void OnStartAnimation(object sender, RoutedEventArgs e) {

moveEye.Begin(eye, true);

} void OnStopAnimation(object sender, RoutedEventArgs e) {

moveEye.Stop(eye);

} }

Now, you can start the application and watch the eye move as soon as one of the Start buttons is clicked

Storyboard

The Storyboard class inherits from the base class Timeline but can contain multiple timelines The

Storyboard class can be used to control timelines The following table describes the methods of the Storyboard class

Storyboard Methods Description

CreateClock() The CreateClock() method returns a Clock object that you can use to

control the animations

Trang 2

Storyboard Methods Description

Pause()Resume() With Pause() and Resume() , you can pause and resume animations

Seek() With the Seek() method, you can jump in time and move the animation

to a specified time interval

Stop() The Stop() method halts the clock and stops the animation

The EventTrigger class makes it possible to define actions when events occur The following table

describes the properties of this class

EventTrigger Properties Description

RoutedEvent With the RoutedEvent property, you can define the event when the

trig-ger should start; for example, a Click event of a Button

SourceName The SourceName property defines to what WPF element the event

should connect

Trigger actions that you can put within an EventTrigger are listed in the following table You ’ ve seen

the BeginStoryboard and StopStoryboard actions in the example, but the following table shows

Trang 3

Adding 3 - D Features in WPF

This section gives you an introduction to the 3 - D features of WPF Here you’ll find the information to get started

The namespace for 3 - D with WPF is System.Windows.Media.Media3D

To understand 3 - D with WPF it is important to know the difference of the coordination system Figure

35 - 22 shows the coordination system of WPF 3 - D The origin is placed in the center The x - axis has positive values to the right and negative values to the left The y - axis is vertical with positive values up and negative values down The z - axis defines positive values in direction to the viewer

ViewPort3D ViewPort3D defines the rendering surface for 3 - D objects This element

contains all the visual elements for 3 - D drawing

ModelVisual3D ModelVisual3D is contained in a ViewPort3D and contains all the visual

elements You can assign a transformation to a complete model

GeometryModel3D GeometryModel3D is contained within a ModelVisual3D and consists of

a mesh and a material

Geometry3D Geometry3D is an abstract base class to define geometric shapes The

con-crete class that derives from Geometry3D is MeshGeometry3D With MeshGeometry3D you can define positions of triangles to build a

3 - D model

Trang 4

Class Description

Material Material is an abstract base class to define the front and back side from

the triangles defined with the MeshGeometry3D Material is contained within a GeometryModel3D NET 3.5 defines several material classes, such as DiffuseMaterial , EmissiveMaterial , and

SpecularMaterial Depending on the material type, the light calculates differently EmissiveMaterial behaves with lighting calculations that the material emits the light equal to the color of the brush

DiffuseMaterial lights with a diffuse light, and SpecularMaterial defines a specularly lit model With the MaterialGroup class you can cre-ate a combination consisting of other materials

Light Light is the abstract base class for lighting Concrete implementations are

AmbientLight , DirectionalLight , PointLight and SpotLight

AmbientLight is an unnatural light that lights the complete scene larly You will not see edges using that light DirectionalLight defines

simi-a directed light Sunlight is simi-a exsimi-ample of directed light The light comes from one side and here you can see edges and shadows PointLight is a light with a specified position and lights in all directions SpotLight lights in a specified direction This light defines a cone so you can get a very intensive illuminated area

Camera Camera is the abstract base class for the camera that is used to map the 3 - D

scene to a 2 - D display Concrete implementations are PerspectiveCamera ,

OrthographicCamera , and MatrixCamera With the

PerspectiveCamera the 3 - D objects are smaller the further away they are

This is different with the OrthographicCamera Here the distance of the camera doesn ’ t influence the size With the MatrixCamera you can define the view and transformation in a matrix

Transform3D Transform3D is the abstract base class for 3 - D transformations Concrete

implementations are RotateTransform3D , ScaleTransform3D ,

TranslateTransform3D , MatrixTransform3D , and

Transform3DGroup TranslateTransform3D allows transforming an object in the x, y, and z direction ScaleTransform3D allows for an object resize With the RotateTransform3D class you can rotate the object defined by an angle in the x, y, and z direction With Transform3DGroup you can combine other transformations

Triangle

This section starts with a simple 3 - D sample A 3 - D model is made up of triangles, so a simple model

is just one triangle The triangle is defined by the Positions property of the MeshGeometry3D

The three points all use the same z coordinate, – 4, and x/y coordinates – 1 – 1, 1 – 1, and 0 1 The property

TriangleIndices indicates the order of the positions in a counterclockwise way With this property

you define which side of the triangle is visible One side of the triangle shows the color defined with

the Material property of the GeometryModel3D class, and the other side shows the BackMaterial

property

Trang 5

The camera that is used to show the scenario is positioned at the coordinates 0, 0, 0, and looks into the direction 0, 0, – 8 Changing the camera position to the left side, the rectangle moves to the right and vice versa Changing the y position of the camera, the rectangle appears larger or smaller

The light that is used in this scene is an AmbientLight to light up the complete scene with a white light Figure 35 - 23 shows the result of the triangle

< ModelVisual3D.Content >

< GeometryModel3D >

< GeometryModel3D.Geometry >

< MeshGeometry3D Positions=”-1 -1 -4, 1 -1 -4, 0 1 -4”

Trang 6

Changing Lights

Figure 35 - 23 just shows a simple triangle where you can get the same result with less effort using 2 - D

However, from here you can continue getting into 3 - D features For example, by changing the light from

an ambient light to a spotlight with the element SpotLight you can immediately see a different

appearance of the triangle With the spotlight you define a position where the light is placed, and the

position to which the light is directed Specifying - 1 1 2 for the position, the light is placed at the left

corner of the triangle and the y coordinate to the height of the triangle From there the light is directed

down and to the left You can see the new appearance of the triangle in Figure 35 - 24

Trang 7

Adding Textures

Instead of using a solid color brush with the materials of the triangle, you can use a different brush such

as the LinearGradientBrush as shown with the following XAML code The LinearGradientBrush element defined with DiffuseMaterial defines gradient stops with the colors yellow, orange, red, blue, and violet To map a 2 - D surface from an object such as the brush to a 3 - D geometry, the

TextCoordinates property must be set TextCoordinates defines a collection of 2 - D points that map

to the 3 - D positions Figure 35 - 25 shows the 2 - D coordinates of the brush from the sample application The first position in the triangle, – 1 – 1, maps to the brush coordinates 0 1; the position 1 – 1, which is the lower corner on the right, maps to 1 1 of the brush, which is violet; and 0 1 maps to 0.5 0 Figure 35 - 26 shows the triangle with the material of the gradient brush, again with the ambient light

TriangleIndices=”0, 1, 2”

TextureCoordinates=”0 1, 1 1, 0.5 0” / >

< /GeometryModel3D.Geometry >

< GeometryModel3D.Material >

< GradientStop Color=”Yellow” Offset=”0” / >

< GradientStop Color=”Orange” Offset=”0.25” / >

< GradientStop Color=”Red” Offset=”0.50” / >

< GradientStop Color=”Blue” Offset=”0.75” / >

y

x

1

10/0

Figure 35-25

(continued)

Trang 8

< GradientStop Color=”Violet” Offset=”1” / >

You can add text or other controls in a similar way to the materials To do this you just need to create

a VisualBrush with the elements that should be painted The VisualBrush is discussed in

Chapter 34 , “ Windows Presentation Foundation ”

3 - Dimensional Object

Now let ’ s get into a real three - dimensional object: a box The box is made up of five rectangles: the back,

front, left, right, and bottom sides Each rectangle is made up of two triangles because this is the core of a

mesh With WPF and 3 - D the term mesh is used to describe the triangle primitive for building 3 - D

shapes

Here is the code of the rectangle for the front side of the box that consists of two triangles The positions

of the triangles are set in a counterclockwise order as defined by the TriangleIndices The front

side of the rectangle is done with a red brush; the back side with a gray brush Both of these brushes

are of type SolidColorBrush and defined with the resources of the Window

Trang 9

The other rectangles look very similar, just with different positions Here you can see the XAML code

of the left side of the box:

< ! Left side >

< GeometryModel3D >

< GeometryModel3D.Geometry >

< MeshGeometry3D Positions=”-1 -1 1, -1 1 1, -1 -1 -1, -1 -1 -1, -1 1 1, -1 1 -1”

All the rectangles are combined within a Model3DGroup , so one transformation can be done with all the sides of the box:

< /Model3DGroup >

With the Transform property of the Model3DGroup element, all the geometries inside this group can be transformed Here a RotateTransform3D is used that defines an AxisAngleRotation3D To rotate the box during runtime, the Angle property is bound to the value of a Slider control

< ! Transformation of the complete model >

< /RotateTransform3D.Rotation >

< /RotateTransform3D >

< /Model3DGroup.Transform >

Trang 10

To see the box, a camera is needed Here the PerspectiveCamera is used so that the box gets smaller

the further the camera is The position and direction of the camera can be set during runtime

The other light source is a SpotLight With this light source it is possible to highlight a specific area

on the box The SpotLight defines the properties InnerConeAngle and OuterConeAngle to define the

area of the full illumination:

Direction=”{Binding Path=Text, ElementName=spotDirection}”

Position=”{Binding Path=Text, ElementName=spotPosition}”

Range=”{Binding Path=Value, ElementName=spotRange}” / >

< /ModelVisual3D.Content >

< /ModelVisual3D >

When running the application you can change the rotation of the box, the camera, and lights as shown in

Figure 35 - 27

Creating a 3 - D model that consists of just rectangles or triangles is easy to do You would not manually

create more complex models; instead you would use one of several tools You can find 3 - D tools for WPF

at www.codeplex/3DTools

Trang 11

Windows Forms Integration

Instead of rewriting your user interface completely from scratch for WPF, you can use existing Windows Forms controls within WPF applications, and create new WPF controls to be used within Windows Forms applications The best way of integrating Windows Forms and WPF is by creating controls and

integrating the controls in the application types of the other technology

The integration of Windows Forms and WPF has a big drawback If you integrate Windows Forms with WPF, the Windows Forms controls still look like they looked in the old days Windows Forms controls and applications don ’ t get the new look of WPF From a user interface standpoint, it would be better to rewrite the UI completely

To integrate Windows Forms and WPF, you need classes from the namespace System

Windows.Forms.Integration in the assembly WindowsFormsIntegration

WPF Controls Within Windows Forms

You can use WPF controls within a Windows Forms application A WPF element is a normal NET class However, you cannot use it directly from the Windows Forms code; a WPF control is not a Windows Forms control The integration can be done by the wrapper class ElementHost from the namespace

System.Windows.Forms.Integration ElementHost is a Windows Forms control, because it derives from System.Windows.Forms.Control , and can be used like any other Windows Forms control in a Windows Forms application ElementHost hosts and manages WPF controls

Figure 35-27

Trang 12

Let ’ s start with a simple WPF control With Visual Studio 2008, you can create a WPF User Control

Library The sample control is derived from the base class UserControl and contains a grid and a

button with a custom content:

< Canvas Height=”230” Width=”230” >

< Ellipse Canvas.Left=”50” Canvas.Top=”50” Width=”100” Height=”100”

Stroke=”Blue” StrokeThickness=”4” Fill=”Yellow” / >

< Ellipse Canvas.Left=”60” Canvas.Top=”65” Width=”25” Height=”25”

Stroke=”Blue” StrokeThickness=”3” Fill=”White” / >

< Ellipse Canvas.Left=”70” Canvas.Top=”75” Width=”5” Height=”5”

You can create a Windows Forms application by selecting the Windows Forms Application

template Because the WPF user control project is in the same solution as the Windows Forms

application, you can drag and drop the WPF user control from the toolbox to the designer surface of

the Windows Forms application This adds references to the assemblies PresentationCore ,

PresentationFramework , WindowsBase , WindowsFormsIntegration , and of course, the assembly

containing the WPF control

Within the designer - generated code you will find a variable referencing the WPF user control and an

object of type ElementHost that wraps the control:

private System.Windows.Forms.Integration.ElementHost elementHost1;

private WPFControl.UserControl1 userControl11;

In the method InitializeComponent you can see object initializations and the assigning of the WPF

control instance to the Child property of the ElementHost class:

private void InitializeComponent()

Trang 13

this.elementHost1.Location = new System.Drawing.Point(39, 44);

Windows Forms Controls Within WPF Applications

You can integrate Windows Forms and WPF in the other direction as well by placing a Windows Forms control within a WPF application As with the ElementHost class used to host a WPF control inside Windows Forms, now you need a wrapper that is a WPF control to host a Windows Forms control This class has the name WindowsFormsHost and is in the same assembly, WindowsFormsIntegration The class WindowsFormsHost is derived from the base classes HwndHost and FrameworkElement , and thus can be used as a WPF element

For this integration, a Windows Control Library is created first Add a TextBox and Button control to the form by using the Designer To change the Text property of the button, the property ButtonText is added to the code behind:

public partial class UserControl1 : UserControl {

public UserControl1() {

InitializeComponent();

}

Figure 35-28

(continued)

Trang 14

public string ButtonText

{

get { return button1.Text; }

set { button1.Text = value; }

}

}

In the WPF application, you can add a WindowsFormsHost object from the toolbox to the Designer This

adds a reference to the assemblies WindowsFormsIntegration , System.Windows.Forms , and the

assembly of the Windows Forms control To use the Windows Forms control from XAML, you must add

an XML namespace alias to reference the NET namespace Because the assembly containing the

Windows Forms control is in a different assembly than the WPF application, you also must add the

assembly name to the namespace alias The Windows Forms control can now be contained within the

WindowsFormsHost element as shown You can assign a value for the property ButtonText directly

from XAML similarly to NET Framework elements

< WindowsFormsHost Grid.Row=”0” Height=”180” >

< winforms:UserControl1 x:Name=”myControl” ButtonText=”Click Me!” / >

< /WindowsFormsHost >

< StackPanel Grid.Row=”1” >

< TextBox Margin=”5,5,5,5” Width=”140” Height=”30” > < /TextBox >

< Button Margin=”5,5,5,5” Width=”80” Height=”40” > WPF Button < /Button >

< /StackPanel >

< /Grid >

< /Window >

You can see a view of the WPF application in Figure 35 - 29 Of course, the Windows Forms control still

looks like a Windows Forms control and does not have all the resizing and styling features you get

with WPF

(continued)

Figure 35-29

Trang 15

WPF Browser Application

Visual Studio 2008 has another WPF project template: a WPF Browser Application Such an application can run within Internet Explorer, but still the NET Framework version that you use must be installed with the client system Here you get the features of the rich client to the browser However, with WPF Browser Applications, the NET Framework is required to be available on the client system, and only Internet Explorer is supported

Creating such a project type, an XBAP (XAML Browser Application) file is created XBAP is an XML file that defines the application and the assemblies it consists of for ClickOnce deployment

An XBAP application is a partial - trust application You can use only NET code that is available with the Internet permissions

ClickOnce is explained in Chapter 16 , “ Deployment ” WPF Browser Applications are different from Silverlight Silverlight defines a subset of WPF that does not require the NET Framework to be installed with the client system Silverlight requires an add - in with the browser but supports different browsers and different operating systems Silverlight 1.0 cannot

be programmed using NET; you can use only JavaScript for accessing the XAML elements matically Silverlight 1.1 will support the NET Microframework

Summar y

This chapter covered some more features of WPF

WPF data binding gives a leap forward compared to Windows Forms You can bind any property of a NET class to a property of a WPF element The binding mode defines the direction of the binding You can bind NET objects and lists, and define a data template to create a default look for a NET class with a data template

Command binding makes it possible to map handler code to menus and toolbars You ’ ve also seen how easy it is to do copy and paste with WPF because a command handler for this technology is already included in the TextBox control

Animation allows the user to dynamically change every property of a WPF element Animations can be very decent and not annoying and make the UI more responsive and attractive for the user

WPF also allows for an easy 3 - D mapping to the 2 - D surface of a screen You ’ ve seen how to create a 3 - D model and view it with the help of different light sources and cameras

This and the previous chapter gave you an overview of WPF and enough information to get started with this technology For more information on WPF, you should read a book that focuses on WPF; for exam- ple, Professional WPF Programming: NET Development with the Windows Presentation

Foundation by Chris Andrade et al (Wiley Publishing, 2007)

Trang 17

Add - Ins

Add - ins allow you to add functionality to an application at a later time You can create a hosting application that gains more and more functionality over time — functionality that might be written by your developer team but also different vendors can extend your application by creating add - ins

Today, add - ins are used with many different applications, such as Internet Explorer and Visual Studio Internet Explorer is a hosting application that offers an add - in framework that is used by many companies to offer extensions when viewing Web pages The Shockwave Flash Object allows you to view Web pages with Flash content The Google toolbar offers specific Google features that can be accessed quickly from Internet Explorer Visual Studio also has an add - in model that allows you to extend Visual Studio with different levels of extensions

For your custom applications it has always been possible to create an add - in model to dynamically load and use functionality from assemblies With an add - in model many issues need to be thought about How can new assemblies be detected? How can versioning issues be resolved? Can the add - in change the stability of the hosting application?

The NET Framework 3.5 offers a framework for hosting and creating add - ins with the assembly System.AddIn This framework is also known by the name Managed AddIn Framework (MAF)

Add - ins are also known by different terms such as “ add - on ” or “ plug - in ”

Topics covered in this chapter are System.AddIn architecture Creating a simple add - in

Trang 18

to resolve these issues In this section, you read about the issues of add - ins and how the architecture of

MAF solves them:

Issues with add - ins

Issues with Add - ins

Creating a hosted application that dynamically loads assemblies that are added at a later time has

several issues that must be dealt with, as shown in the table that follows

Add-Ins Issues Description

different options One way is to add information about add-ins to a tion file This has the disadvantage that the installation of new add-ins needs to change an existing configuration file Another option is to just copy the assem-bly containing the add-in to a predefined directory and read information about the assembly with reflection

configura-You can read more about reflection in Chapter 13, “Reflection.”

the new operator to create an instance You can create such assemblies with the

Activator class Also, different activation options might apply if the add-in is loaded within a different application domain or a new process.Assemblies and application domains are described in Chapter 17, “Assemblies.”

with Internet Explorer crashes caused by various add-ins Depending on the type of the hosting application and how the add-ins are integrated, the add-in can be loaded within a different application domain or also within a different process

collector cannot help here because add-ins might be active in a different application domain or a different process Other ways to keep the object in memory are reference count or leasing and sponsoring mechanisms

version of the host still can load old add-ins, and an old host should have the option to load newer add-ins

Trang 19

Now let ’ s look at the architecture of MAF and how this framework solves these issues The design of MAF was influenced by these goals:

It should be easy to develop add - ins

Finding add - ins during runtime should be performant

Developing hosts should be an easy process as well, but not as easy as developing add - ins

The add - in and the host application should progress independently

Pipeline Architecture

The MAF architecture is based on a pipeline of seven assemblies This pipeline solves the versioning issues with add - ins Because the assemblies from the pipeline have a very light dependency, it is possible that the contract, the hosting, and the add - in applications progress with new versions completely independent of one another

Figure 36 - 1 shows the pipeline of the MAF architecture In the center is the contract assembly This assembly contains a contract interface that lists methods and properties that must be implemented by the add - in and can be called by the host Left of the contract is the host side, and on the right, the add - in side

In the figure you can see the dependencies between the assemblies The host assembly shown leftmost does not have a real dependency to the contract assembly; the same is true of the add - in assembly Both

do not really implement the interface that is defined by the contract Instead, they just have a reference to

a view assembly The host application references the host view; the add - in references the add - in view

The views contain abstract view classes that define methods and properties as defined by the contract

Add-In Adapter

Add-In

Figure 36-1 Figure 36 - 2 shows the relationship of the classes from the pipeline The host class has an association with the abstract host view class and invokes its methods The abstract host view class is implemented by the host adapter Adapters make the connection between the views and the contract The add - in adapter implements the methods and properties of the contract This adapter contains a reference to the add - in view and forwards calls from the host side to the add - in view The host adapter class defines a concrete class that derives from the abstract base class of the host view to implement the methods and properties This adapter includes a reference to the contract to forward calls from the view to the contract

Figure 36-2

Trang 20

With this model it is possible that the add - in side and the host side emerge completely independent Just the

mapping layer needs to adapt For example, if a new version of the host is done that uses completely new

methods and properties, the contract can still stay the same and only the adapter needs to change It is also

possible that a new contract is defined Adapters can change, or several contracts can be used in parallel

Discovery

How can new add - ins be found for the hosting application? The MAF architecture uses a predefined

directory structure to find add - ins and the other assemblies of the pipeline The components of the

pipeline must be stored in these subdirectories:

All these directories with the exception of the AddIns directory directly contain the assembly of the

specific part of the pipeline The AddIns directory contains subdirectories for every add - in assembly

With add - ins, it is also possible to store them in directories that are completely independent of the other

pipeline components

The assemblies of the pipeline are not just loaded dynamically to get all the information about the add - in

using reflection With many add - ins, this would increase the startup time of the hosting application

Instead, MAF uses a cache with information about the pipeline components The cache is created by the

program installing the add - in or by the hosting application if the hosting application has write access to

the directory of the pipeline

The cache information about the pipeline components is created by invoking methods of the

AddInStore class The method Update() finds new add - ins that are not already listed with the store

files The Rebuild() method rebuilds the complete binary store file with information about the add - ins

The following table lists the members of the AddInStore class

pipe-FindAddIn()

FindAddIns()

These methods are used to find add-ins by using the cache The method

FindAddIns() returns a collection of all add-ins that match the host view The FindAddIn() method returns a specific add-in

Trang 21

Activation and Isolation

The FindAddIns() method of the AddInStore class returns a collection of AddInToken objects that represent an add - in With the AddInToken class, you can access information about the add - in such as name, description, publisher, and version You can activate the add - in by using the Activate() method The following table lists properties and methods of the AddInToken class

AddInToken Members Description

NamePublisherVersionDescription

The Name, Publisher, Version and Description properties of the

AddInToken class return information about an add-in that was assigned

to the add-in with the attribute AddInAttribute

AssemblyName AssemblyName returns the name of the assembly that contains the add-in

EnableDirectConnect With the property EnableDirectConnect you can set a value that the

host should directly connect to the add-in instead of using the nents of the pipeline This is only possible if the add-in and the host are running in the same application domain, and the types of the add-in view and the host view are the same With this it is still required that all components of the pipeline exist

compo-QualificationData The add-in can mark appdomain and security requirements with the

attribute QualificationDataAttribute The add-in can list ments for security and isolation requirements For example,

require-[QualificationData(“Isolation”, “NewAppDomain“)] means that the add-in requires to be hosted in a new process You can read this information from the AddInToken to activate the add-in with the speci-fied requirements In addition to appdomain and security requirements, you can use this attribute to pass custom information through the pipeline

Activate() The add-in is activated with the Activate() method With parameters

of this method, you can define if the add-in should be loaded inside a new application domain or a new process You can also define what permissions the add-in gets

One add - in can break the complete application You may have seen Internet Explorer crash because of a failing add - in Depending on the application type and the add - in type, you can avoid this by letting the add - in run within a different application domain or within a different process MAF gives you several options here You can activate the add - in in a new application domain or a new process The new application domain might also have restricted permissions

The Activate() method of the AddInToken class has several overloads where you can pass the environment into which the add - in should be loaded The different options are listed in the following table

Trang 22

Parameters of

AddInToken.Activate()

Description

AppDomain You can pass a new application domain into which the add-in should

be loaded This way you can make it independent of the host application, and it can also be unloaded with the application domain

AddInSecurityLevel If the add-in should run with different security levels you can pass a

value of the AddInSecurityLevel enumeration Possible values are

Internet, Intranet, FullTrust, and Host

PermissionSet If the predefined security levels are not specific enough, you can also

assign a PermissionSet to the appdomain of the add-in

AddInProcess Add-ins can also run within a different process from the hosting

appli-cation You can pass a new AddInProcess to the Activate() method

The new process can shut down if all add-ins are unloaded, or it can keep running This is an option that can be set with the property

KeepAlive

AddInEnvironment Passing an AddInEnvironment object is another option to define the

application domain where the add-in should be loaded With the constructor of AddInEnvironment, you can pass an AppDomain object

You can also get an existing AddInEnvironment of an add-in with the

AddInEnvironment property of the AddInController class

Application domains are explained in Chapter 17 , “ Assemblies ”

The type of application may restrict the choices you have WPF add - ins currently do not support

crossing processes With Windows Forms, it is not possible to have Windows controls connected across

different application domains

Let ’ s get into the steps of the pipeline when the Activate() method of an AddInToken is invoked:

1 The application domain is created with the permissions specified

2 The assembly of the add - in is loaded into the new application domain with the Assembly

.LoadFrom() method

3 The default constructor of the add - in is invoked by using reflection Because the add - in derives

from the base class that is defined with the add - in view, the assembly of the view is loaded as well

4 Next, an instance of the add - in side adapter is constructed The instance of the add - in is passed

to the constructor of the adapter, so the adapter can connect the contract to the add - in The

add - in adapter derives from the base class MarshalByRefObject , so it can be invoked across

application domains

5 The activation code returns a proxy to the add - in side adapter to the application domain of the

hosting application Because the add - in adapter implements the contract interface, the proxy

contains methods and properties of the contract interface

6 An instance of the host side adapter is constructed in the application domain of the hosting

application The proxy of the add - in side adapter is passed to the constructor The activation

finds the type of the host - side adapter from the add - in token

The host side adapter is returned to the hosting application

Trang 23

Contracts

Contracts define the boundary between the host side and the add - in side Contracts are defined with an interface that needs to derive from the base interface IContract The contract should be well - thought in that it supports flexible add - in scenarios as needed

Contracts are not versionable and may not be changed so that previous add - in implementations can still run in newer hosts New versions are created by defining a new contract

There ’ s some restriction on the types you can use with the contract The restriction exists because of versioning issues and also because application domains are crossed from the hosting application to the add - in The types need to be safe and versionable, and able to pass it across the boundaries (application domain or cross - process) to pass it between hosts and add - ins

Possible types that can be passed with a contract are:

Primitive types Other contracts Serializable system types Simple serializable custom types that consists of primitive types, contracts, and do not have an implementation

The members of the IContract interface are explained in the following table

QueryContract() With QueryContract() it is possible to query a contract to verify

if another contract is implemented as well An add-in can support several contracts

RemoteToString() The parameter of QueryContract() requires a string

representa-tion of the contract RemoteToString() returns a string representation of the current contract

AcquireLifetimeToken()RevokeLifetimeToken()

The client invokes AcquireLifetimeToken() to keep a ence to the contract AcquireLifetimeToken() increments a reference count RevokeLifetimeToken() decrements a reference count

refer-RemoteEquals() RemoteEquals() can be used to compare two contract references

Contract interfaces are defined in the namespaces System.AddIn.Contract , System.AddIn.Contract.Collections , and System.AddIn.Contract.Automation The following table lists contract interfaces that you can use with a contract:

Trang 24

Contract Description

IListContract<T> The IListContract<T> can be used to return a list of contracts

IEnumeratorContract<T> IEnumeratorContract<T> is used to enumerate the elements of

a IListContract<T>

IServiceProviderContract An add-in can offer services for other add-ins Add-ins that offer

services are known as service provider and implement the interface IServiceProviderContract With the method

QueryService() an add-in implementing this interface can be queried for services offered

IProfferServiceContract IProfferServiceContract is the interface offered by a service

provider in conjunction with IServiceProviderContract

IProfferServiceContract defines the methods

ProfferService() and RevokeService() ProfferService()

adds an IServiceProviderContract to the services offered,

RevokeService() removes it

INativeHandleContract This interface provides access to native Window handles with the

GetHandle() method This contract is used with WPF hosts to use WPF add-ins

Lifetime

How long does an add - in need to be loaded? How long is it used? When is it possible to unload the

application domain? There are several options to resolve this One option is to use reference counts

Every use of the add - in increments the reference count If the reference count decrements to zero, the

add - in can be unloaded Another option is to use the garbage collector If the garbage collector runs, and

there ’ s no more reference to an object, the object is the target of garbage collection .NET Remoting is

using a leasing mechanism and a sponsor to keep objects alive As soon as the leasing time ends,

sponsors are asked if the object should stay alive

With add - ins, there ’ s a specific issue for unloading add - ins because they can run in different application

domains and also in different processes The garbage collector cannot work across different processes

MAF is using a mixed model for lifetime management Within a single application domain, garbage

collection is used Within the pipeline an implicit sponsorship is used, but reference counting is available

from the outside to control the sponsor

Let ’ s consider a scenario where the add - in is loaded into a different application domain Within the host

application, the garbage collector cleans up the host view and the host side adapter when the reference is

not needed anymore For the add - in side, the contract defines the methods AcquireLifetimeToken()

and RevokeLifetimeToken() to increment and decrement the reference count of the sponsor These

methods do not just increment and decrement a value which could lead to release an object too early if

one party would call the revoke method too often Instead, AcquireLifetimeToken() returns an

identifier for the lifetime token, and this identifier must be used to invoke the RevokeLifetimeToken()

method So these methods are always called in pairs

Trang 25

Usually you do not have to deal with invoking the AcquireLifetimeToken() and

RevokeLifetimeToken() methods Instead you can use the ContractHandle class that invokes

AcquireLifetimeToken() in the constructor and RevokeLifetimeToken() in the finalizer

The finalizer is explained in Chapter 12 , “ Memory Management and Pointers ”

In scenarios where the add - in is loaded in a new application domain, it is possible to get rid of the loaded code when the add - in is not needed anymore MAF uses a simple model to define one add - in

as the owner of the application domain to unload the application domain if this add - in is not needed anymore An add - in is the owner of the application domain if the application domain is created when the add - in is activated The application domain is not unloaded automatically if it was created previously

The class ContractHandle is used in the host side adapter to add a reference count to the add - in The members of this class are explained in the following table

ContractHandle Members Description

Contract In the construction of the ContractHandle class, an object

imple-menting IContract can be assigned to keep a reference to it The

Contract property returns this object

Dispose() The Dispose() method can be called instead of waiting for the

gar-bage collector to do the finalization to revoke the lifetime token

AppDomainOwner() AppDomainOwner() is a static method of the ContractHandle

class that returns the add-in adapter if it owns the application domain that is passed with the method

ContractOwnsAppDomain() With the static method ContractOwnsAppDomain() you can verify

if the specified contract is an owner of the application domain

Thus, the application domain gets unloaded when the contract is disposed

Versioning

Versioning is a very big issue with add - ins The host application is developed further as are the add - ins One requirement for an add - in is that it should be possible that a new version of the host application can still load old versions of add - ins The other direction should work as well: older hosts should run newer versions of add - ins But what if the contract changes?

System.AddIn is completely independent from the implementation of the host application and add - ins This is done with a pipeline concept that consists of seven parts

Trang 26

Copy Local to False, so that the assembly does not get copied One exception is the HostApp console

project that needs a reference to the HostView project This assembly needs to be copied so it can be

found from the host application Also you need to change the output path of the generated assemblies so

that the assemblies are copied to the correct directories of the pipeline

Contracts\

This assembly contains the contract for communi-cation with the add-in

The contract is defined with an interface

AddInViews\

The CalcView assembly contains an abstract class that is referenced by the add-in This is the add-in side of the contract

This assembly contains the implementation of the add-in

CalcAddIn

Adapter

System.AddInSystem.AddIn.ContractCalcView

CalcContract

\Pipeline\

AddInSideAdapters\

CalcAddInAdapter nects the add-in view and the contract assembly and maps the contract to the add-in view

the abstract class of the host view does not need to reference any Add-In assembly and also does not have a reference to another project in the solution

System.AddIn.ContractHostView

Trang 27

The Operate() method invokes the operation within the add - in and requires an operation defined by the IOperation interface and the operands with a double array

With this contract it is possible that the add - in supports any operations that require any number of

double operands and returns one double

The attribute AddInContract is used by the AddInStore to build the cache The AddInContract attribute marks the class as an add - in contract interface

using System.AddIn.Contract;

using System.AddIn.Pipeline;

namespace Wrox.ProCSharp.AddIns{

[AddInContract]

public interface ICalculatorContract : IContract {

IListContract < IOperationContract > GetOperations();

double Operate(IOperationContract operation, double[] operands);

} public interface IOperationContract : IContract {

string Name { get; } int NumberOperands { get; } }

}

Calculator Add - In View

The add - in view redefines the contract as it is seen by the add - in The contract defined the interfaces

ICalculatorContract and IOperationContract For this, the add - in view defines the abstract class

Calculator and the concrete class Operation With Operation there ’ s not a specific implementation required by every add - in Instead, the class is already implemented with the add - in view assembly This class describes an operation for mathematical calculations with the Name and NumberOperands properties

The abstract class Calculator defines the methods that need to be implemented by the add - ins While the contract defines parameters and return types that need to be passed across appdomain - and process - boundaries, that ’ s not the case with the add - in view Here you can use types, which make it easy to write add - ins for the add - in developer The GetOperations() method returns IList < Operation > instead of

IListOperation < IOperationContract > , as you ’ ve seen with the contract assembly

The AddInBase attribute identifies the class as an add - in view for the store

using System.AddIn.Pipeline;

using System.Collections.Generic;

(continued)

Trang 28

public abstract IList < Operation > GetOperations();

public abstract double Operate(Operation operation, double[] operand);

}

public class Operation

{

public string Name { get; set; }

public int NumberOperands { get; set; }

}

}

Calculator Add - In Adapter

The add - in adapter maps the contract to the add - in view This assembly has references to both the

contract and the add - in view assemblies The implementation of the adapter needs to map the method

IListContract < IOperationContract > GetOperations() from the contract to the view

method IList < Operation > GetOperations()

The assembly includes the classes OperationViewToContractAddInAdapter and

CalculatorViewToContractAddInAdapter These classes implement the interfaces

IOperationContract and ICalculatorContract The methods of the base interface IContract can be

implemented by deriving from the base class ContractBase This class offers a default implementation

OperationViewToContractAddInAdapter implements the other members of the IOperationContract

interface and just forwards the calls to the Operation view that is assigned in the constructor

The class OperationViewToContractAddInAdapter also contains static helper methods

ViewToContractAdapter() and ContractToViewAdapter() that map Operation to

IOperationContract and the other way around

private Operation view;

public OperationViewToContractAddInAdapter(Operation view)

Trang 29

{ return new OperationViewToContractAddInAdapter(view);

} public static Operation ContractToViewAdapter(

IOperationContract contract) {

return (contract as OperationViewToContractAddInAdapter).view;

} }}

The class CalculatorViewToContractAddInAdapter is very similar to

OperationViewToContractAddInAdapter : It derives from ContractBase to inherit a default implementation of the IContract interface, and it implements a contract interface This time the

ICalculatorContract interface is implemented with the GetOperations() and Operate() methods The Operate() method of the adapter invokes the Operate() method of the view class

Calculator where IOperationContract needs to be converted to Operation This is done with the static helper method ContractToViewAdapter() that is defined with the

OperationViewToContractAddInAdapter class

The implementation of the GetOperations method needs to convert the collection

IListContract < IOperationContract > to IList < Operation > For such collection conversions, the class CollectionAdapters defines conversion methods ToIList() and ToIListContract() Here, the method ToIListContract() is used for the conversion

The attribute AddInAdapter identifies the class as an add - in side adapter for the add - in store

using System.AddIn.Contract;

using System.AddIn.Pipeline;

namespace Wrox.ProCSharp.AddIns{

[AddInAdapter]

internal class CalculatorViewToContractAddInAdapter : ContractBase, ICalculatorContract

{ private Calculator view;

public CalculatorViewToContractAddInAdapter(Calculator view) {

this.view = view;

} public IListContract < IOperationContract > GetOperations() {

return CollectionAdapters.ToIListContract < Operation, IOperationContract > (view.GetOperations(), OperationViewToContractAddInAdapter.ViewToContractAdapter, OperationViewToContractAddInAdapter.ContractToViewAdapter);

} public double Operate(IOperationContract operation, double[] operands) {

return view.Operate(

OperationViewToContractAddInAdapter.ContractToViewAdapter(

operation), operands);

} }}

Trang 30

Calculator Add - In

The add - in now contains the real implementation of the add - in The add - in is implemented by the class

CalculatorV1 The add - in assembly has a dependency on the add - in view assembly as it needs to

implement the abstract Calculator class

The attribute AddIn marks the class as an add - in for the add - in store, and adds publisher, version, and

description information On the host side, this information can be accessed from the AddInToken

CalculatorV1 returns a list of supported operations in the method GetOperations() Operate()

calculates the operands based on the operation

operations = new List < Operation > ();

operations.Add(new Operation() { Name = “+”, NumberOperands = 2 });

operations.Add(new Operation() { Name = “-”, NumberOperands = 2 });

operations.Add(new Operation() { Name = “/”, NumberOperands = 2 });

operations.Add(new Operation() { Name = “*”, NumberOperands = 2 });

return operand[0] * operand[1];

Because the adapter classes are invoked by NET reflection, it is possible that the

internal access modifier is used with these classes As these classes are an

implementation detail, it’s a good idea to use the internal access modifier.

Trang 31

default:

throw new InvalidOperationException(

String.Format(“invalid operation {0}”, operation.Name));

} } }}

Calculator Host View

Let ’ s continue with the host view of the host side Similar to the add - in view, the host view defines an abstract class with methods similar to the contract However, the methods defined here are invoked by the host application

Both the class Calculator and Operation are abstract as the members are implemented by the host adapter The classes here just need to define the interface to be used by the host application

using System.Collections.Generic;

namespace Wrox.ProCSharp.AddIns{

public abstract class Calculator {

public abstract IList < Operation > GetOperations();

public abstract double Operate(Operation operation, params double[] operand);

} public abstract class Operation {

public abstract string Name { get; } public abstract int NumberOperands { get; } }

}

Calculator Host Adapter

The host adapter assembly references the host view and the contract to map the view to the contract

The class OperationContractToViewHostAdapter implements the members of the abstract

Operation class The class CalculatorContractToViewHostAdapter implements the members of the abstract Calculator class

With OperationContractToViewHostAdapter , the reference to the contract is assigned in the constructor The adapter class also contains a ContractHandle instance that adds a lifetime reference to the contract , so that add - in stays loaded as long it is needed by the hosting application

using System.AddIn.Pipeline;

namespace Wrox.ProCSharp.AddIns{

internal class OperationContractToViewHostAdapter : Operation {

private ContractHandle handle;

public IOperationContract Contract { get; private set; } public OperationContractToViewHostAdapter(IOperationContract contract)

(continued)

Trang 32

The class CalculatorContractToViewHostAdapter implements the methods of the abstract host view

Calculator class and forwards the call to the contract Again, you can see the ContractHandle

holding the reference to the contract, which is similar to the adapter from the add - in side type

conversions This time the type conversions are just in the other direction from the add - in adapters

The attribute HostAdapter marks the class as an adapter that needs to be installed in the

private ICalculatorContract contract;

private ContractHandle handle;

public CalculatorContractToViewHostAdapter(ICalculatorContract contract)

(continued)

Trang 33

{ this.contract = contract;

handle = new ContractHandle(contract);

} public override IList < Operation > GetOperations() {

return CollectionAdapters.ToIList < IOperationContract, Operation > ( contract.GetOperations(),

OperationHostAdapters.ContractToViewAdapter, OperationHostAdapters.ViewToContractAdapter);

} public override double Operate(Operation operation, double[] operands) {

return contract.Operate(OperationHostAdapters.ViewToContractAdapter(

operation), operands);

} }}

Calculator Host

The sample host application uses the WPF technology You can see the user interface of this application

in Figure 36 - 3 On top is the list of available add - ins On the left, the operations of the active add - in are shown As you select the operation that should be invoked, operands are shown After entering the values for the operands, the operation of the add - in can be invoked

The buttons on the bottom row are used to rebuild and update the add - in store, and to exit the application

Figure 36-3

Trang 34

The XAML code that follows shows the tree of the user interface With the ListBox elements, different

styles with item templates are used to give a specific representation of the list of add - ins, the list of

operations, and the list of operands

You can read information about item templates in Chapter 35 , “ Advanced WPF ”

< DockPanel >

< GroupBox Header=”AddIn Store” DockPanel.Dock=”Bottom” >

< UniformGrid Columns=”4” >

< Button x:Name=”rebuildStore” Click=”RebuildStore”

Margin=”5” > Rebuild < /Button >

< Button x:Name=”updateStore” Click=”UpdateStore”

Margin=”5” > Update < /Button >

< Button x:Name=”refresh” Click=”RefreshAddIns”

Margin=”5” > Refresh < /Button >

< Button x:Name=”exit” Click=”App_Exit” Margin=”5” > Exit < /Button >

< /UniformGrid >

< /GroupBox >

< GroupBox Header=”AddIns” DockPanel.Dock=”Top” >

< ListBox x:Name=”listAddIns” ItemsSource=”{Binding}”

Style=”{StaticResource listAddInsStyle}” / >

< /GroupBox >

< GroupBox DockPanel.Dock=”Left” Header=”Operations” >

< ListBox x:Name=”listOperations” ItemsSource=”{Binding}”

< Button x:Name=”buttonCalculate” Click=”Calculate” IsEnabled=”False”

Margin=”5” > Calculate < /Button >

< GroupBox DockPanel.Dock=”Bottom” Header=”Result” >

< Label x:Name=”labelResult” / >

< /GroupBox >

< /StackPanel >

< /DockPanel >

In the code behind, the FindAddIns() method is invoked in the constructor of the Window

FindAddIns() uses the AddInStore class to get a collection of AddInToken objects and pass them to

the DataContext property of the ListBox listAddIns for display The first parameter of the

AddInStore.FindAddIns() method passes the abstract Calculator class that is defined by the host

view to find all add - ins from the store that apply to the contract The second parameter passes the

directory of the pipeline that is read from the application configuration file When you run the sample

application from the Wrox download site you have to change the directory in the application

configuration file to match your directory structure

Trang 35

using System.Windows.Controls;

using Wrox.ProCSharp.AddIns.Properties;

namespace Wrox.ProCSharp.AddIns{

public partial class CalculatorHostWindow : Window {

private Calculator activeAddIn = null;

private Operation currentOperation = null;

public CalculatorHostWindow() {

InitializeComponent();

FindAddIns();

} void FindAddIns() {

try { this.listAddIns.DataContext = AddInStore.FindAddIns(typeof(Calculator), Settings.Default.PipelinePath);

} catch (DirectoryNotFoundException ex) {

MessageBox.Show(“Verify the pipeline directory in the “ + “config file”);

Application.Current.Shutdown();

} } //

To update the cache of the Add - In store, the UpdateStore() and RebuildStore() methods are mapped to the Click events of the Update and Rebuild buttons Within the implementation of these methods, the Rebuild() or Update() methods of the AddInStore class are used These methods return

a string array of warnings if assemblies are stored in the wrong directories Because of the complexity of the pipeline structure, there ’ s a good chance that the first time you may not get the project configuration completely right for copying the assemblies to the correct directories Reading the returned information from these methods, you will get a clear explanation about what ’ s wrong For example, the message ” No usable AddInAdapter parts could be found in assembly Pipeline\AddInSideAdapters\CalcView.dll ” gives a hint that the assembly CalcView is stored inside the wrong directory

private void UpdateStore(object sender, RoutedEventArgs e) {

string[] messages = AddInStore.Update(Settings.Default.PipelinePath);

if (messages.Length != 0) {

MessageBox.Show(string.Join(“\n”, messages), “AddInStore Warnings”, MessageBoxButton.OK, MessageBoxImage.Warning);

} } private void RebuildStore(object sender, RoutedEventArgs e)

(continued)

Trang 36

In Figure 36 - 2 you can see an Activate button beside the available add - in Clicking this button invokes

the handler method ActivateAddIn() With this implementation, the add - in is activated by using the

Activate() method of the AddInToken class Here the add - in is loaded inside a new process that is

created with the AddInProcess class This class starts the process AddInProcess32.exe Setting the

KeepAlive property of the process to false , the process is stopped as soon as the last add - in reference

is garbage collected The parameter AddInSecurityLevel.Internet leads to an add - in running with

restricted permissions The last statement of ActivateAddIn() invokes the ListOperations()

method, which in turn invokes the GetOperations() method of the add - in GetOperations() assigns

the returned list to the data context of the ListBox listOperations for displaying all operations

private void ActivateAddIn(object sender, RoutedEventArgs e)

{

FrameworkElement el = sender as FrameworkElement;

Trace.Assert(el != null, “ActivateAddIn invoked from the wrong “ +

“control type”);

AddInToken addIn = el.Tag as AddInToken;

Trace.Assert(el.Tag != null, String.Format(

“An AddInToken must be assigned to the Tag property “ +

“of the control {0}”, el.Name);

AddInProcess process = new AddInProcess();

After the add - in is activated and the list of operations displays in the UI, the user can select an operation

The Click event of the Button shown in the Operations category is assigned to the handler method

OperationSelected() In the implementation, the Operation object that is assigned to the Tag

property of the Button is retrieved to get the number of operands needed with the operation To allow

the user adding values to the operands, an array of OperandUI objects is bound to the ListBox

listOperands

private void OperationSelected(object sender, RoutedEventArgs e)

{

FrameworkElement el = sender as FrameworkElement;

Trace.Assert(el != null, “OperationSelected invoked from “ +

“the wrong control type”);

(continued)

Trang 37

Operation op = el.Tag as Operation;

Trace.Assert(el.Tag != null, String.Format(

“An AddInToken must be assigned to the Tag property “ + “of the control {0}”, el.Name);

currentOperation = op;

ListOperands(new double[op.NumberOperands]);

} private class OperandUI {

public int Index { get; set; } public double Value { get; set; } }

void ListOperands(double[] operands) {

this.listOperands.DataContext = operands.Select((operand, index) = >

new OperandUI() { Index = index + 1, Value = operand }).ToArray();

}

The Calculate() method is invoked with the Click event of the Calculate button Here, the operands are retrieved from the UI, the operation and operands are passed to the Operate() method of the add - in, and the result is shown with the content of a label

private void Calculate(object sender, RoutedEventArgs e) {

OperandUI[] operandsUI = (OperandUI[])this.listOperands.DataContext;

double[] operands = operandsUI.Select(opui = > opui.Value).ToArray();

labelResult.Content = activeAddIn.Operate(currentOperation, operands);

}

Additional Add - Ins

The hard work is now done The pipeline components and the host application are created The pipeline

is now working, yet it ’ s an easy task to add other add - ins such as the Advanced Calculator add - in shown

in the following code segment into the host application

[AddIn(“Advanced Calc”, Publisher = “Wrox Press”, Version = “1.1.0.0”, Description = “Another AddIn Sample”)]

public class AdvancedCalculatorV1 : Calculator

The next chapter starts a sequence of three chapters for developing the UI with ASP.NET

Trang 39

ASP NET Pages

If you are new to the world of C# and NET, you might wonder why a chapter on ASP.NET has been included in this book It ’ s a whole new language, right? Well, not really In fact, as you will see, you can use C# to create ASP.NET pages

ASP.NET is part of the NET Framework and is a technology that allows for the dynamic creation

of documents on a Web server when they are requested via HTTP This mostly means HTML and XHTML documents, although it is equally possible to create XML documents, CSS files, images, PDF documents, or anything else that supports MIME types

In some ways, ASP.NET is similar to many other technologies — such as PHP, ASP, or ColdFusion

There is, however, one key difference: ASP.NET, as its name suggests, has been designed to be fully integrated with the NET Framework, part of which includes support for C#

Perhaps you are familiar with Active Server Pages (ASP) technology, which enables you to create dynamic content If you are, you will probably know that programming in this technology used scripting languages such as VBScript or JScript The result was not always perfect, at least not for those of us used to “ proper, ” compiled programming languages, and it certainly resulted in a loss

of performance

One major difference related to the use of more advanced programming languages is the provision

of a complete server - side object model for use at runtime ASP.NET provides access to all of the controls on a page as objects, in a rich environment On the server side, you also have access to other NET classes, allowing for the integration of many useful services Controls used on a page expose a lot of functionality; in fact, you can do almost as much as with Windows Forms classes, which provide plenty of flexibility For this reason, ASP.NET pages that generate HTML content

are often called Web Forms

This chapter takes a more detailed look at ASP.NET, including how it works, what you can do with

it, and how C# fits in The following is a brief outline of what is covered:

An introduction to ASP.NET How to create ASP.NET Web Forms with server controls How to bind data to ASP.NET controls with ADO.NET Application configuration

Trang 40

ASP NET Introduction

ASP.NET works with Internet Information Server (IIS) to deliver content in response to HTTP requests

ASP.NET pages are found in aspx files Figure 37 - 1 illustrates the technology ’ s basic architecture

HTTP Request for aspx Resource ASP.NET Generated resource in HTTP Response

Server Processing

of aspx Resource Result of aspx Processing

ASP.NET page in aspx Resource

Database

Other Resources

.NET Framework OS

IIS Web Server

Figure 37 - 1

During ASP.NET processing, you have access to all NET classes, custom components created in C# or

other languages, databases, and so on In fact, you have as much power as you would have running a C#

application; using C# in ASP.NET is, in effect, running a C# application

An ASP.NET file can contain any of the following:

Processing instructions for the server

Code in C#, Visual Basic NET, JScript NET, or any other language that the NET Framework

supports

Content in whatever form is appropriate for the generated resource, such as HTML

Client - side script code, such as JavaScript

Embedded ASP.NET server controls

So, in fact, you could have an ASP.NET file as simple as this:

Hello!

This would simply result in an HTML page being returned (as HTML is the default output of ASP.NET

pages) containing just this text

As you will see later in this chapter, it is also possible to split certain portions of the code into other files,

which can provide a more logical structure

State Management in ASP NET

One of the key properties of ASP.NET pages is that they are effectively stateless By default, no

information is stored on the server between user requests (although there are methods for doing this, as

you will see later in this chapter) At first glance, this seems a little strange because state management

Ngày đăng: 12/08/2014, 23:23

TỪ KHÓA LIÊN QUAN