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

ASP.NET 2.0 Instant Results

.pdf
Скачиваний:
68
Добавлен:
17.08.2013
Размер:
11.03 Mб
Скачать

Modifying the Appointment Booking System

2.Add a relation between this new table and the table BookingObject, joining the two on BookingObject.Id and Exception.BookingObjectId.

3.Open the stored procedure sprocAppointmentCheckAvailability and add the following highlighted code to the WHERE clause right below the first check that filters on BookingObject.Id:

BookingObject.Id = @bookingObjectId

--Make sure the startdate is not in the Exception table AND (CONVERT(varchar(8), @startDate, 112) NOT IN

(SELECT CONVERT(varchar(8), ExceptionDate, 112) FROM Exception WHERE BookingObjectId = @bookingObjectId))

--Make sure the enddate is not in the Exception table

AND (CONVERT(varchar(8), @endDate, 112) NOT IN

(SELECT CONVERT(varchar(8), ExceptionDate, 112) FROM Exception WHERE BookingObjectId = @bookingObjectId))

This code ensures that the availability checker returns False if someone tries to make an appointment for a booking object that is listed in the Exception table for the requested date.

4.Open sprocTimeSheetSelectList and add the highlighted code to the WHERE clause of the first SELECT statement:

AND BookingObjectWorkingDay.WorkingDayId = DATEPART(dw, @selectedDate) AND BookingObjectId NOT IN (SELECT BookingObjectId FROM Exception WHERE

CONVERT(varchar(8), ExceptionDate, 112) = CONVERT(varchar(8), @selectedDate, 112) )

)AS AvailableOnSelectedDay

With this code, the procedure returns False (0) for the AvailableOnSelectedDay column when a booking object is listed in the Exceptions table.

5.As the last step in modifying the database, create three stored procedures to create, delete, and select exceptions. You’ll find the complete code below. Note that the entire code for the modification of the application is also available on the companion CD, so there is no need to type in all this code by hand.

This code creates the stored procedure to select exceptions:

CREATE PROCEDURE sprocExceptionSelectList

@bookingObjectId int

AS

SELECT Id, ExceptionDate FROM Exception WHERE BookingObjectId = @bookingObjectId

This code creates the stored procedure to create exceptions:

CREATE PROCEDURE sprocExceptionInsertSingleItem

@bookingObjectId int, @exceptionDate datetime

AS

IF NOT EXISTS (SELECT 1 FROM Exception WHERE BookingObjectId = @bookingObjectId

47

Chapter 10

AND ExceptionDate = @exceptionDate)

BEGIN

INSERT INTO Exception

(BookingObjectId, ExceptionDate)

VALUES (@bookingObjectId, @exceptionDate)

END

This code creates the stored procedure to delete exceptions:

CREATE PROCEDURE sprocExceptionDeleteSingleItem

@id int

AS

DELETE FROM Exception WHERE ID = @id

Modifying the Business and Data Access Layers

The next step is to change both the business and the data access layers.

1.Open the file BookingObjectManager.vb from the BusinessLogic folder and add the following code:

Public Shared Function GetExceptionList(ByVal bookingObjectId As Integer) _ As DataSet

Return BookingObjectManagerDB.GetExceptionList(bookingObjectId) End Function

Public Shared Sub CreateException(ByVal bookingObjectId As Integer, _ ByVal exceptionDate As DateTime)

BookingObjectManagerDB.CreateException(bookingObjectId, exceptionDate) End Sub

Public Shared Sub DeleteException(ByVal id As Integer)

BookingObjectManagerDB.DeleteException(id)

End Sub

All three methods forward their calls to methods in the BookingObjectManagerDB class that you should create next.

2.Open the file BookingObjectManagerDB.vb in the DataAccess folder and add the following code to the bottom of the file:

Public Shared Function GetExceptionList(ByVal bookingObjectId As Integer) _ As DataSet

Dim myDataSet As DataSet = New DataSet() Try

Using myConnection As New SqlConnection(AppConfiguration.ConnectionString) Dim myCommand As SqlCommand = _

New SqlCommand(“sprocExceptionSelectList”, myConnection) myCommand.CommandType = CommandType.StoredProcedure

myCommand.Parameters.AddWithValue(“@bookingObjectId”, bookingObjectId)

Dim myDataAdapter As SqlDataAdapter = New SqlDataAdapter()

48

Modifying the Appointment Booking System

myDataAdapter.SelectCommand = myCommand myDataAdapter.Fill(myDataSet) myConnection.Close()

Return myDataSet

End Using

Catch ex As Exception

Throw

End Try

End Function

Public Shared Sub CreateException(ByVal bookingObjectId As Integer, _ ByVal exceptionDate As DateTime)

Try

Using myConnection As New SqlConnection(AppConfiguration.ConnectionString) Dim myCommand As SqlCommand = _

New SqlCommand(“sprocExceptionInsertSingleItem”, myConnection) myCommand.CommandType = CommandType.StoredProcedure

myCommand.Parameters.AddWithValue(“@bookingObjectId”, bookingObjectId) myCommand.Parameters.AddWithValue(“@exceptionDate”, exceptionDate)

myConnection.Open()

myCommand.ExecuteNonQuery()

myConnection.Close() End Using

Catch ex As Exception Throw

End Try End Sub

Public Shared Sub DeleteException(ByVal id As Integer) Try

Using myConnection As New SqlConnection(AppConfiguration.ConnectionString) Dim myCommand As SqlCommand = _

New SqlCommand(“sprocExceptionDeleteSingleItem”, myConnection) myCommand.CommandType = CommandType.StoredProcedure

myCommand.Parameters.AddWithValue(“@id”, id)

myConnection.Open()

myCommand.ExecuteNonQuery()

myConnection.Close() End Using

Catch ex As Exception Throw

End Try End Sub

This is the implementation for the three methods that create, delete and select the exceptions. The code should be familiar to you because it is identical to other data access code you have seen so far.

49

Chapter 10

Changing the User Interface

With the changes in the database and the Visual Basic code in the business and data access layers done, the next step is to change the Management section. To manage the exceptions for a booking object, you’ll need to modify the page that allows you to insert or update a booking object.

1.Open CreateUpdateBookingObject.aspx.and add a new row to the bottom of the HTML table.

2.In the second cell of this row, add a GridView control. Bind this GridView to a new ObjectDataSource with the following specifications:

Property Name

Value

Id

odsExceptions

TypeName

BookingObjectManager

DeleteMethod

DeleteException

SelectMethod

GetExceptionList

3.Connect the SelectParameter for the Select method to a query string called Id and add a

DeleteParameter for the DeleteException method. The code for the ObjectDataSource should end up like this:

<asp:ObjectDataSource ID=”odsExceptions” runat=”server” DeleteMethod=”DeleteException”

SelectMethod=”GetExceptionList” TypeName=”BookingObjectManager”> <SelectParameters>

<asp:QueryStringParameter Name=”bookingObjectId” QueryStringField=”Id” Type=”Int32” />

</SelectParameters>

<DeleteParameters>

<asp:Parameter Name=”id” Type=”Int32” /> </DeleteParameters>

</asp:ObjectDataSource>

4.Set the DataKeyNames property of the GridView to Id and check Enable Deleting on the control’s Smart Tag dialog. The code for the GridView should end up like this:

<asp:GridView ID=”GridView1” runat=”server” DataSourceID=”odsExceptions” DataKeyNames=”Id”>

<Columns>

<asp:CommandField ShowDeleteButton=”True” /> </Columns>

</asp:GridView>

5.From the Toolbox, drag a Calendar and a Button right below the GridView. Rename the button to btnInsertNewExceptionDate. The calendar is used to insert new exception dates for the booking object. In the Click handler for the button, add the following code:

Protected Sub btnInsertNewExceptionDate_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnInsertNewExceptionDate.Click

50

Modifying the Appointment Booking System

If Calendar1.SelectedDate <> DateTime.MinValue Then BookingObjectManager.CreateException( _

Convert.ToInt32(Request.QueryString.Get(“Id”)), Calendar1.SelectedDate) GridView1.DataBind()

End If End Sub

This code gets the exception date from the calendar and passes it to CreateException, together with the ID of the booking object.

6.Since creating an exception requires the ID of a booking object, it’s a good idea to hide the calendar and the button when inserting a new booking object. After all, when inserting a new object, its ID is not available yet. To hide these controls, add the following code to the Else clause at the end of Page_Load:

Else

litHeading.Text = “Create new “ & AppConfiguration.BookingObjectNameSingular

Calendar1.Visible = False

btnInsertNewExceptionDate.Visible = False End If

7.Save all your pages and open the Appointment Booking System in a browser, go to the Management section and edit a booking object. You won’t see any exception dates yet, but you can add one by selecting the date on the calendar. Then click the button to insert the exception in the database. When the page reloads, you’ll see the new exception date appear in the

GridView.

8.To see if it all worked correctly, go to the Availability Checker and select the date you inserted in step 7. If everything worked fine, the entire day should not be available for the booking object you changed in step 7.

51

11

Modifying the Greeting Card

Application

The code you have seen in Chapter 11 just scratches the surface of what’s possible with GDI+ in

.NET. There are many classes and methods that enable you to fulfill all your drawing needs. The Graphics class alone has almost 70 methods that allow you to draw rectangles, curves, bezier shapes, lines, pies, and so on. You’ll find many more classes and useful methods, properties, and enumerations in the important drawing namespaces like System.Drawing, System.Drawing

.Drawing2D, System.Drawing.Imaging, and System.Drawing.Text. With these namespaces you could enhance the Toolkit with the following features:

Expand the Toolkit’s Imaging class with a method called AddImageToImage that places an image on top of anther image. This is useful when you want to add your company’s logo to each outgoing image, for example.

Add a method to the Imaging class called AddWatermark. This method can do the same as the AddImageToImage that was just mentioned, but in the AddWatermark you could make the image more or less transparent.

Add methods that give you finer control over the text being added to images. For example, you could create overloads or separate methods that can underline text, or make it semitransparent so it doesn’t disturb the image too much. This is a great enhancement if you want to protect your images with a small copyright notice.

Add drop shadow support to the AddTextToImage method. Using a tiny drop shadow effect on the text that is added to the image can make a big difference in how the text looks.

In addition to changing the Toolkit, you can also change the Greeting Card application. Since it’s just built to showcase the possibilities of GDI+ and the generic Toolkit, the application lacks a lot of features that you’d expect from a true Greeting Card application. Besides building user controls to implement the behavior suggested in the previous list, you could enhance the Greeting Card application with the following features:

Write clean-up code in Session_Start or at a specified interval that cleans up the Temp folder. Right now, the application leaves behind many temporary images in that folder that will fill up your server’s hard drive in no time. You could write code that uses the System.IO namespace to delete all images that are older than an hour or so.

Chapter 11

Implement a Profile system. Right now, the application is accessible for everyone. It could be interesting to limit access to the system to known users with a subscription only. This way, you can track the way they use the application, how often cards are sent, and so on.

Provide default image templates. In the current implementation, the user has to upload a custom file. However, for some users it would be easier if they could choose a ready-made template from a list.

As you can see, there are many ways in which the Greeting Card application and the Toolkit can be enhanced. To help you get started, the following walkthrough guides you through implementing two of these enhancements: adding images on top of other images, and adding a drop-shadow to the text. Remember, the code for these modifications is available on the companion CD, so you don’t have to type it in yourself.

Adding a Drop Shadow to the Text

When you first think about adding a drop shadow to text, you may think it’s a complex operation involving calculations of light direction, distance, and so on. However, in reality it’s quite easy to do. All you need to do is draw the same text in a black font on the same image, and move it a couple of pixels to the right and to the bottom of the original text (or in any other direction). If you draw the text behind the original text, you’ll only see the edges of the black text, so it looks like a drop shadow. To add this effect to the Greeting Card application, carry out the following steps:

1.Open the file Imaging.vb in the Toolkit folder, create a copy of the method AddTextToImage that accepts an input and an output file and remove all the implementation code.

2.Inside the empty body, add the following code:

AddTextToImage (fileNameIn, fileNameOut, myFont, fontColor, textLocation, _

textToAdd, False)

This new overloaded method ensures that existing code that doesn’t know about the new drop shadow feature won’t break. Notice the additional False parameter at the end of the method call. This value is passed to the AddTextToImage method that you’ll modify in the next step to ensure that existing code can still call the default AddTextToImage implementation without a drop shadow effect.

3.Next, add a new Boolean parameter to the original AddTextToImage method and call it addDropShadow. The method signature should end up like this:

Public Shared Sub AddTextToImage(ByVal fileNameIn As String, _

ByVal fileNameOut As String, ByVal myFont As Font, ByVal fontColor As Color,

ByVal textLocation As Point, ByVal textToAdd As String, _

ByVal addDropShadow As Boolean)

4.Inside this method, locate the line that starts with Dim myBrush As SolidBrush. Right before that line, add the following code:

Dim myDropShadowBrush As SolidBrush = New SolidBrush(Color.Black) myGraphics.DrawString(textToAdd, myFont, myDropShadowBrush, _

New Point(textLocation.X + 4, textLocation.Y + 4), myStringFormat)

54

Modifying the Greeting Card Application

It’s important to draw the drop shadow text before the original text is drawn, so the shadow appears to be behind the original text. Notice that the X and Y properties are increased by 4 to make the shadow 4 pixels wide and tall.

5.To allow a user to determine whether the shadow must be added or not, add an <asp:CheckBox> control to the AddText user control right below the Color drop-down in its own table row. Name the checkbox chkAddDropShadow and place some text in front of it describing its purpose. Give the table row an ID of rowShadow and make sure its runat attribute is set to server and its Visible property is set to False.

6.Locate the AddText method in the code-behind of the user control and add the Checked value of the checkbox as the last parameter to the call to Toolkit.Imaging.AddTextToImage. Your code should end up like this:

Toolkit.Imaging.AddTextToImage(Server.MapPath(FileName), _ Server.MapPath(TempFileName), aFont, myColor, _ textLocation, txtTextToAdd.Text, chkAddDropShadow.Checked)

7.In the lstFontName_SelectedIndexChanged method, add code that sets the Visible property of rowShadow to True, similar to how the other rows are made visible.

8.View the page in your browser and when you’re adding text, make sure to tick the drop shadow checkbox. When the page refreshes, you’ll notice that you now have a drop shadow behind the text.

Adding a Logo to the Uploaded Image

The next modification to the Toolkit and the Greeting Cards application is adding a logo to the image that the user uploaded. This logo is placed at the upper-left corner of the uploaded image, but of course you can change the location if you want. To add the image, make sure you have a file called WroxLogo.gif in the Images folder of your application and then perform the following steps:

1.Inside the file Imaging.vb add a new method with the following signature:

Public Shared Sub AddLogoToImage(ByVal fileNameIn As String,

ByVal fileNameOut As String, ByVal fileNameLogo As String)

2.Within the method’s body, add the following code:

Public Shared Sub AddLogoToImage(ByVal fileNameIn As String, _

ByVal fileNameOut As String, ByVal fileNameLogo As String)

Dim myGraphics As Graphics = Nothing

Dim mySourceBitmap As Bitmap = Nothing

Dim myTargetBitmap As Bitmap = Nothing

Dim myLogoBitmap As Bitmap = Nothing

Try

mySourceBitmap = New Bitmap(fileNameIn)

myTargetBitmap = New Bitmap(mySourceBitmap.Width, mySourceBitmap.Height)

myLogoBitmap = New Bitmap(fileNameLogo)

myGraphics = Graphics.FromImage(myTargetBitmap)

myGraphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic myGraphics.SmoothingMode = Drawing2D.SmoothingMode.None

myGraphics.DrawImage(mySourceBitmap, New Rectangle(0, 0, _

55

Chapter 11

mySourceBitmap.Width, mySourceBitmap.Height), 0, 0, _ mySourceBitmap.Width, mySourceBitmap.Height, GraphicsUnit.Pixel)

myGraphics.DrawImage(myLogoBitmap, New Rectangle(5, 5, myLogoBitmap.Width, _ myLogoBitmap.Height), 0, 0, _

myLogoBitmap.Width, myLogoBitmap.Height, GraphicsUnit.Pixel)

mySourceBitmap.Dispose()

myTargetBitmap.Save(fileNameIn)

Catch ex As Exception

Throw

Finally

If myTargetBitmap IsNot Nothing Then myTargetBitmap.Dispose()

End If

If mySourceBitmap IsNot Nothing Then mySourceBitmap.Dispose()

End If

If myLogoBitmap IsNot Nothing Then myLogoBitmap.Dispose()

End If

If myGraphics IsNot Nothing Then myGraphics.Dispose()

End If End Try

End Sub

This code performs a few actions. First, it reads in the original file. It then creates a new Graphics object that has the same dimensions as the original file. The first call to DrawImage copies the bitmap from the original file onto the new bitmap. This is necessary so the original bitmap can be disposed, so the original file can be overwritten with the Save method at the end of the code.

The second call to DrawImage copies the logo bitmap from myLogoBitmap onto the target bitmap using the same code you saw in the CropImage method. It copies the entire bitmap held in myLogoBitmap and places it in the upper-left corner of the target bitmap.

3.The final step is to modify the SelectImage control so it also calls the AddLogoToImage method you just created. The best place to do this is inside the btnUpload_Click method, right after the call to ResizeImage. Add the following highlighted code in btnUpload_Click:

Toolkit.Imaging.ResizeImage(Server.MapPath(FileName), _

AppConfiguration.MaxImageWidth, AppConfiguration.MaxImageHeight)

Toolkit.Imaging.AddLogoToImage(Server.MapPath(FileName), _

Server.MapPath(FileName), Server.MapPath(“~/Images/WroxLogo.gif”))

imgUploaded.ImageUrl = FileName

This adds the logo to the image right after it has been resized to the maximum dimensions. Server.MapPath is used to translate the virtual path ~/Images/WroxLogo.gif into the physical location of the logo.

4.Open up Default.aspx in your browser and upload an image. When the image is displayed, it now has a small logo in the upper-left corner.

56