Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 64 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
64
Dung lượng
761 KB
Nội dung
it into the label control in the middle of the table on the page. This gives us our head- ers and basic table structure when we show the various rows. The code behind this page is shown in Listing 8.12 and uses a lot of the features demonstrated in the first project to generate the output. Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports TWNWObjects Namespace TWNW Public Class PostsView Inherits Page Protected lblPageTitle As Label Protected lblContent As Label Sub Page_Load(objSender As Object, objArgs As EventArgs) Dim strColor As String = “tabletext” If (Request.Cookies(“mID”) Is Nothing) Then Response.Redirect(“login.aspx?msg=403&rURL=” _ & Request.ServerVariables(“SCRIPT_NAME”) _ & “?” _ & Request.ServerVariables(“QUERY_STRING”)) End If Dim DB As New AtWorkUtilities.Database() Dim DBR As New AtWorkUtilities.Database() Dim SD, SDR As SqlDataReader If Int16.Parse(Request.QueryString(“tID”)) > 0 Then Dim T As New Team(DB, Request.QueryString(“tID”)) Dim DR As DataRow = T.GetRow() lblPageTitle.Text = “View Posts - “ & DR(“Name”) DB.Execute(“sp_UpdateMemberDiscussionHistory “ _ & Request.Cookies(“mID”).Value & “, “ _ & Request.QueryString(“tID”)) Else lblPageTitle.Text = “View Posts - Public Forum” DB.Execute(“sp_UpdateMemberDiscussionHistory “ _ & Request.Cookies(“mID”).Value & “, 0”) End If SD = DB.GetDataReader(“sp_RetrieveOriginalPostsByTeam “ _ & Request.QueryString(“tID”), True) Dim SB As New System.Text.StringBuilder() Do While SD.Read() Listing 8.12 posts_view.aspx.vb Teamwork Network: Discussion Boards 495 SB.AppendFormat(“<tr class=””{0}””>”, _ strColor) SB.AppendFormat(“<td>{0}</td>”, _ SD(“Author”)) SB.AppendFormat(“<td>{0}</td>”, _ SD(“Subject”)) SB.AppendFormat(“<td align=””center””>{0} {1}</td>”, _ SD(“PostDate”).ToShortDateString, _ SD(“PostDate”).ToShortTimeString) SDR = DBR.GetDataReader(“sp_RetrieveStatisticsByPost “ _ & SD(“pkPostID”)) If SDR(“LastReplyDate”).ToString() = “” Then SB.Append(“<td align=””center””>None</td>”) Else SB.AppendFormat(“<td align=””center””>{0} {1}</td>”, _ SDR(“LastReplyDate”).ToShortDateString, _ SDR(“LastReplyDate”).ToShortTimeString) End If SB.AppendFormat(“<td align=””center””>{0}</td>”, _ SDR(“ReplyCount”)) SDR.Close() SB.Append(“</tr>” & Environment.NewLine) If strColor = “tabletext” Then strColor = “tabletext_gray” Else strColor = “tabletext” End If Loop DB.Close() DBR.Close() lblContent.Text = SB.ToString() End Sub End Class End Namespace Listing 8.12 posts_view.aspx.vb (continued) We start by verifying that the user has logged into the system. This prevents some- one who has bookmarked the page from getting back in without a valid username and password. We then create two different Database objects: one to show the threads and the other to get the counts. We’ll be using the SqlDataReader object here, but we can only have a single SqlDataReader open at a time with a given connection. Next, we look at the value of the tID value in the query string. If it is absent or zero, we are going to view the public forum. Otherwise, we are looking at a particular team’s discussion board. At this time, we call the stored procedure to update this member’s history record for this particular board. This is the only place we call this stored proce- dure, so there’s no point in making a separate business object to call it. 496 Project 8 We then start looping through the threads found in the database for this team. Each one is shown in a separate row, and when we get to the cells that show the number of replies and the last reply date, we call our second stored procedure, get the values, and then close the second SqlDataReader object. Since the database itself can’t generate this sort of drill-down information in a straightforward way, this method works well. Once we’re done looping through all the records and building the HTML into our StringBuilder object, we put the output into the label control that we added to the ASPX file. This displays the output to the user and gives the user the opportunity to select a thread to view, which is handled by the next page we need to cover. The user can also post a message to this team’s discussion board by clicking the link at the top of the page. We’ll build this page after the thread viewer. Once the user has selected a thread to view, we show the user the Posts_read.aspx page, which is shown in Listing 8.13. This page uses the Repeater control, but not in the wide table-style view we’ve been using in most of the other pages. We’re also not using an alternating row template here since every row looks the same. <%@ Page Inherits=”TWNW.PostsReadThread” Src=”posts_read.aspx.vb” %> <%@ Register Tagprefix=”TWNW” Tagname=”Header” Src=”Header.ascx” %> <%@ Register Tagprefix=”TWNW” Tagname=”Footer” Src=”Footer.ascx” %> <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”> <html> <head> <title>Teamwork Network: View Thread</title> <link href=”styles.css” rel=”stylesheet” type=”text/css”> </head> <body leftmargin=0 topmargin=0> <TWNW:Header id=”PageHeader” runat=”server” /> <p class=”pageheading”>View Thread</p> <p class=”text”> <a href=”post_create.aspx?tid=<% = Request(“tid”) %>”>Post a New Message</a> | <% Response.Write(“<a href=””post_create.aspx?tid=” _ & Request.QueryString(“tid”) _ & “&pid=” _ & Request.QueryString(“pid”) _ & “””>Reply to this Thread</a>”) %> </p> <asp:label id=”lblMessage” class=”text” runat=”server” /> <asp:Repeater id=”rptList” runat=”server”> <HeaderTemplate> <table cellpadding=”4” cellspacing=”0” width=”600”> </HeaderTemplate> <ItemTemplate> <tr class=”tabletext_gray”> <td align=”right” width=”20%”>Author:</td> Listing 8.13 posts_read.aspx Teamwork Network: Discussion Boards 497 <td width=”80%”> <%# DataBinder.Eval(Container.DataItem, “Author”) %> </td> </tr> <tr class=”tabletext_gray”> <td align=”right”>Subject:</td> <td> <%# DataBinder.Eval(Container.DataItem, “Subject”) %> </td> </tr> <tr class=”tabletext_gray”> <td align=”right”>Message Posted:</td> <td> <%# DataBinder.Eval(Container.DataItem, _ “PostDate”).ToShortDateString %> <%# DataBinder.Eval(Container.DataItem, _ “PostDate”).ToShortTimeString %> </td> </tr> <tr class=”tabletext”> <td colspan=”2”> <%# Server.HTMLEncode(DataBinder.Eval( _ Container.DataItem, _ “MessageText”)) %> </td> </tr> </ItemTemplate> <SeparatorTemplate> <tr><td colspan=2> </td></tr> </SeparatorTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> </body> </html> <TWNW:Footer id=”PageFooter” runat=”server” /> </body> </html> Listing 8.13 posts_read.aspx (continued) This page starts with the standard header information and provides two links: one to create a new message in this team’s board, and another to post a reply to this thread. Since all replies are to the original message, we don’t need a separate link for each reply. We then set up the table where the message data will be shown. For the actual message 498 Project 8 text, we prevent members from putting up malicious (intentional or otherwise) HTML by using the Server.HTMLEncode method on the data being shown. Note that this par- ticular field doesn’t bind directly to the field using the <%# symbol. Instead, we use the Response.Write method to print the values from the bound data, but first route it through our HTMLEncode function. This gives us the benefit of fixing the data without having to build the table manually. The code behind this page follows the same pattern as most other data-bound pages, and is shown in Listing 8.14. Imports System Imports System.Data Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports TWNWObjects Namespace TWNW Public Class PostsReadThread Inherits Page Protected lblMessage As Label Protected rptList As Repeater Sub Page_Load(objSender As Object, objArgs As EventArgs) If (Request.Cookies(“mID”) Is Nothing) Then Response.Redirect(“login.aspx?msg=403&rURL=” _ & Request.ServerVariables(“SCRIPT_NAME”) _ & “?” _ & Request.ServerVariables(“QUERY_STRING”)) End If Dim DB As New AtWorkUtilities.Database() Dim DS As DataSet = _ DB.GetDataSet(“sp_RetrieveThreadByPostID “ _ & Request.QueryString(“pid”)) If DS.Tables(0).Rows.Count = 0 Then lblMessage.Text = “<b>There are no messages in “ _ & “this thread.</b>” Else rptList.DataSource = DS rptList.DataBind() End If db.Close() End Sub End Class End Namespace Listing 8.14 posts_read.aspx.vb Teamwork Network: Discussion Boards 499 The stored procedure does most of the work here in formatting the links to the mem- ber profiles. All we have to do is present the data in a readable format. We also make sure that there are messages in the thread to prevent any errors from occurring. Since the only legitimate way to get to this page is by clicking a link from the previous page, any errors are going to come from out-of-date page references where messages may have been manually deleted. The final page we need to build allows users to post new messages or replies to existing threads. The ASPX file is shown in Listing 8.15. <%@ Page Inherits=”TWNW.PostCreate” Src=”post_create.aspx.vb” %> <%@ Register Tagprefix=”TWNW” Tagname=”Header” Src=”Header.ascx” %> <%@ Register Tagprefix=”TWNW” Tagname=”Footer” Src=”Footer.ascx” %> <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”> <html> <head> <title>Teamwork Network: Post a Message</title> <link href=”styles.css” rel=”stylesheet” type=”text/css”> </head> <body> <TWNW:Header id=”PageHeader” runat=”server” /> <table width=”600”> <tr> <td valign=”top” width=”600”> <p><asp:label id=”lblPageTitle” class=”pageheading” runat=”server” /></p> <asp:label id=”lblErrorMessage” class=”errortext” runat=”server” /> <form runat=”server”> <input type=”hidden” runat=”server” id=”fkTeamID”> <input type=”hidden” runat=”server” id=”fkOriginalPostID”> <table cellspacing=”5”> <tr class=”tabletext”> <td align=”right”>Subject:</td> <td> <asp:textbox id=”txtSubject” columns=”40” maxlength=”80” runat=”server” /> </td> </tr> <tr class=”tabletext”> <td valign=”middle” align=”right”> Message Text: </td> <td> <asp:textbox Listing 8.15 post_create.aspx 500 Project 8 id=”txtMessageText” rows=”15” columns=”60” wrap=”true” textmode=”Multiline” runat=”server” /> </td> </tr> <tr class=”tabletext”> <td colspan=2 align=middle> <input type=”submit” name=”btnSubmit” runat=”server” value=”Save” /> <input type=”reset” name=”btnReset” runat=”server” value=”Clear” /> </td> </tr> </table> </form> </td> </tr> </table> <TWNW:Footer id=”PageFooter” runat=”server” /> </body> </html> Listing 8.15 post_create.aspx (continued) This page is similar to the Message Creation page we built in the last project, with some changes to the field names and visible text. We only need two visible boxes on the page: the subject and the message text. The member’s cookie holds their member ID number, and the hidden-input fields allow us to hold the team ID number (passed in through the query string) and the thread’s original message ID number, if any. The code behind this page is shown in Listing 8.16. Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports TWNWObjects Listing 8.16 post_create.aspx.vb Teamwork Network: Discussion Boards 501 Namespace TWNW Public Class PostCreate Inherits System.Web.UI.Page Protected txtSubject As TextBox Protected txtMessageText As TextBox Protected fkTeamID As HTMLControls.HTMLInputHidden Protected fkOriginalPostID As HTMLControls.HTMLInputHidden Protected lblPageTitle As Label Protected lblErrorMessage As Label Sub Page_Load(objSender As Object, objArgs As EventArgs) Dim DB As New AtWorkUtilities.Database() Dim P As Post Dim DR As DataRow Dim objCookie As HTTPCookie objCookie = Request.Cookies(“mID”) If Not Page.IsPostBack Then fkTeamID.Value = Request.QueryString(“tID”) If Request.QueryString(“pID”) = “” Then ‘ ‘ New message to team lblPageTitle.Text = “Post New Message” Else ‘ ‘ Reply to existing message lblPageTitle.Text = “Reply to Message” fkOriginalPostID.Value = Request.QueryString(“pID”) End If Else P = New Post(DB) DR = P.GetRow() DR(“fkAuthorID”) = Int16.Parse(objCookie.Value) If fkOriginalPostID.Value <> “” Then DR(“fkOriginalPostID”) = Int16.Parse(fkOriginalPostID.Value) End If DR(“fkTeamID”) = Int16.Parse(fkTeamID.Value) DR(“Subject”) = txtSubject.Text DR(“MessageText”) = txtMessageText.Text P.SaveRow(DR) If Not P.IsValid Then lblErrorMessage.Text = _ P.ValidationError(“<b>ERROR:</b> The following “ _ & “errors were detected in your data:<br>”, _ “• {0}<br>”, “”) Listing 8.16 post_create.aspx.vb (continued) 502 Project 8 TEAMFLY Team-Fly ® Else P.Save() DB.Close() Response.Redirect(“posts_view.aspx?tid=” _ & fkTeamID.Value) End If End If End Sub End Class End Namespace Listing 8.16 post_create.aspx.vb (continued) When the page is first shown, we determine if we’re creating a new message in a board or a reply to an existing thread. We store the appropriate values in the hidden- input fields and then let the user type the message. When we save the data, we store it in our new Post object, which sets the posting date. If any data is missing, those errors are returned from the object and displayed to the user. Otherwise, we save the posting and go back to the discussion-board thread viewer (Posts_view.aspx). If you want, you can go back to the thread so the user can see his or her message. Note that there is no provision made for editing or deleting an existing post. These may be features you want to add to your own system. The Post object already supports these features since it follows the same design pattern as the other objects we’ve built. You just need to modify this page to repopulate the form if the post is being edited, just as you did in previous portions of this application. You could also restrict editing and posting to the original writer of the message. The reason that I didn’t provide this feature is data integrity. If you delete the first message in a thread, the other replies will be unlinked. Since deletions would probably be somewhat rare, I leave this up to the system administrator to do manually if the need should arise. With all those pages done, we still need to make one change to the Teams.aspx page so that users can pick a team to post a message to if no messages exist. It also provides another way into the system from a different location. The new Teams.aspx page is shown in Listing 8.17 with the changes highlighted in bold. <%@ Page Inherits=”TWNW.TeamsViewAll” Src=”teams.aspx.vb” %> <%@ Register Tagprefix=”TWNW” Tagname=”Header” Src=”Header.ascx” %> <%@ Register Tagprefix=”TWNW” Tagname=”Footer” Src=”Footer.ascx” %> <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”> <html> <head> <title>Teamwork Network: View All Teams</title> Listing 8.17 teams.aspx Teamwork Network: Discussion Boards 503 <link href=”styles.css” rel=”stylesheet” type=”text/css”> </head> <body leftmargin=0 topmargin=0> <TWNW:Header id=”PageHeader” runat=”server” /> <p class=”pageheading”>View All Teams</p> <p class=”text”><a href=”team_create.aspx”>Create a Team</a></p> <asp:label id=”lblMessage” class=”text” runat=”server” /> <asp:Repeater id=”rptList” runat=”server”> <HeaderTemplate> <table cellpadding=”4” cellspacing=”0” width=”100%”> <tr class=”tableheading”> <td width=”30%”>Name</td> <td width=”30%”>Description</td> <td width=”40%”>Actions</td> </tr> </HeaderTemplate> <ItemTemplate> <tr class=”tabletext”> <td valign=”top”><%# DataBinder.Eval(Container.DataItem, _ “Name”) %></td> <td valign=”top”><%# DataBinder.Eval(Container.DataItem, _ “Description”) %></td> <td valign=”top” align=”center”> <a href=”teammembers.aspx?id=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Manage Members</a> <a href=”post_create.aspx?tid=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Post Message</a> <a href=”team_create.aspx?id=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Update</a> <a href=”team_delete.aspx?id=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Delete</a> </td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr class=”tabletext_gray”> <td valign=”top”><%# DataBinder.Eval(Container.DataItem, _ “Name”) %></td> <td valign=”top”><%# DataBinder.Eval(Container.DataItem, _ “Description”) %></td> <td valign=”top” align=”center”> <a href=”teammembers.aspx?id=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Manage Members</a> <a href=”post_create.aspx?tid=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Post Message</a> Listing 8.17 teams.aspx (continued) 504 Project 8 [...]... Validate() Dim dr As DataRow ClearErrors() For Each dr In m_DS.Tables(0).Rows If dr.RowState = DataRowState.Added _ Or dr.RowState = DataRowState.Modified Then ValidateRow(dr) End If Next End Sub ‘ ‘ Checks an individual row for validation rule ‘ compliance Any errors are added to the errors ‘ collection ‘ Private Sub ValidateRow(ByVal dr As DataRow) Listing 9. 8 File.vb class (continued) Teamwork Network:...Teamwork Network: Discussion Boards Update Delete 102 4^3 Then strSize = Math.Round(DR(“FileSize”) / 102 4^3, _ 1).ToString() & “ Gb” ElseIf DR(“FileSize”) > 102 4^2 Then strSize = Math.Round(DR(“FileSize”) / 102 4^2, _ 1).ToString()... Listing 9. 13 pages.aspx.vb (continued) As with the other pages we’ve built that gather statistics for each displayed row, we now have to set up two separate database connections here The primary connection, DB, will be used for the main loop The DB2 connection will be used for gathering the necessary per-row statistics We start by adding the public file library entry to the table that we’re building. .. Not Null 5 09 510 Project 9 Table 9. 2 tblFolders Table Design FIELD NAME SQL DATA TYPE LENGTH OTHER pkFileID int N/A Identity, Primary Key, Not Null fkTeamID int N/A Not Null Name varchar 120 Not Null Description text N/A CreationDate datetime N/A Not Null fkCreatorID int N/A Not Null We are keeping a link to the team from both the folder and any files This makes it possible to have files that are not... Folder class is shown in Listing 9 .10 Imports AtWorkUtilities Imports System.Data.SqlClient Public Class Folder Inherits BaseServices ‘ ‘ If no arguments are supplied, build a separate ‘ database connection for this object ‘ Public Sub New() MyBase.New(New Database(), “SELECT * FROM tblFolders WHERE 1=0”) End Sub ‘ ‘ If database connection is supplied, store it ‘ in the private connection variable for this . dis- cuss at the book’s Web site: www.10projectswithasp .net. We’ll add new features as time goes on to make this site useful for everyone. Teamwork Network: File Libraries PROJECT 9 THE PROBLEM Sharing. href=”team_create.aspx?id=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Update</a> <a href=”team_delete.aspx?id=<%# DataBinder.Eval(Container.DataItem,. href=”post_create.aspx?tid=<%# DataBinder.Eval(Container.DataItem, _ “pkTeamID”) %>”>Post Message</a> <a href=”team_create.aspx?id=<%# DataBinder.Eval(Container.DataItem,