ASP.NET 3.5 Social Networking : Messaging (part 4) - Implementing the presentation layer

2/16/2013 8:26:45 PM

3.4 Implementing the presentation layer

Now that our framework has been updated to handle the new concept of messaging, let's start creating some UI features so that we can use our new tools. We are going to need at least three pages to really utilize our messaging features. We will need a way to create and send a new message, a way to receive and view the messages, and a way to read an individual message. In addition to the creation of a message, we will need a way to easily choose from our list of friends, the recipients of our new messages. Also, while viewing our list of messages, we will need a way of drilling into different folders of messages. Let's get started!

New message

The UI for the new message page is relatively trivial. It consists of a To field, a Subject field, a message field, and a button to signify that we are ready to send the message. Where things are significantly different is in the use of the Xinha WYSIWYG editor! This is a JavaScript library that allows you to transform a multiline text box into a full-featured editor.

Then open the SiteMaster.Master page. Directly after the body add the following JavaScript.

<script type="text/javascript">
xinha_editors = null;
xinha_editors = xinha_editors ? xinha_editors : [];

This code is not part of the standard install process. What it does is allow us to spin up multiple instances of the editor all throughout a single page. You will see this later.

Then further down in our master page, just before the ending body tag, we will insert another huge blob of JavaScript. This is a very large blob that could just as easily be inserted into an external .js file. I am not going to show it here.

You will see that this blog is responsible for setting the vast amount of configuration options that Xinha exposes. This code is heavily commented and so should be understandable. Also, the configuration of this package is covered extensively on the net!

The only thing, but definitely the special one, I added to in this configuration is the very first line that sets the base URL of the site. In this case, I changed it to use a call into the WebContext.RootUrl property.

_editor_url = "<%= _webContext.RootUrl %>Xinha/";

This brings us back to our NewMessage.aspx page. Now that we have Xinha installed, we can add a line below our page UI that effectively ties our multiline text box control to the Xinha library. This is done with a snippet of JavaScript.

<script type="text/javascript">
xinha_editors[xinha_editors.length] = 'ctl00_Content_txtMessage';

Note that this is using the same xinha_editors variable that we defined initially in the Master page! What we have done here is to insert this new control into an array of Xinha editors. Note that we are using the full ClientID of the text box that we want associated as an editor.

Now, we will move on to the presenter of this page. This page has three primary tasks:

  • To send a message

  • To preload a recipient of a message (if linked to from an Alert) and

  • To send a reply to a message

This is really the same thing with the exception that to send a reply to a message, we would first have to load that reply. We will get to that down the road!

To send a message, we have to bubble up the button click event through our code behind and into our presenter. As I have covered this concept extensively, I will not cover it here. So, in the presenter, we have added a method called SendMessage(), which takes in the Subject, Message, and an array of To entries.

public void SendMessage(string Subject, string Message, string[] To)

This method then calls into the MessageService.SendMessage() method and sends the message.

The preloading of a recipient is handled in the Init() method of the presenter. It checks to see if we have an AccountID in the QueryString (via our WebContext wrapper). If so, it gets the Accounts Username property and adds that to the To field in the UI.

Loading a reply message into the UI is very similar to loading a username. The Init() method checks the WebContext to see if we have a MessageID in the QueryString and loads the previous Message details into the UI.

public void Init(INewMessage view)
_view = view;
if(_webContext.MessageID != 0)
_view.LoadReply(_messageRepository.GetMessageByMessageID(_ webContext.MessageID,_userSession.CurrentUser.AccountID));
if(_webContext.AccountID != 0)
_view.LoadTo(_accountRepository.GetAccountByID( _webContext.AccountID).Username);


Friends control

The other important feature that we have as part of the NewMessage.aspx page is the ability to easily select a friend from a list of friends as the recipient of a message. To achieve this, we will create a user control that lists our friends.

The UI for this control is just a simple Repeater object that outputs a friend's username. So let's take a look at what populates the UI. In the Init() method in the FriendPresenter.cs file, we have a call into the FriendRepository.GetFriendsAccountsByAccountID() method, which loads all the users' friends. This is bound to the repeater control in the UI.

public void Init(IFriends view)
_view = view;
_view.LoadFriends(_friendRepository.GetFriendsAccountsByAccountID(_us erSession.CurrentUser.AccountID));


In the code behind for our friend control, we insert a snippet of JavaScript to allow us to click on a friend and carry his/her username into our To field in our NewMessage UI.

public void repFriends_ItemDataBound(object sender, RepeaterItemEventArgs e)
if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
HyperLink linkFriend = e.Item.FindControl("linkFriend") as HyperLink;
linkFriend.Attributes.Add("OnClick", "javascript:document.forms[0]. ctl00_Content_txtTo.value += '" + ((Account)e.Item.DataItem).Username + ";';");


Note that we are adding an attribute for the OnClick event of our link that will call a JavaScript to move the username to our To field with a semicolon delimiter.

This gives us a list of friends, but how do we tie that back into our UI? Open the NewMessage.aspx page. We will need to register the new control in the page and then add a reference to it in the page.

Just below the Page directive add the following code:

<%@ Register Src="~/Mail/UserControls/Friends.ascx"
TagPrefix="Fisharoo" TagName="Friends" %>

Then add a new Content section to our page where the friends control will live:

<asp:Content ContentPlaceHolderID="LeftNavTop" runat="server">
<Fisharoo:Friends ID="friends1" runat="server" />

This inserts the friends control into the top of our left nav!&;

Default (or Inbox)

Now that we can successfully send a message, we need a way to receive those messages. This is done in folder view of our messages. This is really just a page that shows a list of messages, who sent them, and when. We can either click on the sender to go to their profile page, or can click on the message to view it. We can also navigate through pages of messages with a list of page navigation links. And we will have the ability to delete one or many selected messages. Additionally, we will create a Folders control that will allow us to navigate through our various folders to see the messages in those containers.

The UI for this page is very simple. It is just a repeater that iterates through the MessageWithRecipient collection that is passed to it. So let's take a look at the presenter, which actually populates our list of messages. As always this is accomplished in the Init() method of the presenter.

public void Init(IDefault view)
_view = view;
if (_userSession.CurrentUser != null)
_view.LoadMessages(_messageRepository.GetMessagesByAccountID( _userSession.CurrentUser.AccountID,
_webContext.Page, (MessageFolders) _webContext.FolderID));
_messageRepository.GetPageCount((MessageFolders) _webContext.FolderID,
(MessageFolders) _webContext.FolderID, _webContext.Page);


We first check to see that the user of the page is actually logged in. We then make a call into the MessageRepository to get a list of messages by the user's AccountID. We also make a call into MessageRepository to get a page count (the number of pages of messages that we have to navigate through).

Loading messages into the UI is simply a matter of binding the DataSource to the repeater.

public void LoadMessages(List<MessageWithRecipient> Messages)
repMessages.DataSource = Messages;

As this requires no explanation, let's jump right into how we go about building our page navigation. Recall that in the Init() of our presenter we had a call into the view of DisplayPageNavigation(),which received the PageCount of the folder we were working with, and the current page we were viewing. Here is that method:

public void DisplayPageNavigation(Int32 PageCount, MessageFolders folder, Int32 CurrentPage)
if(PageCount == CurrentPage)
linkNext.Visible = false;
if (CurrentPage == 1)
linkPrevious.Visible = false;
linkNext.NavigateUrl = "~/mail/default.aspx?folder=" + ((int) folder).ToString() + "&page=" +
(CurrentPage + 1).ToString();
linkPrevious.NavigateUrl = "~/mail/default.aspx?folder=" + ((int) folder).ToString() + "&page=" +
(CurrentPage - 1).ToString();
for(int i = 1; i<=PageCount;i++)
HyperLink link = new HyperLink();
link.Text = i.ToString();
link.NavigateUrl = "~/mail/default.aspx?folder=" + ((int)folder).ToString() + "&page=" + i.ToString();
phPages.Controls.Add(new LiteralControl("&nbsp;"));


This chunk of code interacts with three controls in our UI — two hyperlinks, one that displays Previous and one displaying Next, and a PlaceHolder control that will hold the individual page numbers of all the pages for this data set.

This method initially determines if we should show the Next or Previous links based on our current page and our total page count. We then hook up the navigation property of each of those links to take us to the next page or the previous page of data. After that we use a for loop to iterate through all the possible pages, from 1 to PageCount, making a new hyperlink for each iteration that contains the location of that page.

The other feature of this page is the ability to delete messages — as many or as few as we like. This is primarily achieved with a helper function in the code behind of the view that extracts all the messages that are selected, which can be called from within the presenter. This allows the presenter to remain in control!

public List<Int32> ExtractSelectedMessages()
List<Int32> result = new List<Int32>();
foreach (RepeaterItem item in repMessages.Items)
if(item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
CheckBox chkMessage = item.FindControl("chkMessage") as CheckBox;
Int32 messageID = Convert.ToInt32(chkMessage.Attributes["MessageID"]);
return result;


This method iterates through all the check boxes to see if they are selected or not. If they are, then it extracts the MessageID from an attribute that was created when we loaded the display. A collection of MessageIDs is then returned to the caller.

This then brings us to the Delete method in the presenter. It is called from a button click event that is bubbled up to the presenter, which then calls into the view to get a list of selected MessageIDs. Then using the MessageRepository we get a copy of that message. With the copy, we then call into the MessageRecipientRepository.DeleteMessageRecipient() method and delete each selected MessageRecipient.


I hate to sound like a broken record but I find myself saying that this UI is also simple. is! This UI is also made up of a Repeater that displays the bound data. In this case, we are displaying folders as hyperlinks, which then link to the same Default.aspx page, but additionally pass in the folder that we are interested in viewing.

I am going to jump right in to the presenter so that we can see the DataSource for our data.

public void Init(IFolders view)
_view = view;


In this case, we are calling into the MessageFolderRepository to get a list of folders for this user. We bind that directly to the UI through our view. The view then iterates through the data in our repeater. In our ItemDataBound method — in the code behind of the view — we update each hyperlink in the UI.

protected void repFolders_ItemDataBound(object sender, RepeaterItemEventArgs e)
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
HyperLink linkFolder = e.Item.FindControl("linkFolder") as HyperLink;
linkFolder.Text = ((MessageFolder)e.Item.DataItem).FolderName;
linkFolder.NavigateUrl = "~/Mail/Default.aspx?folder=" +
((MessageFolder) e.Item.DataItem).MessageFolderID.ToString();
linkFolder.Attributes.Add("FolderID", ((MessageFolder)e.Item.DataItem). MessageFolderID.ToString());


This creates a list of folders for us in a control. But how do we get it into our UI? To do this, we have to go back to our Default.aspx page. This will be done exactly the same way we did for our friends control in our new message page. Open the default page so that we can add the Folders control.

<%@ Register Src="~/Mail/UserControls/Folders.ascx" TagPrefix="Fisharoo" TagName="Folders" %>
<asp:Content ContentPlaceHolderID="LeftNavTop" runat="server">
<Fisharoo:Folders id="Folders1"


Read message

Reading a message is not that difficult at all. We are just loading a message into a static UI based on the MessageID that is passed into the page. Let's first discuss the UI (which could easily be made more complex down the road!). This UI will consist of a From Label, a Subject Label, a Message Label, and a Reply button.

Here is the message view:

And here is what will be seen when replying to the message:

As usual, as all the leg work is done in the presenter, let's jump straight to it.

public void Init(IReadMessage view)
_view = view;
_view.LoadMessage(_messageRepository.GetMessageByMessageID(_webContex t.MessageID,_userSession.CurrentUser.AccountID));


As you can see here, we are populating the UI based on a call into the MessageRepository.GetMessageByMessageID() method. This method sends a MessageWithRecipient into the view, which then loads the message for display. Now that is simple!

For&; the Reply button, we will bubble up the click event into the presenter. The presenter then makes a call to the Redirector class that passes the current MessageID to the NewMessage page. Simple again!

public void Reply()
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone