The clients of the service will communicate with our class by submit- ting objects from the Product and Product.Category classes, and the service will return data to the client applicati
Trang 1of the service’s methods; instead of using the collections as its data source, the service will
contact a database In between sessions, you can persist the collections to an XML file, as cussed in Chapter 13, ‘‘XML in Modern Programming.’’
dis-Start a fresh instance of Visual Studio and select File New New Project Click WCF inthe Installed Templates pane, and in the pane with the matching project types, select WCF Ser-
vice Library Name the new project WCFProducts and click OK to create the project The new
project that Visual Studio will create for you contains two files: the IService1.vb class, which
is an interface that contains the signatures of the service methods, and the Service1.vb class,which contains the implementation of the methods The methods are some extremely trivial
sample methods and you can delete them right away
The first step is the design of a class that represents the entities our service knows about
Obviously, we need a Product and a Category class and I have nested the Category class withinthe Product class Both classes contain just a few properties to identify products and categories.Add the Product class to the WCF project and insert in it the code of Listing 21.4
Listing 21.4: The Product.vb class
<DataContract()>
Public Class Product
<DataMember()> Public ProductID As Integer
<DataMember()> Public ProductName As String
<DataMember()> Public ProductPrice As Decimal
<DataMember()> Public ProductCategoryID As Integer
Public Overrides Function ToString() As String
Return ProductName & " (" & ProductID & ")"
End Function
<DataContract()> Public Class Category
<DataMember()> Public CategoryID As Integer
<DataMember()> Public CategoryName As String
Public Overrides Function ToString() As String
Return CategoryName & " (" & CategoryID.ToString & ")"
End Function
End Class
End Class
This is a very simple class that describes products and categories, if you ignore the
deco-rations of the various members The entire class is marked with the DataContract attribute,
which tells the compiler that the following class contains the service’s contract: the entities ourservice knows about The clients of the service will communicate with our class by submit-
ting objects from the Product and Product.Category classes, and the service will return data
to the client application using instances of these two classes The DataMember attribute tells
the compiler that the corresponding property is a member of the contract and that it should beexposed to the clients If you have properties that you want to use in your code but not expose
to clients, just don’t mark them with the DataMember attribute
Trang 2The next step is the definition of the methods that the clients will use to contact our vice The methods must be defined in an interface class, which contains the method definitionsbut not their actual implementation This interface class contains the service’s metadata — theinformation required by a client to figure out the service’s capabilities Add the IProduct class
ser-to the project and insert the statements shown in Listing 21.5 in it (the IProduct.vb file)
Listing 21.5: Describing the Product class with an interface
This is another trivial class, except that it’s marked with the ServiceContract attribute,which tells the compiler that the class contains the service’s operations (as opposed to the ser-vice’s data structure, which was defined in the Product class) The methods are also markedwith the OperationContract attribute, which makes them available to clients Without thisattribute, the procedures would be internal methods and clients wouldn’t be able to see them
If the service exchanges simple data types with the client, this interface would be adequate.However, practical services are not limited to simple data types like integers and strings Theycommunicate with the client using business objects, which are based on custom classes Theseobjects represent customers, products, invoices, and the like If you want to make use of customobjects, you must declare them in a separate class like the Product class shown earlier
Finally, you must add yet another class to the project — this time a class that contains theactual code and implements the service This is the ProductService class in the sample project,and its code is shown in Listing 21.6 The ProductService class implements the IProduct inter-face, taking into consideration the classes defined in the Product class
Listing 21.6: The implementation of the ProductService class
<ServiceBehavior()> Public Class ProductService :
Implements IProductShared _products As New List(Of Product)
Shared _categories As New List(Of Product.Category)
Trang 3Public Function AddProduct(ByVal prod As Product) As Product
Implements IProduct.AddProduct
‘ grab the next ID in _products list
prod.ProductID =
(From p In _productsSelect p.ProductIDOrder By ProductID Descending)
End Function
Public Function GetAllProducts() As
System.Collections.Generic.List(Of Product)Implements IProduct.GetAllProducts
Return _products
End Function
Public Function RemoveProduct(ByVal ID As Integer)
As Boolean Implements IProduct.RemoveProductproducts.Remove(_products.Find(Function(p) p.ProductID = ID))
End Function
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
Public Function GetCategoryProduct(
ByVal categoryID As Integer)
As List(Of Product)Implements IProduct.GetCategoryProductsReturn (From p In _products
Where p.ProductCategoryID = categoryID).ToList
End Function
Public Sub New()
Trang 4_categories.Add(New Product.Category With{.CategoryID = 101, CategoryName = "Electronics"})_categories.Add(New Product.Category With
{.CategoryID = 102, CategoryName = "Cameras"})_categories.Add(New Product.Category With
{.CategoryID = 103, CategoryName = "Software"})End Sub
End Class
The data are stored in the _products and _categories collections, which are private to the
class, and no client can manipulate these collections directly This is the essence of the service:
It allows clients to view and manipulate the data through a well-defined interface, and the vice itself is in charge of maintaining the integrity of the data Since we don’t have a database
ser-at the back end, we’re also responsible for maintaining the IDs of the various entities Every
time a new product is added, the code retrieves the largest product ID from the _products
collection, adds 1 to it, and forms the ID of the new product The same is true for the IDs ofthe categories Notice also that every time the service is initialized, it adds three rows to the
_categories table It goes without saying that you can change the implementation of the vice so that it interacts directly with the Northwind database instead of custom collections To
ser-do so, you will change the implementation of the ProductService class without having to touchthe other two classes As a consequence, client applications will continue using your service,but with the new implementation of the service, they will be seeing the data of the Northwinddatabase
The two collections must be declared with the Shared keyword so that all instances of theservice will see the same data Had we declared the two collections with a Dim statement, anew set of collections would be created for each instance of the class invoked by a client Inother words, every client application would see its own data source
Your WCF service is ready to service clients To test it, press F5 and you will see an icon
in the lower-right corner of your screen informing you that the WcfSvcHost utility has started.This utility, which comes with Visual Studio, hosts the service and makes it available to clients
at a specific IP address and port Since WcfSvcHost is meant for testing purposes, only cations running on the same machine can connect to it Once the service has been debugged, itcan be deployed as an IIS application
appli-A few moments later you will see another window, the WCF Test Client utility, whichallows you to test your new service without writing a client application The first time yourun the project you’ll see an error message to the effect that the service doesn’t expose anymetadata This happened because you haven’t configured your application yet Right-clickthe App.config file in the Solution Explorer, and from the shortcut menu, select Edit WCFConfiguration The Configuration Editor window appears, as shown in Figure 21.11
Configuring WCF Services
A WCF service is defined by three parameters: an address where it can be reached (the point), a binding protocol, and a contract All three parameters are configurable, and you neednot edit the service code to redeploy it or to support additional bindings You only need to editthe configuration file
end-The address is an IP address or URL that specifies where the service is located It’s theaddress of the machine on which the service is running and, consequently, the address to
Trang 5which clients must connect to make requests The binding determines how the clients will
talk to a service and WCF supports multiple bindings The contract, finally, specifies what theservice does; in other words, the methods it provides The contract is the service interface,
much like the classes and methods of a namespace If you want to totally abstract a WCF
service, think of it as a namespace that’s being hosted on a remote computer Just as you cancall a method in a namespace, you can call a method of a WCF service As you saw in the firstexample of this chapter, you can access a remote service from within your project by adding
a reference to the service With that reference in place, Visual Studio will take care of the
housekeeping needed to connect to the remote service (what’s also known as the plumbing)
Figure 21.11
The Configuration
Edi-tor’s window allows you
to configure the
parame-ters of a WCF service
The binding tells the client how the messages will be transmitted between the client and theservice Web services use HTTP to exchange data with the clients This, however, is not perfectfor all cases HTTP is a universal protocol, and it’s been implemented on every operating sys-tem, but it’s the most generic protocol Windows, as well as other operating systems, supportmessaging: a mechanism for reliably transmitting information between two computers, even ifone of them is offline When the receiving computer is connected, the message will be deliveredand processed This mechanism, which relies on Microsoft’s Message Queues, is the most reli-able mechanism for exchanging data between two computers, but this type of communicationisn’t synchronous
There are situations where the WCF service and its client are deployed on the same local
area network For these cases, there are protocols, such as Named Pipes, that perform much
faster than HTTP I can’t discuss the merits of all available bindings in this chapter This is
an advanced topic, and the goal of this chapter is to introduce you to a technique for writingapplications as services The basic techniques are within the reach of the average VB devel-
oper, and I will limit the discussion to the basic techniques for building WCF services and
Trang 6deploying them on a web server WCF allows you to build a service following the steps cussed so far and then configure them The configuration involves the specification of the end-point (the service’s address) and the binding protocol You can even implement multiple bind-ings on the same service so that different clients can contact the same service using differentprotocols.
dis-To configure the sample WCF service, you must first change the name of the service.Although you changed the default name of the service, the configuration file still remembersthe original name, Service1, which was the name of the sample class that was generated auto-matically and that we removed from the project Click the WCFProducts.Service1 item in theleft pane of the Configuration Editor, which was shown in Figure 21.11, and then select theName property in the right pane Click the button with the ellipsis next to the service’s nameand the Service Type Browser dialog box will open, as shown in Figure 21.12 This dialog box
is similar to the Open dialog box, which allows you to select a file Navigate to the project’sBin/Debug folder and select the WCFProducts.dll file Click open, or double-click the file’sname to see the names of all services implemented in the DLL You will see a single service
name, the WCFProducts.ProductService name Select it and the close the dialog box by
clicking the OK button
to WCFProducts.IProduct interface While configuring the first endpoint, set its name to
HTTPBinding.Now select the second endpoint and you’ll see that it implements the mexHttpBinding, asshown in Figure 21.13 This binding provides the service’s metadata and you need not change
its settings Just set its name to MEXBinding, so that it won’t be displayed as (Empty Name).
Trang 7Figure 21.13
Configuring an endpoint
of a WCF service
Save the configuration with the Save command from the File menu and close the
Config-uration Editor Now you’re ready to test the service Press F5 again and this time the WCF
Test Client window appears, as shown in Figure 21.14 The WCF Test Utility window
con-sists of two panes: on the left pane you see all the methods of the service (you must expand
the service’s interface to see the names of the methods), and on the right pane you can call theselected method and see the results To see the categories shown in Figure 21.14, for example,
I double-clicked the GetAllCategories item in the left pane and then I clicked the Invoke ton The utility called the GetAllCategories method and displayed the results in the lower
but-part of the pane
You can use the WCF Test Client utility to test the methods of your new service, but tually you must host your service to a web server, or an application, and call it from anotherWindows or web client
even-You can also test the methods that submit data to the service If you double-click the
AddProductmethod name, a new tab will open in the right pane, as shown in Figure 21.15, andyou’ll be prompted to enter values for the method parameters Specify the parameter values
(you don’t have to provide a value for the ProductID parameter; this value is assigned
auto-matically by the service) and then click the Invoke button The utility will call the AddProductmethod, and if executed successfully, it will display the new product in the lower half of thetab, as shown in the figure
Note that the new product’s ID is included in the result of the method because the methodreturns an object of the Product type that represents the newly inserted row
Implementing a web or WCF service is no different from implementing a class that exposescertain functionality through a set of methods and communicates with another application byexchanging specific types The only difference between a class you’d use in a Windows applica-tion and a service is that the members of the service are marked with special attributes More-over, when it comes to WCF services, you must also configure them with the Configuration
Editor
Trang 8Figure 21.14
Testing the methods of
the new WCF service
in the WCF Test Client
utility
Figure 21.15
Submitting a new
product to the
Product-Service service through
the WCF Test Client
ADO.NET Data Services
Before ending this chapter, I’d like to show you briefly how to create services that expose anentire database This type of service comes as a special project component of Visual Studio, theADO.NET Data Services component An ADO.NET Data service is a web service that exposes
an entire database, or part of it, as a web service What’s special about this component is thatit’s generated automatically for you; all you have to do is specify the tables you want to expose
Trang 9and a wizard will generate the service for you The data source can be a database, an Entity
Data Model (EDM), or a collection of custom objects There’s nothing new to learn and you cancreate and use data services immediately, with the exception of some techniques for securingyour data The data service will expose methods to both query and update the data source, butyou obviously don’t want to give access to your database to anyone on the Web
Let’s start the exploration of data services by building a new project, the DataService project;you can download it from this URL: www.sybex.com/go/masteringvb2010 Create a new pro-ject of the ASP.NET Web Site type, since your data will be exposed over HTTP As you will
see, you have no need for a website per se, just a web service that will expose the data of a
specific database (or part of it) As soon as the project is created, delete the ASPX page that
Visual Studio adds by default to any project of this type
First, you must create a data source For the purpose of this example, you’ll expose data
from the Northwind database, and to do so, you’ll create an ADO.NET Entity Data Model
by adding a new component of this type to the project Keep the default name, which is
Model1.edmx When the wizard starts, select all of the tables in the database, as you learned
in Chapter 19 For this example, I’ve included all 12 tables of the Northwind database I just
dropped them on the EDM design surface and Visual Studio generated the Model1.edmx data
model
Now that you have the data source, you can add an ADO.NET Data Service component toyour project to expose the selected tables through a web service Right-click the project nameand select Add New Item When the Add New Item dialog box opens, select the ADO.NET
Data Service Name the new service NWWebDataService Visual Studio will create the
NWWebDataService.svc file for you and will open the new data service’s code window You
will see that the new class contains just a few lines of code:
Imports System.Data.Services
Imports System.Linq
Imports System.ServiceModel.Web
Public Class NWWebDataService
‘ TODO: replace [[class name]] with your data class name
Inherits DataService(Of [[class name]])
‘ This method is called only once to initialize service-wide policies
Public Shared Sub InitializeService(
ByVal config As IDataServiceConfiguration)
‘ TODO: set rules to indicate which entity sets
‘ and service operations are visible, updatable, etc
The NWWebDataService inherits from another class, whose name you must supply
by replacing class name in the code line that reads: Inherits DataService(Of [[class
name]]) The class it derives from should be NorthwindEntities, which is the name of the
Trang 10Data Entity class you created as the project’s data source Technically, you didn’t specify theNorthwindEntities name, but Visual Studio created this class and named it after the database.The statements that are commented out specify the data you want to expose through yourdata service By default, the data service won’t expose any data unless you tell it to do so.Replace the last two statements of the InitializeService routine with the following:
config.SetEntitySetAccessRule("*", EntitySetRights.All)
This statement instructs the service to expose all resources Obviously, this is the last thingyou want to do with a real service that will be accessed from outside your test machine,and I’ll come back to the issue of security, but for now let’s grant unconditional access to alltables through your service For the purpose of this chapter, the service will be hosted by theASP.NET Development Server, which can be accessed from the same machine only
You’re probably thinking it’s time to add some real code, or look at a few thousand lines ofcode generated by the wizard This isn’t the case; your data service is complete Right-click theNWWebDataService component name, and from the context menu, select View In Browser Afew seconds later you will see a new Internet Explorer window displaying a list of all tables inthe database, as shown in Figure 21.16
Figure 21.16
The service exposes the
names of all tables in its
data source
Each table, which is an EntitySet in the data source, is exposed as a collection By appendingthe entity name to the base URL of the service, you can view the rows in the correspondingtables Change the URL in the browser address bar to any of the following to see the products,categories, and customers in the Northwind database:
http://localhost:51000/NWWebDataService.svc/Products
Trang 11http://localhost:51000/NWWebDataService.svc/Customers
As you will recall from our discussion of the Entity Framework in Chapter 17, ‘‘Using the
Entity Data Model,’’ the Products table is translated into the Products EntitySet, which is made
up of Product entities The port will be different on your machine, but you will see it on yourbrowser’s address bar as soon as you open the service in the browser This port number will
be different every time you start the application, so it wouldn’t be a bad idea to set a specificport for the service Select the DataService project in the Solution Explorer, open the Project
menu, and select DataService Properties On the Project Properties window that opens, selectthe Web tab, which is shown in Figure 21.17 On this tab, you can set the start action (what
happens when you start the project) as well as the server that will host your server For now,select the Specific Port option and set its value to the number of an unused port (I’ve used theport number 51000) If you decide to make the service public, don’t forget to limit the access
to the service (you don’t want people changing your data at will) You’ll see shortly how youcan restrict access to specific tables and even how to intercept certain operators, like insertions,modifications, and deletions, and determine whether to allow or block them from within
your code
Figure 21.17
Configuring the server
that will host the data
service
Figure 21.18 shows how the first customer, the ubiquitous ALFKI customer, is displayed
The output of the service is just XML, and you can write a client application to access the vice and process the selected rows with LINQ Notice the links to the related tables Each cus-tomer has two related tables with the following relative URLs:
ser-Orders:
Customers(’ALFKI’)/Orders
CustomerDemographics:
Customers(’ALFKI’)/CustomerDemographics
Trang 12Figure 21.18
Requesting a specific
customer through a URL
made up of the service’s
URL and the table name
To view the orders of the customer ALFKI, enter the following URL in your browser:
Trang 13a specific order by its ID and request its detail lines The following URL does exactly that (theURL should be entered as a single line; it’s been broken here to fit the printed page):
http://localhost:51000/NWWebDataService.svc/Customers(’BLAUS’)/
Orders(10501)/Order_Details
The service will return the following XML document:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
Trang 14If you examine it, you’ll see that it includes two related entities: the Order entity (the order
to which all detail lines belong) and the Product entity (the product listed in each detail line)
By default, the data service doesn’t move the related rows from the database to the client Ifyou want to view the related data, you must use the expand keyword followed by the name(s)
of the entities you wish to retrieve along with each product The following URL will bring asingle product, along with its category and supplier:
http://localhost:51000/WebDataService1.svc/
Products(12)?$expand=Category,%20Supplier
If you examine the XML returned by this query, you’ll see that it has three <link> elements,which represent the related rows in other tables: the Order Details, Categories, and Supplierstables The links to the Categories and Suppliers tables have a plus symbol in front of them,and if you click it to expand the corresponding entity, you’ll see the details of the product’scategory or supplier, as shown in Figure 21.19
Figure 21.19
Retrieving related rows
with the $expand
Trang 15the filter keyword, which must be followed by a filtering expression The following statementwill return all products with a price that exceeds $100:
http://localhost:51000/WebDataService1.svc/Products?$filter=UnitPrice gt 100
Note that the comparison operator is not the greater than sign (>) but the gt operator The
fil-tering expressions can get quite complicated because the URL syntax isn’t flexible enough forexpressing multiple criteria, joining tables together, and so on The data service allows us to getthe data we need with a simple HTTP request, but for many operations you’ll have to down-load the desired data at the client and process them locally with LINQ
The data service works very nicely, and it took us no time at all to write You’ll see shortlyhow to write client applications against this service and how to submit updates to the database
as well For now, keep in mind that an ADO.NET Data service exposes (or ‘‘surfaces’’) the data
in a data source We have used a Data Entity Model as our data source in this example, but
you can use any data source such as LINQ to SQL, or even a collection of custom objects Nomatter how you specify the data source, the data service will expose it through HTTP requests
The Basic Query Operators
For those of you who are interested in exploring the notation for URL querying further,
Table 21.1 provides a quick overview of the various operators
Table 21.1: Basic query operators
Logic operators eq (equals), ne (not equals)
gt (greater than), gteq (greater than or equal to)
lt (less than), lteq (less than or equal to)and, or, and not
Arithmetic operators add (addition), sub (subtraction), mul (multiplication), div (division),
mod (remainder)round (round decimal digits)floor (returns the largest integer that doesn’t exceed a value)ceiling (returns the smallest integer that exceeds a value)
String operators contains, endswith, startswith, length, indexof, insert,
replace, substring, tolower, toupper, trim, concat
Date/time operators Second, hour, minute, day, month, year
Type operators Isof, cast
Here are a few simple examples of the operators you can use in your filtering
expres-sions (I’m only showing the part of the URL that follows the service’s address, which is
http://localhost:51000/WebDataService1.svc/)
Trang 16Products?$filter=startswith(ProductName, Sir’)Orders?$filter=month(OrderDate) eq 2
Orders?$filter=endswith(ShipName,’markt’)
ADO.NET Data Services allows you to expose (or surface) an entire database and buildclient applications that use the service as the data source The database has already beenexposed, and you can write code to exploit the data using the HttpWebRequest/HttpWebResponse objects, as you saw in the preceding chapter The data are exposed through thesimplest possible mechanism, namely through HTTP But expressing conditions and statements
to retrieve our data using the URL syntax is rather awkward There are more structured tools,LINQ being one of them Can you access the data exposed by your service with LINQ? Theanswer is Yes! And LINQ can translate the standard query operators into the equivalent URLsyntax This URL querying syntax is convenient for testing the service, but no one expects you
to write applications using the query syntax (not in this day and age, at least) There are tools
to use the same data as business objects from a client application, and this is what you’re about
to do next
Building a Windows Client
In this section, I’ll guide you through the process of building a Windows client that consumesthe data of the data service As you can guess, Microsoft didn’t go to the trouble of developingADO.NET Data Services so we would have to process the XML returned by the queries on ourown There are tools that simplify the process enormously, and you’ll see them in this section.The tool that will allow us to see the entities of the new Entity Data Model at the client is acommand-line tool This tool is the DataSvcUtil.exe utility, which reads the service’s meta-data and creates a class that encapsulates the functionality of the service Open a commandprompt window and run the DataSvcUtil.exe utility, which resides in the folder Windows\
Microsoft.NET\Framework.NET\v.4.0.xxx , where xxx is the latest revision of the framework.
This value as of this writing is 4.0.30138, but it will most likely be a little different by the timeVisual Studio 2010 is released Choose the most recent version of the Framework and switch
to that folder In this folder you’ll find the DataSvcUtil.exe utility, which you must execute,passing as an argument the URL of the data service for which you want to generate a proxy (aproxy is a class that exposes the data model and the appropriate methods to access the service’sdata)
To generate the proxy, start the DataSvcUtil.exe utility with a statement similar to the lowing in the command prompt window:
fol-DataSvcUtil.exe /out:"C:\Project\DataServices\NWProxy.vb"
/uri:"http://localhost:51000/NWWebDataService.csv" /language:vb
This creates the proxy file in the root folder of one of my drives, so I can locate it easily later
Be sure to change the path to a folder that’s easy for you to locate later because you will have
to include this file with your solution
Before you execute this command, however, you must start the service for the new port totake effect Open the service in the browser as usual, and as soon as you see the list of tablesexposed by the service, close the browser The service will continue to run in Visual Studio andthe browser is not required The DataSvcUtil.exe utility will generate the file NWProxy.vb
in the specified folder Move this file to the folder that contains the Windows project you’re
Trang 17building, and then add it to the same project with the Add Existing Item command You
could add the proxy to your current project without moving it, but then the project files will
be scattered all over your drives
To simplify matters, I’ve added a Windows project to the solution, and its main form is
shown in Figure 21.20 This is the client application that will contact the data service to act with the Northwind database To see the newly created data model in action, you must addthe auto-generated proxy file to the Windows project by copying the NWProxy.vb file into thefolder of the Windows application Then place a button on the main form of the test project,
inter-the Read Data From Service button, and create a variable to reference inter-the proxy class with inter-thefollowing declaration in your code (just make sure to change the port to the appropriate value):
Dim service As New NorthwindModel.NorthwindEntities(
Trang 18allows you to access the data With the service variable in place, you can access the tables in
the Northwind database as collections of typed objects
To access a table, use a loop like the following, which iterates through the rows of the tomers table:
Cus-For Each p In service.ProductsDebug.WriteLine(p.ProductName)Next
As you can see, the collections returned by the service are typed and so the p variable exposes
the names of the columns of the Customers table as properties
In a similar manner, you can iterate through the Categories table:
For Each c In categoriesDebug.WriteLine(c.CategoryName)Next
If you want to access the products in each category, you must explicitly request these rows
of the Products table as you iterate through the categories The data service doesn’t moveall data to the client To request the matching rows of a related table, use the LoadPropertymethod, which accepts two arguments: an entity name, which is a row of the current table, andthe name of the related table To iterate through the categories and their related products, writetwo nested loops like the following:
For Each c In categoriesDebug.WriteLine(c.CategoryName)service.LoadProperty(c, "Products")For Each p In c.Products
Debug.WriteLine(p.ProductName & vbTab & p.UnitPrice.ToString)Next
Next
Since you’re working with typed collections, you can use all LINQ operators to process yourdata The following loop selects the customers from Germany and then the orders they haveplaced:
For Each c In service.Customers.Where(Function(cust) cust.Country = "Germany")service.LoadProperty(c, "Orders")
Debug.WriteLine(c.CompanyName)For Each o In c.Orders
Debug.WriteLine(vbTab & o.OrderID)Next
Next
To use the data service efficiently, you must execute the appropriate queries and retrieveonly the relevant data and not entire tables or even related rows that aren’t needed Let’s sayyou want to retrieve the orders from all customers in Germany that were placed in a specificyear Instead of using the LoadProperty method to move all related rows from the Orderstable on the server to the client, you can use the CreateQuery method to pass a query to the
Trang 19server You’ll specify your query in LINQ, but the data service will translate it to the ate SQL query and execute it against the server The following expression retrieves the rows ofthe Orders table as a DataServiceQuery object, which is a typed collection:
appropri-service.CreateQuery(Of NorthwindModel.Order)("Orders")
Then you can apply any filtering on this query to limit the number of rows with the Whereoperator:
Dim selOrders = service.CreateQuery(Of NorthwindModel.Order)("Orders").Where( _
Function(o) Year(o.OrderDate) = 1998 And
o.Customer.CustomerID = c)
Let’s say you need all customers in Italy ordered by their company name To request this
information from the database, you’d write a query like the following:
Dim ItalianCustomers = From c In service.Customers
Where c.Country = "Italy"
OrderBy c.CompanyNameSelect c
The preceding LINQ expression was translated into the following URI query:
{http://localhost:51000/NWWebDataService.svc/
Customers()?$filter=Country eq ‘Italy’&$orderby=CompanyName}
Your regular LINQ statements are being automatically translated into URIs that can be cessed by the service It looks like a new variation of LINQ, LINQ to URI, but I haven’t seenthis term being used in the documentation Anyway, the LINQ component knows how to talk
pro-to ADO.NET Data Services, but not always with success because not all expressions you can
use with LINQ have a counterpart in SQL To retrieve the orders with a freight charge of morethan $20, use the following trivial LINQ query:
Dim q = From o In service.Orders
Where o.Freight > 20Select o
The preceding LINQ query is translated into the following URI by the service:
http://localhost:51000/NWWebDataService.svc/
Orders()?$filter=cast(Freight gt 10M,’Edm.Boolean’)
In general, it’s much simpler to write queries using LINQ than to try to construct the properURL for any given query The following LINQ query retrieves the products that contain the
word sauce in their name, regardless of spelling:
Dim q = From p In service.Products
Where p.ProductName.Contains("sauce")
Select p
Trang 20When this query is translated into a URI query, the service makes use of the substringof ator, as shown here:
oper-{http://localhost:51000/NWWebDataService.svc/Products()?$
filter=substringof(’Sauce’,ProductName)}
If you’re wondering how I found the URI query for these LINQ queries, it’s really simple.Place a breakpoint before the LINQ query you want to monitor, and when the program breaks,
add a new watch on the variable that represents the result of the query (the q variable in most
of this section’s examples) As soon as the LINQ statement is executed, the SQL statement thatwill be executed against the database will appear in the Watches window
Submitting Updates
Using an ADO.NET data service to explore the data in a database is a fairly straightforwardapproach Surfacing your data with a data service is ideal for reporting and other applicationsthat need not modify the database Of course, the data service allows you to submit updates aswell, although this isn’t the best implemented feature of an ADO.NET data service — not yet,that is My main objection to updating a database through a data service is that the methodsthat perform the updates do not return the error messages generated by the database Whatyou get back is a generic error telling you that ‘‘an error occurred while processing thisrequest.’’ Whether the error occurred because the data violated some constraint or whether
it occurred because a field value was inappropriate for the corresponding column, the errormessage is the same If you decide to use a data service to submit updates to the database, beprepared to validate the data as best as you can at the client, because the server won’t helpyou determine the source of the update errors
Since it’s only a question of time before Microsoft brings ADO.NET Data Services up to parwith the other data access technologies, let’s look at the process of submitting updates to thedatabase Since the underlying data source is an Entity Data Model, the process of submittingdata to the service is more or less familiar to you To insert new rows, you create new entities
at the client and submit them to the server with the service’s SaveChanges method To updateexisting rows, you just change the desired fields and then call the same method To delete rows,you delete entities at the client and then call the SaveChanges method
To create a new product, for example, you must first create a Product object:
Dim prod As New NorthwindModel.Product
And then set the object’s properties with statements like the following:
prod.ProductName = "NEW PRODUCT NAME"
prod.UnitPrice = 11.2prod.UnitsInStock = 1prod.UnitsOnOrder = 12
Some of the properties are also entities, and they must be set to the appropriate entity Theproduct category is specified in the database with the CategoryID field, but the entity Product
is related to the entity Category, so you must create a new Category entity and assign it to
the Category property of the prod variable The same is true for the product’s supplier: You
Trang 21can set the prod.SupplierID field; you must set the Supplier property to an entity of the
Supplier type The following statements create the Category entity by reading a row from theCategoriestable and set up the Category property of the new product:
Dim cat = service.Categories.Where(Function(c) c.CategoryID = 4).First
prod.Category = cat
For the product supplier, I followed a different approach to better demonstrate the process
of updating the Data service This time I created a new Supplier entity, which provides onlyscalar properties, and then I set the new product’s Supplier property to this value:
Dim supplier As New NorthwindModel.Supplier
supplier.CompanyName = "New Supplier"
supplier.ContactName = "Contact name"
supplier.ContactTitle = "Contact title"
supplier.Address = "Supplier address"
supplier.City = "City"
supplier.Country = "Country"
service.AddToSuppliers(supplier)
service.SetLink(prod, "Supplier", supplier)
Note that this time the new entity is added to the Suppliers entity set at the client with the
AddToSuppliersmethod The last statement associates the product with its supplier This linkdoes not exist at the client and must be added explicitly Note that you don’t have to specifythe fields that take part in the relationship
At this point you can submit the new product to the database by calling the SaveChangesmethod The SaveChanges method doesn’t accept any arguments; it submits all changes to thedata service Obviously, it will first submit the new supplier and then the new product But thisisn’t something you have to worry about; the data service knows how to insert the rows in thecorrect order
You may have noticed that the code didn’t set the IDs of the two new rows The IDs are
assigned by the database and the client has no way of knowing the next available ID in the
database Other users may have inserted rows into any table and the client can’t make any
assumptions as to the next available ID You could also use globally unique identifiers (GUIDs)
as primary keys, which would allow you to generate the primary key values at the client, butfor most databases in use today this isn’t the case Windows generates a long string that’s
unique every time you create one (as the term suggests, it’s a globally unique identifier, not inyour computer or your network)
After the SaveChanges method is called, the properties prod.ProductID and supp.Supplier
IDwill have the correct values, which will be transmitted to the client by the data service This
is why we had to explicitly add the appropriate links between the entities at the client with theSetLink method As a reminder, this is necessary for new rows only If the ID of the relatedrow is known, as was the case with the Category entity, there’s no need to call the SetLink
method
The Simple Updates button of the sample application contains the statements presented sofar in this chapter Open the project to see the code that implements the simple operations, likeupdates and deletions
Trang 22Performing Transactions
Real data-driven applications perform updates in a transactional manner As you will recallfrom Chapter 15, ‘‘Programming with ADO.NET,’’ an order has to be committed to the data-base in a transactional manner; the entire order must fail if a single row fails to be committed
to the database Data services allow you to perform multiple updates in the context of a action as long as all the updates that belong to the transaction are submitted with a single call
trans-to the SaveChanges method In addition, you must set the SaveChangesDefaultOptions
prop-erty of the entity set to Batch.
Let’s consider the example of committing an order to the Northwind database, a ratherfamiliar example in this book You have seen how to perform transactions with ADO.NET aswell as with data entities To perform a transaction with a data service, you first create all theobjects that take part in the transaction: the order’s header and its detail lines You should notcall the SaveChanges method until all entities have been created at the client, as discussed inthe preceding section When the entire order has been set up at the client, you can submit it
to the database by calling the SaveChanges method
Let’s review the actual code that submits a new order to the database You can find the codediscussed in this section in the Transactional Updates button of the DataServices project As
usual, start with a reference to the data service, the service variable:
Dim service As New NorthwindModel.NorthwindEntities(
New Uri("http://localhost:51000/NWWebDataService.svc"))
Then, create a new Order object, the newOrder variable, and add it to the Orders table The new
row is appended to the Orders entity set at the client Moreover, the new order has no ID yet
The OrderID value will be assigned by the database when the transaction is submitted to the database Here are the statements that create the newOrder object:
Dim newOrder As New NorthwindModel.Orderservice.AddToOrders(newOrder)
Now create a customer object that represents the customer that placed the order In a realapplication, the user will most likely select the customer from a list, but since this application
doesn’t have an elaborate user interface, I retrieve a row from the Customers entity set at the client You can’t simply set the newOrder.CustomerID property, even though the newOrder variable exposes the CustomerID property The newOrder object has a Customer property too,
and there’s a relationship between the Orders and Customers tables To associate a customerwith the new order, we must set the order’s Customer property to a Customer object and thenestablish a relationship between the two The following statement creates the Customer objectthat represents the Customer ANTON:
Dim cust = service.Customers.Where(Function(p) p.CustomerID = "ANTON").First()
Next, assign the cust object to the new order’s Customer property and then create a link
between the order and the customer:
newOrder.Customer = custservice.SetLink(newOrder, "Customer", cust)
Trang 23Follow similar steps to associate an employee with the order:
Dim emp = service.Employees.Where(Function(p) p.EmployeeID = 3).First
newOrder.Employee = emp
service.SetLink(newOrder, "Employee", emp)
And then you can set the remaining (scalar) properties of the order with simple statements likethe following:
newOrder.OrderDate = Now
newOrder.ShipAddress = cust.Address
newOrder.ShipCity = cust.City
Now you can create the order details Each detail is a variable of the Detail type, and each
must be added to the Order_Details property of the newOrder object The Order_Details
property is a collection, and as such it provides an Add method The following statement creates
a new variable, the dtl variable, that represents an order detail:
Dim dtl As New NorthwindModel.Order_Detail
This variable must be added to the Order_Details entity set:
Dim dtlProd = service.Products.Where(Function(p) p.ProductID = 31).First
Set the Product property of the new order to the dtlProduct object:
dtl.Product = dtlProd
And create a link between the detail line and the corresponding row in the Products entity set:
service.SetLink(dtl, "Product", dtlProd)
Then, you can set the remaining properties of the detail line with simple statements like the
following:
dtl.Product = dtlProd
dtl.UnitPrice = 11.2
dtl.Quantity = 9
Trang 24And finally, associate the new detail line with the new order:
service.SetLink(dtl, "Order", newOrder)
Let’s add a second detail line to the order with the following statements:
dtl = New NorthwindModel.Order_DetaildtlProd = New NorthwindModel.ProductdtlProd = service.Products.Where(Function(p) p.ProductID = 56).First()dtl.Order = newOrder
dtl.Product = dtlProddtl.UnitPrice = dtlProd.UnitPrice * 0.9dtl.Discount = 0.1
dtl.Quantity = -5service.AddToOrder_Details(dtl)newOrder.Order_Details.Add(dtl)service.SetLink(dtl, "Product", dtlProd)service.SetLink(dtl, "Order", newOrder)
This time I’ve chosen to include a discount as well Other than that, the process of creating a
new detail line is the same The new detail line is linked to a Product entity because it contains the ID of a product and to the Order entity to which is belongs.
At last, you can commit the new order to the data service by calling the SaveChanges
method of the service variable All the objects you have created at the client will be submitted
to the database in the proper order by the data service To ensure that all rows will be inserted
in a transactional manner, you must also set the service.SaveChangesDefaultOptionsproperty to the value shown in the code:
service.SaveChangesDefaultOptions = Services.Client.SaveChangesOptions.BatchTry
service.SaveChanges()Catch ex As Exception
MsgBox("FAILED TO COMMIT NEW ORDER")End Try
To see for yourself that the order is submitted in a transactional manner, set the price of theproduct of the first detail line to a negative value The database will reject this value and theentire transaction will fail The error that will be raised by the data service will have a verygeneric description, which won’t help you locate the bug in your code With a straight ADOtransaction, you get back the error message generated by the database, which clearly states thevalue that the database couldn’t accept
Once the transaction has been committed, the data service will return the ID of the order aswell as the IDs of all entities involved in the transaction In this case, there’s only one ID value
to be set by the database
Through the examples in this section, it’s clear that a data service is quite trivial to build andvery easy to use for selection queries When it comes to updating the database, however, thedata service doesn’t provide all the mechanisms you’ve come to expect with other data accesstechnologies You must establish relationships between entities in your code and you can’t rely
on meaningful error descriptions to debug your code
Trang 25Securing Your Data Service
Exposing a database as a web service on the Internet is not the best idea To secure the
database from malicious users, you must set up some security measures As you recall, the
SetEntitySetAccessRule method sets the access rule for the various entities exposed by theservice So far, you allowed users to access all entities for all operations with the following
statement:
config.SetEntitySetAccessRule("*", EntitySetRights.All)
The first argument is the name of an entity and the second argument is a member of the
EntitySetRight enumeration: None, All, AllRead, AllWrite, ReadMultiple, ReadSingle,
WriteAppend , WriteDelete, WriteMerge, WriteReplace The names of most members are
self-descriptive The ReadMultiple and ReadSingle members determine whether users can
read multiple rows or a single row of the corresponding entity set
Limiting Data Access
Whenever possible, you should limit the number of rows a client application can request
because sloppy developers will retrieve an entire table to select a few rows at the client The
following method call enables clients to read all rows, insert new rows, and replace existing
rows in the Orders entity set:
config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead Or
EntitySetRights.WriteAppend Or EntitySetRights.WriteReplace)Notice that multiple options are combined with the Or operator
The SetServiceOperationAccessRule specifies the access rules for the various operations
The first argument is a method name and the second argument is a member of the
ServiceOperationRights enumeration: All, AllRead, None, OverrideSetEntityRights,
ReadMultiple, or ReadSingle.
The two methods are quite useful for specifying simple access rules but not nearly adequate
enough for implementing more advanced security rules Typical access rules, such as allowing
users to view their own orders only, must be implemented with the appropriate procedures
These procedures are called interceptors because they intercept a query and alter the query’s
default behavior To intercept a selection query, for example, use the QueryInterceptor
attribute followed by the name of an entity set in parentheses:
<QueryInterceptor("Orders")>
Public Function OnQueryOrders() As Expression(Of Func(Of Orders, Boolean))
‘ statements
End Function
The OnQueryOrders function will be called every time a client selects one or more rows from
the Orders table and it’s implemented as a lambda expression that accepts as arguments a
Trang 26collection of the Orders entity set (the original result of the query) and a Boolean variable.The function’s body should set the second argument to True or False for each member ofthe collection, depending on whether the member should be included in the result or not.Note that the interceptor applies to all queries to the specific table, whether they query theOrders entity set directly or they query the same set indirectly — for example, a query to theCustomers table that expands the customer’s orders.
The following interceptor for the Orders entity set eliminates all orders except for the onesplaced by the customer that makes the request It assumes that the service is hosted as an IISapplication with authentication and the user has connected to the service with the same user-name as the company name, which is rarely the case In a realistic scenario, the service wouldlook up the user’s company name in a table and then use it to filter the results of the query:
<QueryInterceptor("Orders")>
Public Function OnQueryOrders() As Expression(Of Func(Of Orders, Boolean))Return Function(o) o.Customers.ContactName =
HttpContext.Current.User.Identity.NameEnd Function
You can implement interceptors for all types of queries, including insertion, modification,and deletion queries To define a change interceptor for the Products entity set in the North-wind data service project, open the Northwind.svc file and define a service operation methodnamed OnChangeProducts as follows:
<ChangeInterceptor("Products")>
Public Sub OnChangeProducts(ByVal product As Products,
ByVal operations As UpdateOperations)
The interceptor for operations that submit edits to the database includes an argument thatdetermines the update operation that fired the interceptor You can determine the type ofoperation from within the interceptor code and react differently to different operations Youmay reject a delete operation, for example, but accept insertions and updates The methodthat intercepts all modifications is the ChangeInterceptor, and it provides two arguments:the row that’s about to be modified and the operation The operation is a member of theUpdateOperations enumeration, whose members are Add, Update, Change, and Delete What
makes this type of interceptor especially useful is that you can access the fields of the rowbeing modified and reject certain operations based on the value of the row’s columns Thisinformation is passed to the method as a row of the corresponding table and it’s the firstargument of the ChangeInterceptor interceptor
The Products table of the Northwind database, for example, has a column that specifieswhether a product has been discontinued or not, the Discontinued column It probably doesn’tmake a lot of sense to create a new product that’s already discontinued This is a business deci-sion, of course, but here’s an interceptor for the Add operation that disallows the insertion of aproduct that has its Discontinued column set to True:
<ChangeInterceptor("Products")> _Public Sub OnChangeProducts(
Trang 27ByVal product As Products, ByVal operation As UpdateOperations)
If operation = UpdateOperations.Add Then
If product.Discontinued Then
Throw New DataServiceException(
400, "Can’t modify a discontinued product!")End If
End If
End Sub
If this exception is raised, the service will return an error message with the specified tion If the same error were raised while testing the service from the browser, the error wouldhave been a 400 error (the ‘‘page not found’’ error)
descrip-The Bottom Line
Create a simple ASP.NET web service. Creating ASP.NET web services is straightforwardwith Visual Studio ASP.NET web services provide a great method for delivering data and
functionality within a distributed environment, including the Internet
Master It Develop an ASP.NET web service that enables the user to add two numbers
Consume an ASP.NET web service. Adding a web reference or service reference to a web
service is a key element to creating an application that can consume the web service
Master It Create a new website and add a service reference to a web service on your
machine
Create a WCF service. WCF services are similar to web services, but they give developers
more options for deployment and they support more data exchange protocols
Master It Outline the steps involved in building a WCF service
Work with ADO.NET Data Services. ADO.NET Data Services is a project component thatexposes, or surfaces, data as a service through HTTP Data services are built automatically byVisual Studio based on any data source, and you can access them through URI requests
Master It How do you access the methods of an ADO.NET data service?
Trang 29The Bottom Line
Each of The Bottom Line sections in the chapters suggest exercises to deepen skills and standing Sometimes there is only one possible solution, but often you are encouraged to useyour skills and creativity to create something that builds on what you know and lets youexplore one of many possible solutions
under-Chapter 1: Getting Started with Visual Basic 2010
Navigate the integrated development environment of Visual Studio. To simplify the cess of application development, Visual Studio provides an environment that’s common to alllanguages, known as an integrated development environment (IDE) The purpose of the IDE
pro-is to enable the developer to do as much as possible with vpro-isual tools before writing code TheIDE provides tools for designing, executing, and debugging your applications It’s your seconddesktop, and you’ll be spending most of your productive hours in this environment
Master It Describe the basic components of the Visual Studio IDE
Solution The basic components of the Visual Studio IDE are the Form Designer, whereyou design the form by dropping and arranging controls, and the code editor, where youwrite the code of the application The controls you can place on the form to design theapplication’s interface are contained in the Toolbox window To set the properties of acontrol, you must select it on the form and locate the appropriate property in the Propertieswindow
Understand the basics of a Windows application. A Windows application consists of avisual interface and code The visual interface is what users see at runtime: a form with con-trols with which the user can interact — by entering strings, checking or clearing check boxes,clicking buttons, and so on The visual interface of the application is designed with visualtools The visual elements incorporate a lot of functionality, but you need to write some code
to react to user actions
Master It Describe the process of building a simple Windows application
Solution First, you must design the form of the application by dropping controls fromthe Toolbox window onto the form Size and align the controls on the form, and then settheir properties in the Properties window The controls include quite a bit of functional-ity right out of the box A TextBox control with its MultiLine property set to True and itsScrollBarsproperty set to Vertical is a complete, self-contained text editor.
Trang 30After the visual interface has been designed, you can start coding the application dows applications follow an event-driven model: Code the events to which you want yourapplication to react The Click events of the various buttons are typical events to which
Win-an application reacts
Then, there are events that are ignored by developers The TextBox control, for example,fires some 60 events, but most applications don’t react to more than one or two of them.Select the actions to which you want your application to react and program these eventsaccordingly When an event is fired, the appropriate event handler is automatically invoked
Event handlers are subroutines that pass two arguments to the application: the sender argument, which is the control that fired the event, and the e argument which carries addi-
tional information about the event (information such as the mouse button that was pressed,the character typed by the user, and so on) To program a specific event for a control,double-click the control on the design surface and the editor window will come up with thedefault event for the control You can select any other event for the same control to program
in the Events combo box at the top of the editor’s window
Chapter 2: Handling Data
Declare and use variables. Programs use variables to store information during their tion, and different types of information are stored in variables of different types Dates, forexample, are stored in variables of the Date type, while text is stored in variables of the Stringtype The various data types expose a lot of functionality that’s specific to a data type; the meth-ods provided by each data type are listed in the IntelliSense box
execu-Master It How would you declare and initialize a few variables?
Solution To declare multiple variables in a single statement, append each variable’s nameand type to the Dim statement
Dim speed As Single, distance As Integer
Variables of the same type can be separated with commas, and you need not repeat the type
of each variable:
Dim First, Last As String, BirthDate As Date
To initialize the variables, append the equals sign and the value as shown here:
Dim speed As Single = 75.5, distance As Integer = 14902
Master It Explain briefly the Explicit, Strict, and Infer options
Solution These three options determine how Visual Basic handles variable types, and theycan be turned on or off The Explicit option requires that you declare all variables in yourcode before using them When it’s off, you can use a variable in your code without declaring
Trang 31it The compiler will create a new variable of the Object type The Strict option requires thatyou declare variables with a specific type If the Strict option if off, you can declare variableswithout a type, with a statement like this:
Dim var1, var2
The last option, Infer, allows you to declare and initialize typed variables without
speci-fying their type The compiler infers the variable’s type from the value assigned to it Thefollowing declarations will create a String and a Date variable as long as the Infer option is
on Otherwise, they will create two object variables:
Dim D = #3/5/1008#, S=my name
Use the native data types. The CLR recognized the following data types, which you can use
in your code to declare variables: String, numeric data types (Integer, Double, and so on), Date,Char and Boolean types
All other variables, or variables that are declared without a type, are Object variables and canstore any data type or any object
Master It How will the compiler treat the following statement?
Dim amount = 32
Solution The amount variable is not declared with a specific data type With the default
settings, the compiler will create a new Object variable and store the value 32 in it If the
Infer option is on, the compiler will create an Integer variable and store the value 32 in it Ifyou want to be able to store amounts with a fractional part in this variable, you must assign
a floating-point value to the variable (such as 32.00) or append the R type character to thevalue (32R)
Create custom data types. Practical applications need to store and manipulate multiple dataitems, not just integers and strings To maintain information about people, we need to store
each person’s name, date of birth, address, and so on Products have a name, a description, aprice, and other related items To represent such entities in our code, we use structures, whichhold many pieces of information about a specific entity together
Master It Create a structure for storing products and populate it with data
Solution Structures are declared with the Structure keyword and their fields with the
Dimstatement:
Structure Product
Dim ProductCode As String
Dim ProductName As String
Dim Price As Decimal
Dim Stock As Integer
End Structure
Trang 32To represent a specific product, declare a variable of the Product type and set its fields,which are exposed as properties of the variable:
Dim P1 As ProductP1.ProductCode = SR-0010
P1.ProductName = NTR TV-42
P1.Price = 374.99P1.Stock = 3
Use arrays. Arrays are structures for storing sets of data as opposed to single-valuedvariables
Master It How would you declare an array for storing 12 names and another one for ing 100 names and Social Security numbers?
stor-Solution The first array stores a set of single-valued data (names) and it has a single mension Since the indexing of the array’s elements starts at 0, the last element’s index forthe first array is 11, and it must be declared as follows:
di-Dim Names(11) As String
The second array stores a set of pair values (names and SSNs), and it must be declared as atwo-dimensional array:
Dim Persons(100,1) As String
If you’d rather avoid the index 0, you can declare the two arrays as follows:
Dim Names(1 To 11) As StringDim Persons(1 To 100, 1 To 1) As String
Chapter 3: Visual Basic Programming Essentials
Use Visual Basic’s flow-control statements. Visual Basic provides several statements forcontrolling the flow of control in a program: decision statements, which change the course ofexecution based on the outcome of a comparison, and loop statements, which repeat a number
of statements while a condition is true or false
Master It Explain briefly the decision statements of Visual Basic
Solution The basic decision statement in VB is the If…End If statement, which executesthe statements between the If and End If keywords if the condition specified in the If part
is true A variation of this statement is the If…Then…Else statement
If the same expression must be compared to multiple values and the program should cute different statements depending on the outcome of the comparison, use the Select Casestatement
exe-Write subroutines and functions. To manage large applications, break your code into small,manageable units These units of code are the subroutines and functions Subroutines performactions and don’t return any values Functions, on the other hand, perform calculations andreturn values Most of the language’s built-in functionality is in the form of functions
Trang 33Master It How will you create multiple overloaded forms of the same function?
Solution Overloaded functions are variations on the same function with different ments All overloaded forms of a function have the same name, and they’re prefixed withthe Overloads keyword Their lists of arguments, however, are different — either in the
argu-number of arguments or in the argument types
Pass arguments to subroutines and functions. Procedures and functions communicate withone another via arguments, which are listed in a pair of parentheses following the procedure’sname Each argument has a name and a type When you call a procedure, you must supply
values for each argument, and the types of the values should match the types listed in the cedure’s definition
pro-Master It Explain the difference between passing arguments by value and passing ments by reference
argu-Solution The first mechanism, which was the default mechanism with earlier versions
of the language, passes a reference to the argument Arguments passed by reference are
prefixed by the keyword ByRef in the procedure’s definition The procedure has access tothe original values of the arguments passed by reference and can modify them The sec-
ond mechanism passes to the procedure a copy of the original value Arguments passed byvalue are prefixed with the keyword ByVal in the procedure’s definition The procedure
may change the values of the arguments passed by value, but the changes won’t affect thevalue of the original variable
Chapter 4: GUI Design and Event-Driven Programming
Design graphical user interfaces. A Windows application consists of a graphical user face and code The interface of the application is designed with visual tools and consists of
inter-controls that are common to all Windows applications You drop inter-controls from the Toolbox
window onto the form, size and align the controls on the form, and finally set their propertiesthrough the Properties window The controls include quite a bit of functionality right out of thebox, and this functionality is readily available to your application without a single line of code
Master It Describe the process of aligning controls on a form
Solution To align controls on a form, you should select them in groups, according to
their alignment Controls can be aligned to the left, right, top, and bottom After selecting agroup of controls with a common alignment, apply the proper alignment with one of the
commands of the Format Align menu Before aligning multiple controls, you should
adjust their spacing Select the controls you want to space vertically or horizontally and just their spacing with one of the commands of the Format Horizontal Spacing and
ad-Format Vertical Spacing menus You can also align controls visually, by moving them
with the mouse As you move a control around, a blue snap line appears every time the
control is aligned with another one on the form
Program events. Windows applications follow an event-driven model: We code the events towhich we want our application to respond For example, an application reacts to Click events
of the various buttons You select the actions to which you want your application to react andprogram these events accordingly
When an event is fired, the appropriate event handler is automatically invoked Event handlers
are subroutines that pass two arguments to the application: the sender argument (which is
Trang 34an object that represents the control that fired the event) and the e argument (which carries
additional information about the event)
Master It How will you handle certain keystrokes regardless of the control that receivesthem?
Solution You can intercept all keystrokes at the form’s level by setting the form’s Previewproperty to True Then insert some code in the form’s KeyPress event handler
Key-to examine the keystroke passed Key-to the event handler and Key-to process it To detect the keypresses in the KeyPress event handler, use an If statement like the following:
If e.KeyChar = "A" Then
’ process the A keyEnd If
Write robust applications with error handling. Numerous conditions can cause an tion to crash, but a well-written application should be able to detect abnormal conditions and
applica-handle them gracefully To begin with, you should always validate your data before you attempt
to use them in your code A well-known computer term is ‘‘garbage in, garbage out,’’ whichmeans you shouldn’t perform any calculations on invalid data
Master It How will you execute one or more statements in the context of a structuredexception handler?
Solution A structured exception handler has the following syntax:
Chapter 5: Basic Windows Controls
Use the TextBox control as a data-entry and text-editing tool. The TextBox control is themost common element of the Windows interface, short of the Button control, and it’s used
to display and edit text You can use a TextBox control to prompt users for a single line oftext (such as a product name) or a small document (a product’s detailed description) You can
Trang 35actually implement a functional text editor by placing a TextBox control on a form and setting
a few of its properties
Master It What are the most important properties of the TextBox control? Which ones
would you set in the Properties windows at design time?
Solution The first property you’ll most likely change is the MultiLine property, whosedefault value is False To set the initial text on the control, use the Text or Lines properties.The Text property returns or sets the text on the control The Lines property is an array
of string that holds each text line in a separate element To interact with the user, use the
text-selection properties SelectedText, SelectionLength, and SelectionStart You canuse these properties to retrieve and manipulate the text selected by the user on the control
or to select text from within your code
Master It How would you implement a control that suggests lists of words matching thecharacters entered by the user?
Solution Use the autocomplete properties AutoCompleteMode, AutoCompleteSource, andAutoCompleteCustomSource The AutoCompleteMode property determines whether the
control will suggest the possible strings, automatically complete the current word as you
type, or do both The AutoCompleteSource property specifies where the strings that will
be displayed will come from and its value is a member of the AutoCompleteSource
enu-meration If this property is set to AutoCompleteSoure.CustomSource, you must set up
an AutoCompleteStringCollection collection with your custom strings and assign it to theAutoCompleteCustomSourceproperty
Use the ListBox, CheckedListBox, and ComboBox controls to present lists of items. The
ListBox control contains a list of items from which the user can select one or more, depending
on the setting of the SelectionMode property
Master It How would you locate an item in a ListBox control?
Solution To locate a string in a ListBox control, use the FindString and FindString
Exactmethods The FindString method locates a string that partially matches the one
you’re searching for; FindStringExact finds an exact match Both methods perform
case-insensitive searches and return the index of the item they’ve located in the list
We usually call the FindStringExact method and then examine its return value If an exactmatch is found, we select the item with the index returned by the FindExact method If
an exact match is not found, in which case the method returns –1, we call the FindStringmethod to locate the nearest match
Use the ScrollBar and TrackBar controls to enable users to specify sizes and positions with the mouse. The ScrollBar and TrackBar controls let the user specify a magnitude by scrolling
a selector between its minimum and maximum values The ScrollBar control uses some visualfeedback to display the effects of scrolling on another entity, such as the current view in a longdocument
Master It Which event of the ScrollBar control would you code to provide visual feedback
to the user?
Solution The ScrollBar control fires two events: the Scroll event and the ValueChangedevent They’re very similar and you can program either event to react to the changes in the
Trang 36ScrollBar control The advantage of the Scroll event is that it reports the action that caused
it through the e.Type property You can examine the value of this property in your codeand react to actions like the end of the scroll:
Private Sub blueBar_Scroll(
ByVal sender As System.Object,ByVal e As System.Windows.Forms.ScrollEventArgs)Handles blueBar.Scroll
If e.Type = ScrollEventType.EndScroll Then
‘ perform calculations and provide feedbackEnd If
End Sub
Chapter 6: Working with Forms
Visual form design Forms expose a lot of trivial properties for setting their appearance Inaddition, they expose a few properties that simplify the task of designing forms that can beresized at runtime The Anchor property causes a control to be anchored to one or more edges
of the form to which it belongs The Dock property allows you to place on the form controlsthat are docked to one of its edges To create forms with multiple panes that the user can resize
at runtime, use the SplitContainer control If you just can’t fit all the controls in a reasonablysized form, use the AutoScroll properties to create a scrollable form
Master It You’ve been asked to design a form with three distinct sections You should alsoallow users to resize each section How will you design this form?
Solution The type of form required is easily designed with visual tools and the help of theSplitContainer control Place a SplitContainer control on the form and set its Dock property
to Fill You’ve just created two vertical panes on the form, and users can change their
rel-ative sizes at any time To create a third pane, place another SplitContainer control on one
of the first control’s panes and set its Dock property to Fill and its Orientation property
to Horizontal At this point, the form is covered by three panes and users can change each
pane’s size at the expense of its neighboring panes
Design applications with multiple forms. Typical applications are made up of multipleforms: the main form and one or more auxiliary forms To show an auxiliary form from withinthe main form’s code, call the auxiliary form’s Show method, or the ShowDialog method if youwant to display the auxiliary form modally (as a dialog box)
Master It How will you set the values of selected controls in a dialog box, display them,and then read the values selected by the user from the dialog box?
Solution Create a Form variable that represents the dialog box and then access any control
on the dialog box through its name as usual, prefixed by the form’s name:
Dim Dlg As AuxFormDlg.txtName = "name"
Trang 37Then call the form’s ShowDialog method to display it modally and examine the
Dialog-Resultproperty returned by the method If this value is OK, process the data on the dialogbox; if it isn’t, do not process the dialog box:
If Dlg.ShowDialog = DialogResult.OK Then
UserName = Dlg.TxtName
End If
To display an auxiliary form, just call the Show method This method doesn’t return a
value, and you can read the auxiliary form’s contents from within the main form’s code
at any time You can also access the controls of the main form from within the auxiliary
form’s code
Design dynamic forms. You can create dynamic forms by populating them with controls atruntime through the form’s Controls collection First, create instances of the appropriate con-trols by declaring variables of the corresponding type Then set the properties of each of thesevariables that represent controls Finally, place the control on the form by adding the corre-
sponding variable to the form’s Controls collection
Master It How will you add a TextBox control to your form at runtime and assign a dler to the control’s TextChanged event?
han-Solution Create an instance of the TextBox control, set its Visible property and then add
it to the form’s Controls collection:
Dim TB As New TextBox
TB.Visible = True
’ statements to set other properties,
’ including the control’s location on the form
Me.Controls.Add(TB)
Then write a subroutine that will handle the TextChanged event This subroutine, let’s call itTBChanged(), should have the same signature as the TextBox control’s TextChanged event.Use the AddHandler statement to associate the TBChanged() subroutine with the new con-trol’s TextChanged event:
AddHandler TB.TextChanged, _
New SystemEventHandler(AddressOf TBChanged)
Design menus. Both form menus and context menus are implemented through the
Menu-Strip control The items that make up the menu are ToolMenu-StripMenuItem objects The ToolMenu-Strip-MenuItem objects give you absolute control over the structure and appearance of the menus ofyour application
ToolStrip-Master It What are the two basic events fired by the ToolStripMenuItem object?
Solution When the user clicks a menu item, the DropDownOpened and Click events are
fired in this order The DropDownOpened event gives you a chance to modify the menu that’sabout to be opened After the execution of the DropDownOpened event handler, the Click
event takes place to indicate the selection of a menu command We rarely program the
Trang 38DropDownOpenedevent, but every menu item’s Click event handler should contain somecode to react to the selection of the item.
Chapter 7: More Windows Controls
Use the OpenFileDialog and SaveFileDialog controls to prompt users for filenames.
Windows applications use certain controls to prompt users for common information, such
as filenames, colors, and fonts Visual Studio provides a set of controls that are grouped inthe Dialogs section of the Toolbox All common dialog controls provide a ShowDialog method,which displays the corresponding dialog box in a modal way The ShowDialog method returns
a value of the DialogResult type, which indicates how the dialog box was closed, and youshould examine this value before processing the data
Master It Your application needs to open an existing file How will you prompt users forthe file’s name?
Solution First you must drop an instance of the OpenFileDialog control on the form Tolimit the files displayed in the Open dialog box, use the Filter property to specify the rele-vant file type(s) To display text files only, set the Filter property to Text files|*.txt
If you want to display multiple filename extensions, use a semicolon to separate sions with the Filter property; for example, the string Images|*.BMP;*.GIF;*.JPG willcause the control to select all the files of these three types and no others The first part of theexpression (Images) is the string that will appear in the drop-down list with the file types.You should also set the CheckFileExists property to True to make sure the file specified
exten-on the cexten-ontrol exists Then display the Open dialog box by calling its ShowDialog method,
as shown here:
If FileOpenDialog1.ShowDialog =Windows.Forms.DialogResult.OK{process file FileOpenDialog1.FileName}
tech-is an array of strings
OpenFileDialog1.Multiselect = TrueOpenFileDialog1.ShowDialog()Dim filesEnum As IEnumeratorListBox1.Items.Clear()filesEnum =
Trang 39While filesEnum.MoveNext
‘ current file’s name is filesEnum.Current
End While
The other technique is to use the FolderBrowserDialog control, which prompts users to
select a folder, not individual files Upon return, the control’s SelectedPath property tains the pathname of the folder selected by the user from the dialog box, and you can usethis property to process all files of a specific type in the selected folder
con-Use the ColorDialog and FontDialog controls to prompt users for colors and typefaces. TheColor and Font dialog boxes allow you to prompt users for a color value and a font, respec-
tively Before showing the corresponding dialog box, set its Color or Font property according
to the current selection, and then call the control’s ShowDialog method
Master It How will you display color attributes in the Color dialog box when you open it?How will you display the attributes of the selected text’s font in the Font dialog box whenyou open it?
Solution To prompt users to specify a different color for the text on a TextBox control,
execute the following statements:
ColorDialog1.Color = TextBox1.ForeColor
If ColorDialog1.ShowDialog = DialogResult.OK Then
TextBox1.ForeColor = ColorDialog1.Color
End If
To populate the Font dialog box with the font in effect, assign the TextBox control’s Font
property to the FontDialog control’s Font property by using the following statements:
FontDialog1.Font = TextBox1.Font
If FontDialog1.ShowDialog = DialogResult.OK Then
TextBox1.Font = FontDialog1.Font
End If
Use the RichTextBox control as an advanced text editor to present richly formatted text.
The RichTextBox control is an enhanced TextBox control that can display multiple fonts andstyles, format paragraphs with different styles, and provide a few more-advanced text-editingfeatures Even if you don’t need the formatting features of this control, you can use it as an
alternative to the TextBox control At the very least, the RichTextBox control provides more
editing features, a more-useful undo function, and more-flexible search features
Master It You want to display a document with a title in large, bold type, followed by acouple of items in regular style Which statements will you use to create a document like
this on a RichTextBox control?
Document’s Title
Item 1 Description for item 1
Item 2 Description for item 2
Solution To append text to a RichTextBox control, use the AppendText method This
method accepts a string as an argument and appends it to the control’s contents The text is
Trang 40formatted according to the current selection’s font, which you must set accordingly throughthe SelectionFont property To switch to a different font, set the SelectionFont propertyagain and call the AppendText method.
Assuming that the form contains a control named RichTextBox1, the following statementswill create a document with multiple formats In this sample, I’m using three different type-faces for the document
"Description for item 1" & vbCrLf)Editor.SelectionFont = fntItem
Editor.SelectionIndent = 20Editor.AppendText("Item 2" & vbCrLf)Editor.SelectionFont = fntTextEditor.SelectionIndent = 40Editor.AppendText(
"Description for item 2" & vbCrLf)
Create and present hierarchical lists by using the TreeView control. The TreeView control
is used to display a list of hierarchically structured items Each item in the TreeView control
is represented by a TreeNode object To access the nodes of the TreeView control, use theTreeView.Nodescollection The nodes under a specific node (in other words, the child nodes)form another collection of Node objects, which you can access by using the expressionTreeView.Nodes(i).Nodes The basic property of the Node object is the Text property, whichstores the node’s caption The Node object exposes properties for manipulating its appearance(its foreground/background color, its font, and so on)
Master It How will you set up a TreeView control with a book’s contents at design time?
Solution Place an instance of the TreeView control on the form and then locate its Nodesproperty in the Properties window Click the ellipsis button to open the TreeNode Editordialog box, where you can enter root nodes by clicking the Add Root button and child nodesunder the currently selected node by clicking the Add Child button The book’s chaptersshould be the control’s root nodes, and the sections should be child nodes of those chapternodes If you have nested sections, add them as child nodes of the appropriate node While
a node is selected in the left pane of the dialog box, you can specify its appearance in theright pane by setting the font, color, and image-related properties