Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-flash-10-multiplayer-game-game-interface-design
Packt
28 Jul 2010
10 min read
Save for later

Flash 10 Multiplayer Game: Game Interface Design

Packt
28 Jul 2010
10 min read
(For more resources on Flash and Games, see here.) Overview of Pulse library components The Pulse package includes two components Pulse.swc and PulseUI.swc.The Pulse.swc offers the API required for you to build a multiplayer game. While PulseUI offers the game screen management, both aid in the rapid development of your game. The Pulse.swc is required in order to communicate with the server and with other clients. The usage of PulseUI, on the other hand, is optional. It is recommended to use the PulseUI since it allows you to focus only on the game implementation and leaves the standard feature set of a multiplayer game to be taken care of by the PulseUI package. Once you have the implementation of your game done and working well, you can then replace the PulseUI package with something of your own that is more suited to your game. The following is a block diagram that shows the dependencies among different components: The Pulse API design The interaction of the game client with the server and other clients happens primarily via two classes that expose the Pulse features: GameClient GameClientCallback The GameClient is primarily used to send request to the server while creating a room, joining a room, or sending a message to other players such as chat or game state updates during game play. The GameClientCallback is an AS3 interface class for which one of the classes within the GameClient must implement. All notifications from the server are processed by the Pulse layer and corresponding notifications are called on the implementation of the callback class—for example, when a create room request was successful or when a chat message was received, etc. Creating the Hello World sample Let us now explore the Hello World sample that is included in the Pulse package. The Hello World sample and the rest of the samples rely heavily on the game screen management framework package, PulseUI, which is also included in the Pulse package along with the source code. In this article, we will focus on the code contained in the Hello World sample and how the sample makes use of the PulseUI. In order to explore the Hello World sample, we first need to create a project in Flash Builder—all the required source files already exists in the sample folders. The Hello World sample does the following: create a room or join an existing game room, then add, remove, or modify a game state—the changes done on one client instance are then reflected on all other clients that are in the same room. Think it is too much for a Hello World sample? It is not! These are just the basic functionalities for any multiplayer game. Moreover, we don't need to write the code for every bit of functionality because we heavily rely on Pulse SDK to do all the dirty work. Setting up the project Fire up the Flash Builder 4 IDE and let us start by creating an ActionScript project called Hello World: From the main menu, navigate to File | New | ActionScript Project. You will see the following screenshot. Enter a project name HelloWorld or any other name of your choice. Since we already have the entire source required for Hello World from the Pulse package, click on Next to specify that the source folder is already on the disk. This will bring up the following screen where we choose the Hello World src folder as shown. Note that the screenshot shows that Pulse was installed under F:Gamantra. This path may be different on your computer. Once we have chosen the source folder, we still need to choose the main source folder and main application file. Unfortunately, in order to do this, we need to navigate a bug in Flash Builder 4. You need to click on the Back button and then again on the Next button, bringing us back to where we were. We now click on the Browse button, as shown in the screenshot, and choose the [source path] src and click on OK. Next we choose the main application file—this determines the main class file that the execution will start with. We need to tell the Flash Builder to use the Pulse libraries for this project. In the Flash world, the library files come with an extension .swc, which stands for shockwave component. Once you make it available to your project, you can start using the classes and functions that are exposed from within the library. In order to do so, choose the Library Path tab view and click on the Add SWC… button; navigate to the lib folder within the Pulse installation folder and choose Pulse.swc and once again do the same procedure for PulseUI.swc. Click on the Finish button. As a final step, before attempting to run the sample, we also need to set the stage size to 800 (width) by 600 (height). The PulseUI requires the stage size to be exactly this size. We may also set the background color of our choice as shown in the following screenshot: After this step, Flash Builder 4 should be able to crunch all the code in folders and report no problems. This will also create the swf files under the project folder within the workspace ready for you to take it for a spin. At this point, you may also use the debugger to step through the code. But make sure the Pulse server is running so that you may login and explore all the screens. The Hello World specification The Hello World client will be able to create a new HelloGameState and share it with other players, and any player may change the x and y and have that change reflected in every player's screen. Here is the final screen that we will end up with: The screenshot is that of the game screen. The circles are a visual representation of the game states, the position of the circle comes from the corresponding game states x and y values and so does the color from the color property. We will have two buttons: one to add new game states and another to remove them. To add a new circle (a game state), we click on the Add button. To remove an existing game state, we click on any of the circles and click on the Remove button. The selected circle appears to be raised like the one on the far right-hand side of the screenshot. We may also modify an existing game state by moving the circles by clicking and dragging them to a different position—doing that on one client, we can observe the change in every other player's screen as well. The schema file For any Pulse-based game development, we first start out with an XML-formatted schema file. Let's now explore the schema file for the Hello World sample. The game developer must create a schema file that specifies all the needed game states, avatars, and game room objects. After you have created the schema file, we then use a Pulse modeler tool to create the class files based on the schema to be used within the game. So first let's examine the schema file for the Hello World project: <ObjectSchema> <import> <client import="pulse.gsrc.client.*" /> </import> <class name="HelloGameState" parent="GameState" classId="601" > <public> <property index="0" name="x" count="1" type="int"/> <property index="1" name="y" count="1" type="int"/> <property index="2" name="color" count="1" type="int"/> </public> </class></ObjectSchema> Navigate to the project folder where you have created the project and create a file called GameSchema.xml with the above content. We will not go through the details of the XML file in greater detail since it is out of the scope of this article. For the Hello World sample, we will define a game state object that we can use to share game states among all the players within a game room. We will name the class as HelloGameState, but you are welcome to call it by any name or something that makes sense to your game. You may also define as many game state classes as you like. For the HelloGameState in the schema file, each game state instance will define three properties, namely, x, y, and color. Code generator In order to create the AS3 class files from the schema file, you need to run the batch file called PulseCodeGen.bat found in the $bin folder. It takes the following three parameters: Path to schema file Namespace Output directory In order to make our life easier, let us create a batch file that will call the PulseCodeGen and pass all the required parameters. The reason for creating the batch file is that you have to code generate every time you modify the schema file. As you progress through your game implementation, it is normal to add a new class or modify an existing one. The convenience batch file may look like what's shown next. Let's call it .init.bat and save it in the same root folder for the sample along with the schema file. @ECHO OFFIF EXIST .srchwgsrcclient del .srchwgsrcclient*.asCALL "%GAMANTRA%"binPulseCodeGen.bat .GameSchema.xml hw.gsrc .srchwgsrcIF NOT %ERRORLEVEL% == 0 GOTO ERRORECHO Success!GOTO END:ERRORECHO oops!:ENDpause The schema file parameter to the Pulse code generator is specified as .GameSchema.xml because the schema file and the batch file are in the same folder. The second parameter is the package name for the generated classes—in this example, it is specified to be hw.gsrc. You specify the directory that the generated classes will be saved to as the last parameter. Note that the code generator appends client to both the package and directory into which it will be saved. It is also important to match the package name and directory structure as required by the AS3 compiler. Upon running the code gen successfully, there is one AS3 class generated for each class in the schema file and two additional supporting class files. One is a factory class called GNetClientObjectFactory, which is responsible for creating new instances of generated classes, and the other is GNetMetaDataMgr, which aids in serializing and de-serializing the transmitting data over the network. The data carried is what resides in the instances of generated classes. You don't need to deal with these two extra classes first hand; it is mostly used by the underlying Pulse runtime system. As for the generated classes for what is defined in the schema file, the name of the class would be identical to what is specified in the schema file plus the suffix Client. In this example, there would be a class generated with the name HelloGameStateClient.as. Go ahead and try running the batch file called init.bat under $samplesHelloWorld. Project directory structure The Hello World that is part of the Pulse package is organized into the following directory structure: hw gsrc client rsrc ui The package hw being the root package contains the main class HelloWorld.as, and the gsrc as you see contains the generated class. The rsrc folder contains the skin files, which we will discuss in more detail later in this article. The skin files in Pulse consist of three PNG files that provide all the basic buttons and background for the game. You can simply replace these PNG files with your own set, provided the individual elements with the file are of the exact dimensions and are placed at the exact same positions.
Read more
  • 0
  • 1
  • 4777

article-image-comparing-asterisk-and-openser
Packt
21 Oct 2009
4 min read
Save for later

Comparing Asterisk and OpenSER

Packt
21 Oct 2009
4 min read
Introduction If you work with IP telephony, it's quite possible that you have not heard about OpenSER, but certainly you must have heard about Asterisk. Well, I love a polemic headline and I have seen this question asked in the forums many times.  So, I will dare to compare these two very popular softwares dedicated to the VoIP market.  The idea here is not to show you which one is the best, but mainly how they are different from each other. Below is a comparison topic by topic. Architecture Asterisk is a Back to Back User Agent (B2BUA), while OpenSER is a Session Initiation Protocol (SIP) Proxy.  This makes all the difference between them. The SIP proxy architecture is faster than a B2BUA because it deals only with signaling. On the other hand, the B2BUA architecture, even being slower, handles the media and it is capable of several services not available in a SIP proxy such as Codec Translation (that is G729<->G.711), Protocol Translation (SIP<->H323), and services related to media such as IVR, Queuing, Text to Speech, and Voice Recognition. Nat Traversal OpenSER deals a lot better with NAT traversal then Asterisk. You can send the media from your customer directly to the provider using OpenSER in most cases (non-symmetric NAT). Manipulating directly the SIP protocol allows you to handle special cases, such as, when you have two customers behind the same NAT device and want to send the media directly between them. Load Balancing OpenSER has specific load balancing algorithms with hash. So it can load balance by the "ruri", "username", "call-id", and some other properties. It can use redirected messages consuming very few resources from the load balancer machine. Failover is part of the solution, things you won't find on Asterisk, but are complementary. Low Level Access to SIP Header and Transactions OpenSER gives you low level access to the protocol. You can handle all the requests and responses. So it is possible, most times, to translate between two incompatible versions of SIP, handling directly the SIP headers, requests, and responses. This is an important feature when you have SIP implementations from different manufacturers, which can be incompatible between each other. Integration with Radius, Diameter, and LDAP OpenSER has built-in integration with LDAP, Radius, and Diameter. While this is also possible with Asterisk, the implementation on OpenSER is developed in C, integrated as a module, and is part of the OpenSER distribution (no perl, no python, no third-party modules). Carrier Class Routing The module CARRIERROUTE implements sophisticated algorithms to route calls to the PSTN. Some times VoIP providers have tables with more then 40.000 routes. In this case, you will absolutely need a specific routing module capable of failback, blacklists, and some other features specific to VoIP providers. Media Services OpenSER is a SIP Proxy and is not capable of any media related services. So it is not possible to create, using OpenSER, systems such as VoiceMail, IVR, TTS, and Voice Recognition. However, it is possible to integrate any of these services to the platform using a separate Media Server such as Asterisk, Yate, and FreeSwitch.  This is by design, and it is the way the SIP protocol is defined in the standards (RFC3261). Connectivity to the PSTN OpenSER always need a SIP gateway to connect to the PSTN. There is no possibility to install telephony cards in the server.  In several cases, Asterisk is used as the PSTN gateway for OpenSER. Conclusion I love this discussion, because Asterisk and OpenSER completes one another. OpenSER provides rock solid SIP services to VoIP providers, it is capable to handle large volumes of calls, to load balance SIP, to solve advanced NAT scenarios, and to deal with SIP signaling as no other. Asterisk is a B2BUA, very strong in the PBX market. It is simpler to configure and can handle low to medium volumes. Asterisk can be used as a "single box does it all", while OpenSER requires all the architectural components of SIP to work. OpenSER is a "hit" in the VoIP provider market and in Universities. Asterisk PBX is a success in the IP PBX market, and it is getting a piece of the small to medium VoIP providers. Usually you start using OpenSER when you have some special need, such as load balancing or when you have large volumes such as more than a thousand registered users. Choose wisely!   If you have read this article you may be interested to view : Using Asterisk as a PSTN Gateway for OpenSER Building the User Portal with SerMyAdmin for OpenSER
Read more
  • 0
  • 0
  • 4773

article-image-microsoft-office-outlook-programming-using-vsto-30-and-c-part-2
Packt
12 Oct 2009
4 min read
Save for later

Microsoft Office Outlook Programming Using VSTO 3.0 and C#: Part 2

Packt
12 Oct 2009
4 min read
Working with Appointments Before we start working with the Appointments feature in Microsoft Office Outlook 2007, let's take a look at the Microsoft Office Outlook calendar. This will help you understand the concepts of Appointments more easily, and also explain how you can utilize this functionality for your needs. The Microsoft Outlook 2007 calendar is the scheduling component of the Outlook mail management system. It is well-integrated with other Microsoft Outlook functionality such as email, contacts, appointments, and other items in. Appointments are the actions you're scheduling in your Outlook calendar, inviting other people to participate if required. You can set the status of your availability for an appointment, and you can also schedule recurring appointments. Let's create an Outlook Appointment dynamically by using VSTO objects and C# programming: Open Visual Studio 2008, to create a new Outlook 2007 Add-in template project. Select New Project. Under Office select 2007 and select Outlook 2007 Add-in template and name the project as per your requirement. The solution will be created with all of supporting files required for the development of our Outlook solution. Write the following code, which will dynamically create an Appointment item in the ThisAddIn.cs file: private void ThisAddIn_Startup(object sender, System.EventArgs e){// Outlook AppointmentItem object to compose new AppointmentOutlook.AppointmentItem PacktAppointmentItem = (Outlook.AppointmentItem)this.Application.CreateItem(Outlook.OlItemType.olAppointmentItem);// Set the subject property valuePacktAppointmentItem.Subject = "Regarding book review";// Set the location property valuePacktAppointmentItem.Location = "Meeting Hall";// Set the start datePacktAppointmentItem.Start = DateTime.Today;// Set the end datePac ktAppointmentItem.End = DateTime.Today;// Set the body property valuePacktAppointmentItem.Body = "Book review comments fromall editors";// Set the required attendee informationPacktAppointmentItem.RequiredAttendees = "vivek@vsto.com";// Set the optional attandee informationPacktAppointmentItem.OptionalAttendees = "radhika@vsto.com";// If parameter is set to false compose Appointment won't displayPacktAppointmentItem.Display(true);// To send the composed PacktAppointmentItem//((Outlook._AppointmentItem)PacktAppointmentItem).Send();} The following screenshot shows the results of adding and executing this code: The AppointmentItem object is used to create appointments dynamically. An AppointmentItem object can be used to create a meeting, a one-time appointment, or a recurring appointment. Let's perform a demonstration of how to delete a recurring appointment from your Outlook 2007 calendar, by using VSTO programming. Open Visual Studio 2008 and create a new solution, as described earlier. Write the following code, which will dynamically delete an Appointment item, inside the ThisAddIn.cs file: private void ThisAddIn_Startup(object sender, System.EventArgs e){// Reading the calendar folder through MEPIFolder objectOutlook.MAPIFolder PacktCalendarInfo = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);// Get the data items in the calendar folderOutlook.Items PacktCalendarDataItems = PacktCalendarInfo.Items;// Searching the Appointment items based on subjectOutlook.AppointmentItem PacktAppointmentItem =PacktCalendarDataItems["Book release"] as Outlook.AppointmentItem;// Selected appointment's recurrence informationOutlook.RecurrencePattern PacktRecPattern = PacktAppointmentItem.GetRecurrencePattern();// Loading the appointment to AppointmentItem ObjectOutlook.AppointmentItem PacktAppointmentDelete = PacktRecPattern.GetOccurrence(new DateTime(2008, 9, 28, 8, 0, 0));// Now delete using the Delete methodPacktAppointmentDelete.Delete();} Working with meetings Meetings are generally discussions amongst more than two people, during which predetermined topics are discussed. Meetings help you prepare a plan, or finalize pending work, or perform other tasks involving colleagues. In Microsoft Office Outlook, a meeting is a scheduled appointment—that is, people are invited to attend. You can set the meeting time and other options for the meeting attendees, to process the invitation. VSTO 3.0 supports the dynamic creation of meeting items for Office. Let's create a meeting invitation dynamically, by using the VSTO object model and C# programming. Open Visual Studio 2008 and create a new solution, as explained earlier. Write the following code, which will dynamically create a meeting invite item, inside the ThisAddIn.cs file: private void ThisAddIn_Startup(object sender, System.EventArgs e){// Outlook PacktMeetingItem object to compose new meeting requestOutlook.AppointmentItem PacktMeetingItem = (Outlook.AppointmentItem)this.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem);PacktMeetingItem.MeetingStatus = Microsoft.Office.Interop.Outlook.OlMeetingStatus.olMeeting;// Set the subject for the meetingPacktMeetingItem.Subject = "Changes in book content";// Update the body information of the meetingPacktMeetingItem.Body = "Work on the changes and update";// Start Expiry Time of the meetingPacktMeetingItem.Start = new DateTime(2008, 9, 28, 9, 0, 0);// Set the recipient informationOutlook.Recipient PacktRecipient = PacktMeetingItem.Recipients.Add("Radhika Rajagopalan");PacktRecipient.Type = (int)Outlook.OlMeetingRecipientType.olRequired;// If parameter is set to false compose MeetingItem won't displayPacktMeetingItem.Display(true);// To send the composed PacktMeetingItem//((Outlook.MeetingItem)PacktMeetingItem).Send();} As we can see in the following screenshot, a Meeting tab is created successfully after executing this program. An Outlook meeting is one of the many types of Appointments in Outlook. Meetings are internally linked with the Outlook calendar. A meeting request can be created using only the AppointmentItem object. To create and set the meeting invitation by using the AppointmentItem, you must set the MeetingStatus property to olMeeting.
Read more
  • 0
  • 0
  • 4772

article-image-restful-services-jax-rs-20
Packt
26 Sep 2013
16 min read
Save for later

RESTful Services JAX-RS 2.0

Packt
26 Sep 2013
16 min read
Representational State Transfer Representational State Transfer (REST) is a style of information application architecture that aligns the distributed applications to the HTTP request and response protocols, in particular matching Hypermedia to the HTTP request methods and Uniform Resource Identifiers (URI). Hypermedia is the term that describes the ability of a system to deliver self-referential content, where related contextual links point to downloadable or stream-able digital media, such as photographs, movies, documents, and other data. Modern systems, especially web applications, demonstrate through display of text that a certain fragment of text is a link to the media. Hypermedia is the logical extension of the term hypertext, which is a text that contains embedded references to other text. These embedded references are called links, and they immediately transfer the user to the other text when they are invoked. Hypermedia is a property of media, including hypertext, to immediately link other media and text. In HTML, the anchor tag <a> accepts a href attribute, the so-called hyperlink parameter. The World Wide Web is built on the HTTP standards, Versions 1.0 and 1.1, which define specific enumerations to retrieve data from a web resource. These operations, sometimes called Web Methods, are GET, POST, PUT, and DELETE. Representational State Transfer also reuses these operations to form semantic interface to a URI. Representational State Transfer, then, is both a style and architecture for building network enabled distributed applications. It is governed by the following constraints: Client/Server: A REST application encourages the architectural robust principle of separation of concerns by dividing the solution into clients and servers. A standalone, therefore, cannot be a RESTful application. This constraint ensures the distributed nature of RESTful applications over the network. Stateless: A REST application exhibits stateless communication. Clients cannot and should not take advantage of any stored context information in the server and therefore the full data of each request must be sent to the server for processing. Cache: A REST application is able to declare which data is cacheable or not cacheable. This constraint allows the architect to set the performance level for the solution, in other words, a trade-off. Caching data to the web resource, allows the business to achieve a sense of latency, scalability, and availability. The counter point to improved performance through caching data is the issue of expiration of the cache at the correct time and sequence, when do we delete stale data? The cache constraint also permits successful implementation providers to develop optimal frameworks and servers. Uniform Interface: A REST application emphasizes and maintains a unique identifier for each component and there are a set of protocols for accessing data. The constraint allows general interaction to any REST component and therefore anyone or anything can manipulate a REST component to access data. The drawback is the Uniform Interface may be suboptimal in ease-of-use and cognitive load to directly provide a data structure and remote procedure function call. Layered Style: A REST application can be composed of functional processing layers in order to simplify complex flows of data between clients and servers. Layered style constraint permits modularization of function with the data and in itself is another sufficient example of separation of concerns. The layered style is an approach that benefits load-balancing servers, caching content, and scalability. Code-on-Demand: A REST application can optimally supply downloadable code on demand for the client to execute. The code could be the byte-codes from the JVM, such as a Java Applet, or JavaFX WebStart application, or it could be a JavaScript code with say JSON data. Downloadable code is definitely a clear security risk that means that the solution architect must assume responsibility of sandboxing Java classes, profiling data, and applying certificate signing in all instances. Therefore, code-on-demand, is a disadvantage in a public domain service, and this constraint in REST application is only seen inside the firewalls of corporations. In terms of the Java platform, the Java EE standard covers REST applications through the specification JAX-RS and this article covers Version 2.0. JAX-RS 2.0 features For Java EE 7, the JAX-RS 2.0 specification has the following new features: Client-side API for invoking RESTful server-side remote endpoint Support for Hypermedia linkage Tighter integration with the Bean Validation framework Asynchronous API for both server and client-side invocations Container filters on the server side for processing incoming requests and outbound responses Client filter on the client side for processing outgoing request and incoming responses Reader and writer interceptors to handle specific content types Architectural style The REST style is simply a Uniform Resource Identifier and the application of the HTTP request methods, which invokes resources that generate a HTTP response. Although Fielding, himself, says that REST does not necessarily require the HTTP communication as a networker layer, and the style of architecture can be built on any other network protocol. Let's look at those methods again with a fictional URL (http://fizzbuzz.com/) Method Description POST A REST style application creates or inserts an entity with the supplied data. The client can assume new data has been inserted into the underlying backend database and the server returns a new URI to reference the data. PUT A REST style application replaces the entity into the database with the supplied data. GET A REST style application retrieves the entity associated with the URI, and it can be a collection of URI representing entities or it can be the actual properties of the entity DELETE A REST style application deletes the entity associated with the URI from the backend database. The user should note that PUT and DELETE are idempotent operations, meaning they can be repeated endlessly and the result is the same in steady state conditions. The GET operation is a safe operation; it has no side effects to the server-side data. REST style for collections of entities Let's take a real example with the URL http://fizzbuzz.com/resources/, which represents the URI of a collection of resources. Resources could be anything, such as books, products, or cast iron widgets. Method Description GET Retrieves the collection entities by URI under the link http://fizzbuzz.com/resources and they may include other more data. POST Creates a new entity in the collection under the URI http://fizzbuzz.com/resources. The URI is automatically assigned and returned by this service call, which could be something like http://fizzbuzz.com/resources/WKT54321. PUT Replaces the entire collection of entities under the URI http://fizzbuzz.com/resources. DELETE Deletes the entire collection of entities under the URI http://fizzbuzz.com/resources. As a reminder, a URI is a series of characters that identifies a particular resource on the World Wide Web. A URI, then, allows different clients to uniquely identify a resource on the web, or a representation. A URI is combination of a Uniform Resource Name (URN) and a Uniform Resource Locator (URL). You can think of a URN like a person's name, as way of naming an individual and a URL is similar to a person's home address, which is the way to go and visit them sometime. In the modern world, non-technical people are accustomed to desktop web browsing as URL. However, the web URL is a special case of a generalized URI. A diagram that illustrates HTML5 RESTful communication between a JAX RS 2.0 client and server, is as follows: REST style for single entities Assuming we have a URI reference to a single entity like http://fizzbuzz.com/resources/WKT54321. Method Description GET Retrieves the entity with reference to URI under the link http://fizzbuzz.com/resources/WKT54321. POST Creates a new sub entity under the URI http://fizzbuzz.com/resources/WKT54321. There is a subtle difference here, as this call does something else. It is not often used, except to create Master-Detail records. The URI of the subentity is automatically assigned and returned by this service call, which could be something like http://fizzbuzz.com/resources/WKT54321/D1023 PUT Replaces the referenced entity's entire collection with the URI http://fizzbuzz.com/resources/WKT54321 . If the entity does not exist then the service creates it. DELETE Deletes the entity under the URI references http://fizzbuzz.com/resources/WKT54321 Now that we understand the REST style we can move on to the JAX-RS API properly. Consider carefully your REST hierarchy of resources The key to build a REST application is to target the users of the application instead of blindly converting the business domain into an exposed middleware. Does the user need the whole detail of every object and responsibility in the application? On the other hand is the design not spreading enough information for the intended audience to do their work? Servlet mapping In order to enable JAX-RS in a Java EE application the developer must set up the configuration in the web deployment descriptor file. JAX-RS requires a specific servlet mapping to be enabled, which triggers the provider to search for annotated classes. The standard API for JAX-RS lies in the Java package javax.ws.rs and in its subpackages. Interestingly, the Java API for REST style interfaces sits underneath the Java Web Services package javax.ws. For your web applications, you must configure a Java servlet with just fully qualified name of the class javax.ws.rs.core.Application. The Servlet must be mapped to a root URL pattern in order to intercept REST style requests. The following is an example code of such a configuration: <?xml version="1.0" encoding="UTF-8"?><web-app xsi:schemaLocation="http://metadata-complete="false"><display-name>JavaEE Handbook 7 JAX RS Basic</display-name><servlet><servlet-name>javax.ws.rs.core.Application</servlet-name><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>javax.ws.rs.core.Application</servlet-name><url-pattern>/rest/*</url-pattern></servlet-mapping></web-app> In the web deployment descriptor we just saw, only the servlet name is defined, javax.ws.rs.core.Application. Do not define the servlet class. The second step maps the URL pattern to the REST endpoint path. In this example, any URL that matches the simplified Glob pattern /rest/* is mapped. This is known as the application path. A JAX-RS application is normally packaged up as a WAR file and deployed to a Java EE application server or a servlet container that conforms to the Web Profile. The application classes are stored in the /WEB-INF/classes and required libraries are found under /WEB-INF/lib folder. Therefore, JAX-RS applications share the consistency of configurations as servlet applications. The JAX-RS specification does recommend, but does not enforce, that conformant providers follow the general principles of Servlet 3.0 plug-ability and discoverability of REST style endpoints. Discoverability is achieved in the recommendation through class scanning of the WAR file, and it is up to the provider to make this feature available. An application can create a subclass of the javax.ws.rs.core.Application class. The Application class is a concrete class and looks like the following code: public class Application {public Application() { /* ... */ }public java.util.Set<Class<?>> getClasses() {/* ... */ }public java.util.Set<Object> getSingletons() {/* ... */ }public java.util.Map<String,Object> getProperties() {/* ... */ }} Implementing a custom Application subclass is a special case of providing maximum control of RESTful services for your business application. The developer must provide a set collection of classes that represent JAX-RS end points. The engineer must supply a list of Singleton object, if any, and do something useful with the properties. The default implementation of javax.ws.rs.core.Application and the methods getClasses() and getSingletons() return empty sets. The getProperties() method returns an empty map collection. By returning empty sets, the provider assumes that all relevant JAX-RS resource and provider classes that are scanned and found will be added to the JAX-RS application. Majority of the time, I suspect, you, the developer will want to rely on annotations to specify the REST end points and there are Servlet Context listeners and Servlet Filters to configure application wide behavior, for example the startup sequence of a web application. So how can we register our own custom Application subclass? The answer is just subclass the core class with your own class. The following code explains what we just read: package com.fizbuzz.services;@javax.ws.rs.ApplicationPath("rest")public class GreatApp extends javax.ws.rs.core.Application {// Do your custom thing here} In the custom GreatApp class, you can now configure logic for initialization. Note the use of @ApplicationPath annotation to configure the REST style URL. You still have to associate your custom Application subclass into the web deployment descriptor with a XML Servlet name definition. Remember the Application Configuration A very common error for first time JAX-RS developers is to forget that the web deployment descriptor really requires a servlet mapping to a javax.ws.js.core.Application type. Now that we know how to initialize a JAX-RS application, let us dig deeper and look at the defining REST style endpoints. Mapping JAX-RS resources JAX-RS resources are configured through the resource path, which suffixes the application path. Here is the constitution of the URL. http://<hostname>:<port>/<web_context>/<application_path>/<resource_path> The <hostname> is the host name of the server. The <port> refers to the port number, which is optional and the default port is 80. The <web_context> is the Servlet context, which is the context for the deployed web application. The <application_path> is the configuration URI pattern as specified in the web deployment descriptor @ApplicationPath or the Servlet configuration of Application type. The <resource_path> is the resource path to REST style resource. The final fragment <resource_path> defines the URL pattern that maps a REST style resource. The resource path is configured by annotation javax.ws.rs.Path. Test-Driven Development with JAX-RS Let us write a unit test to verify the simplest JAX-RS service. It follows a REST style resource around a list of books. There are only four books in this endpoint and the only thing the user/client can do at the start is to access the list of books by author and title. The client invokes the REST style endpoint, otherwise known as a resource with an HTTP GET request. The following is the code for the class RestfulBookService: package je7hb.jaxrs.basic;import javax.annotation.*;import javax.ws.rs.*;import java.util.*;@Path("/books")public class RestfulBookService {private List<Book> products = Arrays.asList(new Book("Sir Arthur Dolan Coyle","Sherlock Holmes and the Hounds of the Baskervilles"),new Book("Dan Brown", "Da Vinci Code"),new Book("Charles Dickens", "Great Expectations"),new Book("Robert Louis Stevenson", "Treasure Island"));@GET@Produces("text/plain")public String getList() {StringBuffer buf = new StringBuffer();for (Book b: products) {buf.append(b.title); buf.append('n'); }return buf.toString();}@PostConstructpublic void acquireResource() { /* ... */ }@PreDestroypublic void releaseResource() { /* ... */ }static class Book {public final String author;public final String title;Book(String author, String title) {this.author = author;this.title = title;}}} The annotation @javax.ws.rs.Path declares the class as a REST style end-point for a resource. The @Path annotation is assigned to the class itself. The path argument defines the relative URL pattern for this resource, namely/books. The method getList() is the interesting one. It is annotated with both @javax.ws.rs.GET and @javax.ws.rs.Produces. The @GET is one of the six annotations that conform to the HTTP web request methods. It indicates that the method is associated with HTTP GET protocol request. The @Produces annotation indicates the MIME content that this resource will generate. In this example, the MIME content is text/plain. The other methods on the resource bring CDI into the picture. In the example, we are injecting post construction and pre destruction methods into the bean. This is the only class that we require for a simple REST style application from the server side. With an invoking of the web resource with a HTTP GET Request like http://localhost:8080/mywebapp/rest/books we should get a plain text output with list of titles like the following: Sherlock Holmes and the Hounds of the BaskervillesDa Vinci CodeGreat ExpectationsTreasure Island So do we test this REST style interface then? We could use Arquillian Framework directly, but this means our tests have to be built specifically in a project and it complicates the build process. Arquillian uses another open source project in the JBoss repository called ShrinkWrap. The framework allows the construction of various types of virtual Java archives in a programmatic fashion. Let's look at the unit test class RestfulBookServiceTest in the following code: package je7hb.jaxrs.basic;// import omittedpublic class RestfulBookServiceTest {@Testpublic void shouldAssembleAndRetrieveBookList()throws Exception {WebArchive webArchive =ShrinkWrap.create(WebArchive.class, "test.war").addClasses(RestfulBookService.class).setWebXML(new File("src/main/webapp/WEB-INF/web.xml")).addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");File warFile = new File(webArchive.getName());new ZipExporterImpl(webArchive).exportTo(warFile, true);SimpleEmbeddedRunner runner =SimpleEmbeddedRunner.launchDeployWarFile(warFile, "mywebapp", 8080);try {URL url = new URL("http://localhost:8080/mywebapp/rest/books");InputStream inputStream = url.openStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));List<String> lines = new ArrayList<>();String text = null;int count=0;while ( ( text = reader.readLine()) != null ) {lines.add(text);++count;System.out.printf("**** OUTPUT ****text[%d] = %sn", count, text );}assertFalse( lines.isEmpty() );assertEquals("Sherlock Holmes and the Houndsof the Baskervilles", lines.get(0));assertEquals("Da Vinci Code", lines.get(1));assertEquals("Great Expectations", lines.get(2));assertEquals( "Treasure Island", lines.get(3) );}finally {runner.stop();}}} In the unit test method, shouldAssembleAndRetrieveBookList(), we first assemble a virtual web archive with an explicit name test.war. The WAR file contains the RestfulBookService services, the Web deployment descriptor file web.xml and an empty beans.xml file, which if you remember is only there to trigger the CDI container into life for this web application. With the virtual web archive, we export the WAR as a physical file with the utility ZipExporterImpl class from ShinkWrap library, which creates the file test.war in the project root folder. Next, we fire up the SimpleEmbeddedRunner utility. It deploys the web archive to an embedded GlassFish container. Essentially, this is the boilerplate to get to deliver a test result. We, then, get to the heart of the test itself; we construct a URL to invoke the REST style endpoint, which is http://localhost:8080/mywebapp/rest/books. We read the output from the service endpoint with Java standard I/O line by line into a list collection of Strings. Once we have a list of collections, then we assert each line against the expected output from the rest style service. Because we acquired an expensive resource, like an embedded Glassfish container, we are careful to release it, which is the reason, why we surround critical code with a try-finally block statement. When the execution comes to end of test method, we ensure the embedded GlassFish container is shut down.
Read more
  • 0
  • 0
  • 4771

article-image-simple-alphabetical-glossary-using-jquery
Packt
05 Oct 2009
8 min read
Save for later

Simple Alphabetical Glossary Using jQuery

Packt
05 Oct 2009
8 min read
Adding jQuery to your page As we have discussed above you can download the latest version of jQuery from jQuery site (http://jquery.com/) and can be added as a reference to your web pages accordingly. You can reference a local copy of jQuery using <script> tag in the page. Either you can reference your local copy or you can directly reference remote copy from jQuery.com or Google Ajax API (http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js) Prerequisite Knowledge In order to understand the code, one should have the basic knowledge of HTML, CSS, JavaScript and basic knowledge of jQuery. Ingredients Used HTML CSS jQuery Photoshop (Used for Designing the Button Background) Preview/Download If you would like to see the working example, click the following link: http://www.developersnippets.com/snippets/jquery/alphabetical_glossary/alphabetical_glossary.html. And if you would like to download the snippet, click the following link: http://www.developersnippets.com/snippets/jquery/alphabetical_glossary.zip. Figure 1: Snapshot of "Simple Alphabetical Glossary using jQuery" Figure 2: Overview of div’s and Listings used Figure 3: Image used for Listings (CSS Sprite) Successfully tested The above application is successfully tested on various browsers like IE 6.0, IE 7, IE 8, Mozilla Firefox (Latest Version), Google Chrome and Safari Browser (4.0.2) respectively. HTML Code Below is the HTML code with comments for you to better understand. <div id="body-container"> <div class="glossary-container"> <ul class="firstUL"> <li id="a" class="selected">A</li> <li id="b">B</li> <li id="c">C</li> <li id="d">D</li> <li id="e">E</li> <li id="f">F</li> <li id="g">G</li> <li id="h">H</li> </ul> </div> <!-- Close of glossary-container --> <div class="content-container"> <!-- A --> <div id="content-for-a" style="background-color:#d2e2fc"> <!-- Content for A --> </div> <!-- B --> <div id="content-for-b"> <!-- Content for B --> </div> <!-- C --> <div id="content-for-c"> <!-- Content for C --> </div> <!-- D --> <div id="content-for-d"> <!-- Content for D --> </div> </div> <!-- Close of content-container --></div> <!-- Close of body-container --> Explanation of HTML Code To get the UI shown in above screenshot, I have written some HTML div tags to hold the Glossary terms in one container and the results in another container. CSS styles are used to assign some nice colors. <div id="body-container">.....</div> I have used "body-container" as the main container to catch hold of other two div containers. <div class="glossary-container">.....</div> "glossary-container" contains a glossary term that is Alphabets, as of now in this example I have used alphabets only from "A" to "H". <div class="content-container">.....</div> In "content-container" I have arranged all the results or definitions of glossary terms, for each and every glossary term I have used separate <div> tags like for Alphabet "A" --- <div id="content-for-a" style="background-color:#d2e2fc">....</div>, and given default background color as "background-color:#d2e2fc" which highlights the definition accordingly. After going through the HTML code, we will have a glance on CSS styling. This is very important to give a good look and feel to the application. Explanation of CSS Code <style>/* Making margin and padding to 0, since by default the body will be allocated some amount of pixels of margin and padding. */body{ margin:0; padding:0;}#body-container{ width:415px; /* Given a constant width of 415px to body-container div */ height:500px; /* Given a constant height of 500px to the div */ margin:0 auto; /* This will align the div to center */ border:1px solid #3285ef; /* Giving the border */}#body-container .glossary-container{ clear:both; /* This will not allow floating elements on either sides */}#body-container .content-container{ height:430px; /* Given a constant height of 430px to the div */ width:415px; /* Given a constant width of 415px to the div */ overflow:auto; /* Scroll bar is shown when content is more than specified height */ font-family:'Arial',Verdana,Tahoma; /* Taken the default font to 'Arial' */ font-size:10pt; /* Making font size to 10 points */ clear:both; /* This will not allow floating elements on either sides */}#body-container .content-container div{ padding-left:10px; /* Left padding given as 10px */ border-bottom:1px #666666 solid; /* In order to separate each terms given bottom border color as #666666 (gray) with 1px */}#body-container .content-container div h2{ margin-top:0px; /* Making the top margin to 0px */}#body-container .content-container p.return-to-top{ color:#0066FF; /* Giving text color to Return to top text */ text-decoration:underline; /* The text will be underlined */ text-align:right; /* Text will be aligned to right */ margin-right:10px; /* Given some margin 10px to right */ cursor:pointer; /* Making the cursor to 'hand' */}.firstUL{ padding:0px 0px 0px 10px; /* Given some padding to left and 0 padding to top, right, bottom */ margin:0px; /* margin to 0px */ background-color:#3285ef; /* Given background color */}.firstUL li { background:transparent url(images/link_sprite_img.jpg) no-repeat scroll 0 0; /* For all li’s(listings) given default background image using CSS Sprite concept */ display:inline; /* Listings will be placed in a line */ font-family:'Arial',Verdana,Tahoma; /* Setting the font to 'Arial' */ font-size:16pt; /* Setting the font size to 16 points */ font-weight:bold; /* Making the text to bold */ padding:10px 15px 22px; /* Given some padding to top, right, bottom and left */ line-height:70px; /* This property specifies the line height */ cursor:pointer; /* Making the cursor to 'hand' */}.firstUL li.selected{ background:transparent url(images/link_sprite_img.jpg) no-repeat scroll 0px -57px; /* When any listing is highlighted, we are given the background to image using CSS Sprite concept */ color:#ffffff; /* Making the font color 'white' */ font-weight:bold; /* Making text bold */}</style> Explanation of jQuery Code In order to work your jQuery code, as mentioned above in "Adding jQuery to your page" section, we need to include jQuery JavaScript file onto your web page using <script> tag. <!-- jQuery --><script language="javascript" type="text/javascript" src="js/jquery.js"></script> I have downloaded the jQuery file from jQuery site and kept it on my local machine. To see the scrolling effect, you need to include the following plugin: <!-- scrollTo Plugin --><script language="javascript" type="text/javascript" src="js/jquery.scrollTo-min.js"></script> You can get the above plugin at this location—http://plugins.jquery.com/project/ScrollTo The above two .js files should be in included in <head> tag in order to utilize those in our code. jQuery Code <script language="javascript" type="text/javascript">$(document).ready(function() { //below code is for high-lighting the link and scroll to particular DOM Element as well $(".firstUL li").each(function() { $(this).click(function() { //On click of any Alphabet $(".firstUL li").removeClass("selected"); //Initially remove "selected" class if any $(this).addClass("selected"); //Add "selected" class for the clicked one elementClick = $(this).attr("id"); //get respective 'Id' for example 'a','b','c'.. etc., $(".content-container").scrollTo($("#content-for-"+elementClick), 800); //scrollTo particular DOM Element $(".content-container div").css({'background-color' : '#ffffff'}); //set the background color to default, that is white $(".content-container #content-for-"+elementClick).css({'background-color' : '#d2e2fc'}); //set the background color to light-blue to that div }); }); //When "Return to Top" is clicked highlight the first Alphabet that 'A' and scroll to top. $('.return-to-top').click(function(){ $(".firstUL li").each(function() { $(".firstUL li").removeClass("selected"); //Remove classname "selected" }); $("#a").addClass("selected"); //Add a class named "selected" to the first Alphabet $(".content-container").scrollTo($("#content-for-a"), 800); //This is for scrolling to particular element that is "A" here... $(".content-container div").css({'background-color' : '#ffffff'}); //set the background color to default, that is white $(".content-container #content-for-a").css({'background-color' : '#d2e2fc'}); //set the background color to light-blue to that div });});</script> Summary In this article, we saw how to create a Simple Alphabetical Glossary using jQuery. We have learnt how we can highlight particular DOM Element, how we can scroll-to particular div element using scroll-to plugin, and learnt how we can add the background-color to a div using CSS properties.
Read more
  • 0
  • 0
  • 4770

article-image-aspnet-social-networks-making-friends-part-2
Packt
22 Oct 2009
18 min read
Save for later

ASP.NET Social Networks—Making Friends (Part 2)

Packt
22 Oct 2009
18 min read
Implementing the presentation layer Now that we have the base framework in place, we can start to discuss what it will take to put it all together. Searching for friends Let's see what it takes to implement a search for friends. SiteMaster Let's begin with searching for friends. We haven't covered too much regarding the actual UI and nothing regarding the master page of this site. Putting in simple words, we have added a text box and a button to the master page to take in a search phrase. When the button is clicked, this method in the MasterPage code behind is fired. protected void ibSearch_Click(object sender, EventArgs e){ _redirector.GoToSearch(txtSearch.Text);} As you can see it simply calls the Redirector class and routes the user to the Search.aspx page passing in the value of txtSearch (as a query string parameter in this case). public void GoToSearch(string SearchText){ Redirect("~/Search.aspx?s=" + SearchText); } Search The Search.aspx page has no interface. It expects a value to be passed in from the previously discussed text box in the master page. With this text phrase we hit our AccountRepository and perform a search using the Contains() operator. The returned list of Accounts is then displayed on the page. For the most part, this page is all about MVP (Model View Presenter) plumbing. Here is the repeater that displays all our data. <%@ Register Src="~/UserControls/ProfileDisplay.ascx" TagPrefix="Fisharoo" TagName="ProfileDisplay" %>...<asp:Repeater ID="repAccounts" runat="server" OnItemDataBound="repAccounts_ItemDataBound"> <ItemTemplate> <Fisharoo:ProfileDisplay ShowDeleteButton="false" ID="pdProfileDisplay" runat="server"> </Fisharoo:ProfileDisplay> </ItemTemplate></asp:Repeater> The fun stuff in this case comes in the form of the ProfileDisplay user control that was created so that we have an easy way to display profile data in various places with one chunk of reusable code that will allow us to make global changes. A user control is like a small self-contained page that you can then insert into your page (or master page). It has its own UI and it has its own code behind (so make sure it also gets its own MVP plumbing!). Also, like a page, it is at the end of the day a simple object, which means that it can have properties, methods, and everything else that you might think to use. Once you have defined a user control you can use it in a few ways. You can programmatically load it using the LoadControl() method and then use it like you would use any other object in a page environment. Or like we did here, you can add a page declaration that registers the control for use in that page. You will notice that we specified where the source for this control lives. Then we gave it a tag prefix and a tag name (similar to using asp:Control). From that point onwards we can refer to our control in the same way that we can declare a TextBox! You should see that we have <Fisharoo:ProfileDisplay ... />. You will also notice that our tag has custom properties that are set in the tag definition. In this case you see ShowDeleteButton="false". Here is the user control code in order of display, code behind, and the presenter: //UserControls/ProfileDisplay.ascx<%@ Import namespace="Fisharoo.FisharooCore.Core.Domain"%><%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ProfileDisplay.ascx.cs" Inherits="Fisharoo.FisharooWeb.UserControls.ProfileDisplay" %><div style="float:left;"> <div style="height:130px;float:left;"> <a href="/Profiles/Profile.aspx?AccountID=<asp:Literal id='litAccountID' runat='server'></asp:Literal>"> <asp:Image style="padding:5px;width:100px;height:100px;" ImageAlign="Left" Width="100" Height="100" ID="imgAvatar" ImageUrl="~/images/ProfileAvatar/ProfileImage.aspx" runat="server" /></a> <asp:ImageButton ImageAlign="AbsMiddle" ID="ibInviteFriend" runat="server" Text="Become Friends" OnClick="lbInviteFriend_Click" ImageUrl="~/images/icon_friends.gif"></asp:ImageButton> <asp:ImageButton ImageAlign="AbsMiddle" ID="ibDelete" runat="server" OnClick="ibDelete_Click" ImageUrl="~/images/icon_close.gif" /><br /> <asp:Label ID="lblUsername" runat="server"></asp:Label><br /> <asp:Label ID="lblFirstName" runat="server"></asp:Label> <asp:Label ID="lblLastName" runat="server"></asp:Label><br /> Since: <asp:Label ID="lblCreateDate" runat="server"></asp:Label><br /> <asp:Label ID="lblFriendID" runat="server" Visible="false"></asp:Label> </div> </div>//UserControls/ProfileDisplay.ascx.csusing System;using System.Collections;using System.Configuration;using System.Data;using System.Linq;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Linq;using Fisharoo.FisharooCore.Core.Domain;using Fisharoo.FisharooWeb.UserControls.Interfaces;using Fisharoo.FisharooWeb.UserControls.Presenters;namespace Fisharoo.FisharooWeb.UserControls{ public partial class ProfileDisplay : System.Web.UI.UserControl, IProfileDisplay { private ProfileDisplayPresenter _presenter; protected Account _account; protected void Page_Load(object sender, EventArgs e) { _presenter = new ProfileDisplayPresenter(); _presenter.Init(this); ibDelete.Attributes.Add("onclick","javascript:return confirm('Are you sure you want to delete this friend?')"); } public bool ShowDeleteButton { set { ibDelete.Visible = value; } } public bool ShowFriendRequestButton { set { ibInviteFriend.Visible = value; } } public void LoadDisplay(Account account) { _account = account; ibInviteFriend.Attributes.Add("FriendsID",_account.AccountID.ToString()); ibDelete.Attributes.Add("FriendsID", _account.AccountID.ToString()); litAccountID.Text = account.AccountID.ToString(); lblLastName.Text = account.LastName; lblFirstName.Text = account.FirstName; lblCreateDate.Text = account.CreateDate.ToString(); imgAvatar.ImageUrl += "?AccountID=" + account.AccountID.ToString(); lblUsername.Text = account.Username; lblFriendID.Text = account.AccountID.ToString(); } protected void lbInviteFriend_Click(object sender, EventArgs e) { _presenter = new ProfileDisplayPresenter(); _presenter.Init(this); _presenter.SendFriendRequest(Convert.ToInt32(lblFriendID.Text)); } protected void ibDelete_Click(object sender, EventArgs e) { _presenter = new ProfileDisplayPresenter(); _presenter.Init(this); _presenter.DeleteFriend(Convert.ToInt32(lblFriendID.Text)); } }}//UserControls/Presenter/ProfileDisplayPresenter.csusing System;using System.Data;using System.Configuration;using System.Linq;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Linq;using Fisharoo.FisharooCore.Core;using Fisharoo.FisharooCore.Core.DataAccess;using Fisharoo.FisharooWeb.UserControls.Interfaces;using StructureMap;namespace Fisharoo.FisharooWeb.UserControls.Presenters{ public class ProfileDisplayPresenter { private IProfileDisplay _view; private IRedirector _redirector; private IFriendRepository _friendRepository; private IUserSession _userSession; public ProfileDisplayPresenter() { _redirector = ObjectFactory.GetInstance<IRedirector>(); _friendRepository = ObjectFactory.GetInstance<IFriendRepository>(); _userSession = ObjectFactory.GetInstance<IUserSession>(); } public void Init(IProfileDisplay view) { _view = view; } public void SendFriendRequest(Int32 AccountIdToInvite) { _redirector.GoToFriendsInviteFriends(AccountIdToInvite); } public void DeleteFriend(Int32 FriendID) { if (_userSession.CurrentUser != null) { _friendRepository.DeleteFriendByID(_userSession.CurrentUser.AccountID , FriendID); HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Raw Url); } } }} All this logic and display is very standard. You have the MVP plumbing, which makes up most of it. Outside of that you will notice that the ProfileDisplay control has a LoadDisplay() method responsible for loading the UI for that control. In the Search page this is done in the repAccounts_ItemDataBound() method. protected void repAccounts_ItemDataBound(object sender, RepeaterItemEventArgs e){ if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { ProfileDisplay pd = e.Item.FindControl("pdProfileDisplay") as ProfileDisplay; pd.LoadDisplay((Account)e.Item.DataItem); if(_webContext.CurrentUser == null) pd.ShowFriendRequestButton = false; }} The ProfileDisplay control also has a couple of properties one to show/hide the delete friend button and the other to show/hide the invite friend button. These buttons are not appropriate for every page that the control is used in. In the search results page we want to hide the Delete button as the results are not necessarily friends. We would want to be able to invite them in that view. However, in a list of our friends the Invite button (to invite a friend) would no longer be appropriate as each of these users would already be a friend. The Delete button in this case would now be more appropriate. Clicking on the Invite button makes a call to the Redirector class and routes the user to the InviteFriends page. //UserControls/ProfileDisplay.ascx.cspublic void SendFriendRequest(Int32 AccountIdToInvite){ _redirector.GoToFriendsInviteFriends(AccountIdToInvite);}//Core/Impl/Redirector.cspublic void GoToFriendsInviteFriends(Int32 AccoundIdToInvite){ Redirect("~/Friends/InviteFriends.aspx?AccountIdToInvite=" + AccoundIdToInvite.ToString());} Inviting your friends This page allows us to manually enter email addresses of friends whom we want to invite. It is a standard From, To, Message format where the system specifies the sender (you), you specify who to send to and the message that you want to send. //Friends/InviteFriends.aspx<%@ Page Language="C#" MasterPageFile="~/SiteMaster.Master" AutoEventWireup="true" CodeBehind="InviteFriends.aspx.cs" Inherits="Fisharoo.FisharooWeb.Friends.InviteFriends" %><asp:Content ContentPlaceHolderID="Content" runat="server"> <div class="divContainer"> <div class="divContainerBox"> <div class="divContainerTitle">Invite Your Friends</div> <asp:Panel ID="pnlInvite" runat="server"> <div class="divContainerRow"> <div class="divContainerCellHeader">From:</div> <div class="divContainerCell"><asp:Label ID="lblFrom" runat="server"></asp:Label></div> </div> <div class="divContainerRow"> <div class="divContainerCellHeader">To:<br /><div class="divContainerHelpText">(use commas to<BR />separate emails)</div></div> <div class="divContainerCell"><asp:TextBox ID="txtTo" runat="server" TextMode="MultiLine" Columns="40" Rows="5"></asp:TextBox></div> </div> <div class="divContainerRow"> <div class="divContainerCellHeader">Message:</div> <div class="divContainerCell"><asp:TextBox ID="txtMessage" runat="server" TextMode="MultiLine" Columns="40" Rows="10"></asp:TextBox></div> </div> <div class="divContainerFooter"> <asp:Button ID="btnInvite" runat="server" Text="Invite" OnClick="btnInvite_Click" /> </div> </asp:Panel> <div class="divContainerRow"> <div class="divContainerCell"><br /><asp:Label ID="lblMessage" runat="server"> </asp:Label><br /><br /></div> </div> </div> </div></asp:Content> Running the code will display the following: This is a simple page, so the majority of the code for it is MVP plumbing. The most important part to notice here is that when the Invite button is clicked the presenter is notified to send the invitation. //Friends/InviteFriends.aspx.csusing System;using System.Collections;using System.Configuration;using System.Data;using System.Linq;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Linq;using Fisharoo.FisharooWeb.Friends.Interface;using Fisharoo.FisharooWeb.Friends.Presenter;namespace Fisharoo.FisharooWeb.Friends{ public partial class InviteFriends : System.Web.UI.Page, IInviteFriends { private InviteFriendsPresenter _presenter; protected void Page_Load(object sender, EventArgs e) { _presenter = new InviteFriendsPresenter(); _presenter.Init(this); } protected void btnInvite_Click(object sender, EventArgs e) { _presenter.SendInvitation(txtTo.Text,txtMessage.Text); } public void DisplayToData(string To) { lblFrom.Text = To; } public void TogglePnlInvite(bool IsVisible) { pnlInvite.Visible = IsVisible; } public void ShowMessage(string Message) { lblMessage.Text = Message; } public void ResetUI() { txtMessage.Text = ""; txtTo.Text = ""; } }} Once this call is made we leap across to the presenter (more plumbing!). //Friends/Presenter/InviteFriendsPresenter.csusing System;using System.Data;using System.Configuration;using System.Linq;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Linq;using Fisharoo.FisharooCore.Core;using Fisharoo.FisharooCore.Core.DataAccess;using Fisharoo.FisharooCore.Core.Domain;using Fisharoo.FisharooWeb.Friends.Interface;using StructureMap;namespace Fisharoo.FisharooWeb.Friends.Presenter{ public class InviteFriendsPresenter { private IInviteFriends _view; private IUserSession _userSession; private IEmail _email; private IFriendInvitationRepository _friendInvitationRepository; private IAccountRepository _accountRepository; private IWebContext _webContext; private Account _account; private Account _accountToInvite; public void Init(IInviteFriends view) { _view = view; _userSession = ObjectFactory.GetInstance<IUserSession>(); _email = ObjectFactory.GetInstance<IEmail>(); _friendInvitationRepository = ObjectFactory.GetInstance< IFriendInvitationRepository>(); _accountRepository = ObjectFactory.GetInstance<IAccountRepository>(); _webContext = ObjectFactory.GetInstance<IWebContext>(); _account = _userSession.CurrentUser; if (_account != null) { _view.DisplayToData(_account.FirstName + " " + _account.LastName + " &lt;" + _account.Email + "&gt;"); if (_webContext.AccoundIdToInvite > 0) { _accountToInvite = _accountRepository.GetAccountByID (_webContext.AccoundIdToInvite); if (_accountToInvite != null) { SendInvitation(_accountToInvite.Email, _account.FirstName + " " + _account.LastName + " would like to be your friend!"); _view.ShowMessage(_accountToInvite.Username + " has been sent a friend request!"); _view.TogglePnlInvite(false); } } } } public void SendInvitation(string ToEmailArray, string Message) { string resultMessage = "Invitations sent to the following recipients:<BR>"; resultMessage += _email.SendInvitations (_userSession.CurrentUser,ToEmailArray, Message); _view.ShowMessage(resultMessage); _view.ResetUI(); } }} The interesting thing here is the SendInvitation() method, which takes in a comma delimited array of emails and the message to be sent in the invitation. It then makes a call to the Email.SendInvitations() method. //Core/Impl/Email.cspublic string SendInvitations(Account sender, string ToEmailArray, string Message){ string resultMessage = Message; foreach (string s in ToEmailArray.Split(',')) { FriendInvitation friendInvitation = new FriendInvitation(); friendInvitation.AccountID = sender.AccountID; friendInvitation.Email = s; friendInvitation.GUID = Guid.NewGuid(); friendInvitation.BecameAccountID = 0; _friendInvitationRepository.SaveFriendInvitation(friendInvitation); //add alert to existing users alerts Account account = _accountRepository.GetAccountByEmail(s); if(account != null) { _alertService.AddFriendRequestAlert(_userSession.CurrentUser, account, friendInvitation.GUID, Message); } //TODO: MESSAGING - if this email is already in our system add a message through messaging system //if(email in system) //{ // add message to messaging system //} //else //{ // send email SendFriendInvitation(s, sender.FirstName, sender.LastName, friendInvitation.GUID.ToString(), Message); //} resultMessage += "• " + s + "<BR>"; } return resultMessage;} This method is responsible for parsing out all the emails, creating a new FriendInvitation, and sending the request via email to the person who was invited. It then adds an alert to the invited user if they have an Account. And finally we have to add a notification to the messaging system once it is built. Outlook CSV importer The Import Contacts page is responsible for allowing our users to upload an exported contacts file from MS Outlook into our system. Once they have imported their contacts, the user is allowed to select which email addresses are actually invited into our system. Importing contacts As this page is made up of a couple of views, let's begin with the initial view. //Friends/OutlookCsvImporter.aspx<asp:Panel ID="pnlUpload" runat="server"> <div class="divContainerTitle">Import Contacts</div> <div class="divContainerRow"> <div class="divContainerCellHeader">Contacts File:</div> <div class="divContainerCell"><asp:FileUpload ID="fuContacts" runat="server" /></div> </div> <div class="divContainerRow"> <div class="divContainerFooter"><asp:Button ID="btnUpload" Text="Upload & Preview Contacts" runat="server" OnClick="btnUpload_Click" /></div> </div> <br /><br /> <div class="divContainerRow"> <div class="divContainerTitle">How do I export my contacts from Outlook?</div> <div class="divContainerCell"> <ol> <li> Open Outlook </li> <li> In the File menu choose Import and Export </li> <li> Choose export to a file and click next </li> <li> Choose comma seperated values and click next </li> <li> Select your contacts and click next </li> <li> Browse to the location you want to save your contacts file </li> <li> Click finish </li> </ol> </div> </div></asp:Panel> As you can see from the code we are working in panels here. This panel is responsible for allowing a user to upload their Contacts CSV File. It also gives some directions to the user as to how to go about exporting contacts from Outlook. This view has a file upload box that allows the user to browse for their CSV file, and a button to tell us when they are ready for the upload. There is a method in our presenter that handles the button click from the view. //Friends/Presenter/OutlookCsvImporterPresenter.cspublic void ParseEmails(HttpPostedFile file){ using (Stream s = file.InputStream) { StreamReader sr = new StreamReader(s); string contacts = sr.ReadToEnd(); _view.ShowParsedEmail(_email.ParseEmailsFromText(contacts)); }} This method is responsible for handling the upload process of the HttpPostedFile. It puts the file reference into a StreamReader and then reads the stream into a string variable named contacts. Once we have the entire list of contacts we can then call into our Email class and parse all the emails out. //Core/Impl/Email.cspublic List<string> ParseEmailsFromText(string text){ List<string> emails = new List<string>(); string strRegex = @"w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*"; Regex re = new Regex(strRegex, RegexOptions.Multiline); foreach (Match m in re.Matches(text)) { string email = m.ToString(); if(!emails.Contains(email)) emails.Add(email); } return emails;} This method expects a string that contains some email addresses that we want to parse. It then parses the emails using a regular expression (which we won't go into details about!). We then iterate through all the matches in the Regex and add the found email addresses to our list provided they aren't already present. Once we have found all the email addresses, we will return the list of unique email addresses. The presenter then passes that list of parsed emails to the view. Selecting contacts Once we have handled the upload process and parsed out the emails, we then need to display all the emails to the user so that they can select which ones they want to invite. Now you could do several sneaky things here. Technically the user has uploaded all of their email addresses to you. You have them. You could store them. You could invite every single address regardless of what the user wants. And while this might benefit your community over the short run, your users would eventually find out about your sneaky practice and your community would start to dwindle. Don't take advantage of your user's trust! //Friends/OutlookCsvImporter.aspx<asp:Panel visible="false" ID="pnlEmails" runat="server"> <div class="divContainerTitle">Select Contacts</div> <div class="divContainerFooter"><asp:Button ID="btnInviteContacts1" runat="server" OnClick="btnInviteContacts_Click" Text="Invite Selected Contacts" /></div> <div class="divContainerCell" style="text-align:left;"> <asp:CheckBoxList ID="cblEmails" RepeatColumns="2" runat="server"></asp:CheckBoxList> </div> <div class="divContainerFooter"><asp:Button ID="btnInviteContacts2" runat="server" OnClick="btnInviteContacts_Click" Text="Invite Selected Contacts" /></div></asp:Panel> Notice that we have a checkbox list in our panel. This checkbox list is bound to the returned list of email addresses. public void ShowParsedEmail(List<string> Emails){ pnlUpload.Visible = false; pnlResult.Visible = false; pnlEmails.Visible = true; cblEmails.DataSource = Emails; cblEmails.DataBind();} The output so far looks like this: Now the user has a list of all the email addresses that they uploaded, which they can then go through selecting the ones that they want to invite into our system. Once they are through selecting the emails that they want to invite, they can click on the Invite button. We then iterate through all the items in the checkbox list to locate the selected items. protected void btnInviteContacts_Click(object sender, EventArgs e){ string emails = ""; foreach (ListItem li in cblEmails.Items) { if(li != null && li.Selected) emails += li.Text + ","; } emails = emails.Substring(0, emails.Length - 1); _presenter.InviteContacts(emails);} Once we have gathered all the selected emails, we pass them to the presenter to run the invitation process. public void InviteContacts(string ToEmailArray){ string result = _email.SendInvitations(_userSession.CurrentUser, ToEmailArray, ""); _view.ShowInvitationResult(result);} The presenter promptly passes the selected items to the Email class to handle the invitations. This is the same method that we used in the last section to invite users. //Core/Impl/Email.cspublic string SendInvitations(Account sender, string ToEmailArray, string Message){...} We then output the result of the emails that we invited into the third display. <asp:Panel ID="pnlResult" runat="server" Visible="false"> <div class="divContainerTitle">Invitations Sent!</div> <div class="divContainerCell"> Invitations were sent to the following emails:<br /> <asp:Label ID="lblMessage" runat="server"></asp:Label> </div></asp:Panel>
Read more
  • 0
  • 0
  • 4768
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-maximizing-everyday-debugging
Packt
14 Mar 2014
5 min read
Save for later

Maximizing everyday debugging

Packt
14 Mar 2014
5 min read
(For more resources related to this topic, see here.) Getting ready For this article, you will just need a premium version of VS2013 or you may use VS Express for Windows Desktop. Be sure to run your choice on a machine using a 64-bit edition of Windows. Note that Edit and Continue previously existed for 32-bit code. How to do it… Both features are now supported by C#/VB, but we will be using C# for our examples. The features being demonstrated are compiler-based features, so feel free to use code from one of your own projects if you prefer. To see how Edit and Continue can benefit 64-bit development, perform the following steps: Create a new C# Console Application using the default name. To ensure the demonstration is running with 64-bit code, we need to change the default solution platform. Click on the drop-down arrow next to Any CPU and select Configuration Manager…: When the Configuration Manager dialog opens, we can create a new Project Platform targeting 64-bit code. To do this, click on the drop-down menu for Platform and select <New...>: When <New...> is selected, it will present the New Project Platform dialog box. Select x64 as the new platform type: Once x64 has been selected, you will return to the Configuration Manager. Verify that x64 remains active under Platform and then click on Close to close this dialog. The main IDE window will now indicate that x64 is active: Now, let's add some code to demonstrate the new behavior. Replace the existing code in your blank class file so that it looks like the following listing: class Program { static void Main(string[] args) { int w = 16; int h = 8; Debugging Your .NET Application 156 int area = calcArea(w, h); Console.WriteLine("Area: " + area); } private static int calcArea(int width, int height) { return width / height; } } Let's set some breakpoints so that we are able to inspect during execution. First, add a breakpoint to the Main method's Console line. Add a second breakpoint to the calcArea method's return line. You can do this by either clicking on the left side of the editor window's border or by right-clicking on the line, and selecting Breakpoint | Insert Breakpoint: If you are not sure where to click, use the right-click method and then practice toggling the breakpoint by left-clicking on the breakpoint marker. Feel free to use any method that you find most convenient. Once the two breakpoints are added, Visual Studio will mark their location as shown in the following screenshot (the arrow indicates where you may click to toggle the breakpoint): With the breakpoint marker now set, let's debug the program. Begin debugging by either pressing F5 or clicking on the Start button on the toolbar: Once debugging starts, the program will quickly execute until stopped by the first breakpoint. Let's first take a look at Edit and Continue. Visual Studio will stop at the calcArea method's return line. Astute readers will notice an error (marked by 1 in the following screenshot) present in the calculation as the area value returned should be width * height. Make the correction. Before continuing, note the variables listed in the Autos window (marked by 2 in the following screenshot). If you don't see Autos, it can be made visible by pressing Ctrl + D, A or through Debug | Windows | Autos while debugging. After correcting the area calculation, advance the debugging step by pressing F10 twice. (Alternatively make the advancement by selecting the menu item Debug | Step Over twice). Visual Studio will advance to the declaration for area. Note that you were able to edit your code and continue debugging without restarting. The Autos window will update to display the function's return value, which is 128 (the value for area has not been assigned yet): There's more… Programmers who write C++ already have the ability to see the return values of functions; this just brings .NET developers into the fold. Your development experience won't have to suffer based on the languages chosen for your projects. The Edit and Continue functionality is also available for ASP.NET projects. New projects created in VS2013 will have Edit and Continue enabled by default. Existing projects imported to VS2013 will usually need this to be enabled if it hasn't been already. To do so, right-click on your ASP.NET project in Solution Explorer and select Properties (alternatively, it is also available via Project | <Project Name> Properties…). Navigate to the Web option and scroll to the bottom to check the Enable Edit and Continue checkbox. The following screenshot shows where this option is located on the properties page: Summary In this article, we learned how to use the Edit and Continue feature. Using this feature enables you to make changes to your project without having to immediately recompile your project. This simplifies debugging and enables a bit of exploration. You also saw how the Autos window can display the values of variables as you step through your program’s execution. Resources for Article: Further resources on this subject: Using the Data Pager Control in Visual Studio 2008 [article] Load Testing Using Visual Studio 2008: Part 1 [article] Creating a Simple Report with Visual Studio 2008 [article]
Read more
  • 0
  • 0
  • 4767

article-image-software-task-management-tool-rake
Packt
16 Apr 2014
5 min read
Save for later

The Software Task Management Tool - Rake

Packt
16 Apr 2014
5 min read
(For more resources related to this topic, see here.) Installing Rake As Rake is a Ruby library, you should first install Ruby on the system if you don't have it installed already. The installation process is different for each operating system. However, we will see the installation example only for the Debian operating system family. Just open the terminal and write the following installation command: $ sudo apt-get install ruby If you have an operating system that doesn't contain the apt-get utility and if you have problems with the Ruby installation, please refer to the official instructions at https://www.ruby-lang.org/en/installation. There are a lot of ways to install Ruby, so please choose your operating system from the list on this page and select your desired installation method. Rake is included in the Ruby core as Ruby 1.9, so you don't have to install it as a separate gem. However, if you still use Ruby 1.8 or an older version, you will have to install Rake as a gem. Use the following command to install the gem: $ gem install rake The Ruby release cycle is slower than that of Rake and sometimes, you need to install it as a gem to work around some special issues. So you can still install Rake as a gem and in some cases, this is a requirement even for Ruby Version 1.9 and higher. To check if you have installed it correctly, open your terminal and type the following command: $ rake --version This should return the installed Rake version. The next sign that Rake is installed and is working correctly is an error that you see after typing the rake command in the terminal: $ mkdir ~/test-rake $ cd ~/test-rake $ rake rake aborted! No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb) (See full trace by running task with --trace) Downloading the example code You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. Introducing rake tasks From the previous error message, it's clear that first you need to have Rakefile. As you can see, there are four variants of its name: rakefile, Rakefile, rakefile.rb, and Rakefile.rb. The most popularly used variant is Rakefile. Rails also uses it. However, you can choose any variant for your project. There is no convention that prohibits the user from using any of the four suggested variants. Rakefile is a file that is required for any Rake-based project. Apart from the fact that its content usually contains DSL, it's also a general Ruby file. Also, you can write any Ruby code in it. Perform the following steps to get started: Let's create a Rakefile in the current folder, which will just say Hello Rake, using the following commands: $ echo "puts 'Hello Rake'" > Rakefile $ cat Rakefile puts 'Hello Rake' Here, the first line creates a Rakefile with the content, puts 'Hello Rake', and the second line just shows us its content to make sure that we've done everything correctly. Now, run rake as we tried it before, using the following command: $ rake Hello Rake rake aborted! Don't know how to build task 'default' (See full trace by running task with --trace) The message has changed and it says Hello Rake. Then, it gets aborted because of another error message. At this moment, we have made the first step in learning Rake. Now, we have to define a default rake task that will be executed when you try to start Rake without any arguments. To do so, open your editor and change the created Rakefile with the following content: task :default do puts 'Hello Rake' end Now, run rake again: $ rake Hello, Rake The output that says Hello, Rake demonstrates that the task works correctly. The command-line arguments The most commonly used rake command-line argument is -T. It shows us a list of available rake tasks that you have already defined. We have defined the default rake task, and if we try to show the list of all rake tasks, it should be there. However, take a look at what happens in real life using the following command: $ rake -T The list is empty. Why? The answer lies within Rake. Run the rake command with the -h option to get the whole list of arguments. Pay attention to the description of the -T option, as shown in the following command-line output: -T, --tasks [PATTERN] Display the tasks (matching optional PATTERN) with descriptions, then exit. You can get more information on Rake in the repository at the following GitHub link at https://github.com/jimweirich/rake. The word description is the cornerstone here. It's a new term that we should know. Additionally, there is also an optional description to name a rake task. However, it's recommended that you define it because you won't see the list of all the defined rake tasks that we've already seen. It will be inconvenient for you to read your Rakefile every time you try to run some rake task. Just accept it as a rule: always leave a description for the defined rake tasks. Now, add a description to your rake tasks with the desc method call, as shown in the following lines of code: desc "Says 'Hello, Rake'" task :default do puts 'Hello, Rake.' end As you see, it's rather easy. Run the rake -T command again and you will see an output as shown: $ rake -T rake default # Says 'Hello, Rake' If you want to list all the tasks even if they don't have descriptions, you can pass an -A option with the -T option to the rake command. The resulting command will look like this: rake -T -A.
Read more
  • 0
  • 0
  • 4767

article-image-branding-sharepoint-device-channels-and-design-packages
Packt
22 Jan 2014
11 min read
Save for later

Branding SharePoint with Device Channels and Design Packages

Packt
22 Jan 2014
11 min read
With the 2013 release of SharePoint, Microsoft has added two new capabilities that assist with full-scale branding of SharePoint sites: device channels and design packages. A device channel uses the user agent of the web browser sending the incoming web request to determine which master page to render the content pages with. A common use of the device channels is to detect tablets and smartphones to use a more touch-friendly interface design. For instance, a device channel can be configured to look for an iPad in the following user agent to identify the iPad devices: Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X)AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0Mobile/11B554a Safari/9537.53 Any portion of the user agent can be used for a device channel. It is important to be specific, but not too specific. Using iPad would apply to all the devices that specify iPad in their user agent, whereas iPad; U; CPU OS 7_0 would only apply to iPads running on iOS Version 7.0. A design package is a SharePoint solution, packaged as a WSP file containing branding customizations, such as master pages and cascading style sheets. This provides a simple method of exporting a site design from one site and applying it to another. A design package will only contain items that are not default to SharePoint. Default items, such as the included master pages, will be referenced, but are not included as part of the package. Prior to SharePoint 2013, packaged design solutions could only be created manually or with Visual Studio. Design packages allow any site collection administrator to create and apply packaged designs. This allows the site collection administrators to obtain packaged designs (from third parties, and so on) and apply them, without having to manually upload and configure each piece of the design. Creating a device channel for mobile devices One of the most common scenarios for using device channels is to identify the tablet and smartphone browsers. Applying a mobile-specific master page, when appropriate, can provide the users with a design that is more touch friendly and is laid out in a specific manner for smaller screens. In this recipe, we are going to create a device channel that will identify Android, iOS, BlackBerry, WebOS, and Windows mobile devices. There are hundreds of mobile-specific browsers that we can detect with the user agent. However, for this recipe we are going to keep it simple. Getting ready In order to view and modify the device channels for a SharePoint site, the SharePoint Server Publishing Infrastructure site collection feature and SharePoint Server Publishing site feature must be activated. How to do it... Follow these steps to create a device channel for mobile devices: Navigate to the site in your preferred web browser. Select Site settings from the Settings menu. Select Device Channels from the Look and Feel section. You can also navigate to the Device Channels page from the Design Manager page. Select New Item. Provide a Name, Description, and Alias for the device channel. The Alias field specified will be used when specifying which master page to use with the device channel in the device channel mappings file. We will learn about this in the next recipe, Applying a master page to a device channel. Specify the Device Inclusion Rules to be included in the device channel. Android iPad iPod iPhone BlackBerry IEMobile WebOS When using multiple device inclusion rules, place each string on a new line to match the user agent. Device Inclusion Rules are simply strings that are looked for in the user agent of incoming web requests. Mark the Active checkbox and click on Save. How it works... Device channels are created and stored in the /DeviceChannels SharePoint list in the root site of a site collection. When an incoming browser request is received, SharePoint checks whether the incoming user agent matches any of the Device Inclusion Rules before selecting the master page to use. Many web browsers have developer tools that allow changing the user agent reported by the browser. Switching the user agent is one way in which we can test to ensure our device channels are working correctly. Internet Explorer 11, for instance, includes this option in the Emulation section of the F12 Developer Tools. There's more... A device channel may also be created with PowerShell or with code using the server-side object model. Creating a device channel for mobile devices using PowerShell Follow these steps to create a device channel for mobile devices using PowerShell: Get the site using the Get-SPWeb Cmdlet. $web = Get-SPWeb http://sharepoint/site Get the DeviceChannels list. $list = $web.Lists["Device Channels"] Add a new SPListItem item to the Items collection of the list. $item = $list.Items.Add() Assign the values to each of the properties on the SPListItem item. $item["Name"] = "PowerShell" $item["Alias"] = "PowerShell" $item["Description"] = "PowerShell Channel" $item["Device Inclusion Rules"] = "Android`niPad`niPod`niPhone`nBlackBerry`nIEMobile`nWebOS" $item["Active"] = $true When a line break is required within a string, in PowerShell, an escape character can be used. Escape characters in PowerShell use the tilde character. For example, a new line is represented by `n. Call the Update method on the list to update the Items collection. $item.Update() Use the Dispose method to discard the SPWeb object. $web.Dispose() Creating a device channel for mobile devices with code using the server-side object model Follow these steps to create a device channel for mobile devices with code using the server-side object model: Open the site collection containing the site in a using statement. using (var site = new SPSite("http://sharepoint/site")) Open the site in a using statement. using (var web = site.OpenWeb()) Get the DeviceChannels list. var list = web.Lists["Device Channels"]; Add a new SPListItem item to the Items collection of the list. var item = list.Items.Add(); Assign the values to each of the properties on the SPListItem item. item["Name"] = "Code"; item["Alias"] = "Code "; item["Description"] = "Code Channel"; item["Device Inclusion Rules"] = "AndroidniPadniPodniPhonenBlackBerrynIEMobilenWebOS"; item["Active"] = true; When a line break is required within a string in C#, an escape character can be used. Escape characters in C# use the backslash character. For example, a new line is represented by n. Call the Update method on the list to update the Items collection. item.Update(); See also SharePoint Design Manager branding and design capabilities How to: Add or Delete List Items SPWeb class SPSite class Get-SPWeb Applying a master page to a device channel Once a device channel has been created, it can be configured to use as a different site master page rather than the default site master page. For instance, browsers targeted by a mobile device channel could display the content using the oslo master page whereas all other browsers could display the same content using the seattle master page. The System Master Page is configured for all device channels and cannot be configured for individual device channels. How to do it... Follow these steps to apply a master page to a device channel: Navigate to the site in your preferred web browser. Select Site settings from the Settings menu. Select Master page from the Look and Feel section. Specify which Site Master Page to use for each device channel. Click on Save. How it works... The master page to device channel mappings are stored in the _catalogs/masterpages/__DeviceChannelMappings.aspx file as XML within the root site of a site collection. For each incoming browser web request, this file is used by SharePoint to determine which master page to use with the content returned to the browser. There's more... A device channel mapping may also be configured with PowerShell or with code using the server-side object model. In this recipe, these two methods are similar. However, the .NET reflection methods used are slightly different. When an object is instantiated with reflection in PowerShell, its public properties and methods become available to the command line. However, when an object is instantiated with reflection in the .NET code, each property and method needs to be searched for before being able to access them. The methods that provide the functionality to configure the device channel mappings are not publicly exposed in the SharePoint assemblies. As a result, we will use the .NET reflection to instantiate the objects required. It is important to note that non-public classes in the SharePoint assemblies can change between SharePoint versions and updates without notice. Using reflection tools, such as .NET Reflector (http://www.red-gate.com/products/dotnet-development/reflector/) and dotPeek (http://www.jetbrains.com/decompiler/), we can browse the assemblies to adjust the references accordingly. Applying a master page to a device channel using PowerShell Follow these steps to apply a master page to a device channel using PowerShell: Load the Microsoft.SharePoint.dll and Microsoft.SharePoint.Publishing.dll assemblies into the PowerShell session. [Reflection.Assembly]::LoadFrom("C:Program FilesCommonFilesmicrosoft sharedWeb ServerExtensions15ISAPIMicrosoft.SharePoint.Publishing.dll") [Reflection.Assembly]::LoadFrom("C:Program FilesCommonFilesmicrosoft sharedWeb ServerExtensions15ISAPIMicrosoft.SharePoint.dll") Get the object types for the parameters that will be used when getting the class constructor for the MasterPageMappingsFile object and later instantiating the object. $typeWeb = [Microsoft.SharePoint.SPWeb] $typeBool = [System.Boolean] $typeMappingFile =[System.Type]::GetType("Microsoft.SharePoint.Publishing.Mobile.MasterPageMappingsFile, Microsoft.SharePoint.Publishing,Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c") Create an array of the object types. $consMappingFileParams = ($typeWeb, $typeBool, $typeWeb) Get the class constructor for the MasterPageMappingsFile object. $consMappingFile = $typeMappingFile.GetConstructor($consMappingFileParams) Create an array of the parameters required to instantiate the MasterPageMappingsFile object. $mappingFileParams =[System.Array]::CreateInstance([System.Object], 3)$mappingFileParams[0] = (Get-SPSitehttp://sharepoint/sitecollection).RootWeb$mappingFileParams[1] = $false$mappingFileParams[2] = $null When invoking a constructor to create an instance of a .NET object in PowerShell, we have to create a System.Object array rather than using a PowerShell array. Even though the base class for a PowerShell array is System.Object[], when calling the Invoke method on the class constructor, it will see it as a PSObject object instead. The same goes for the SPWeb object we are passing as the first parameter. .NET will see the object as a PSObject object instead of a SPWeb object if we use Get-SPWeb. However, if we get the SPWeb object from the SPSite object, it will not get treated as a PSObject object. Invoke the class constructor to create an instance of the MasterPageMappingsFile object. $mappingFile = $consMappingFile.Invoke($mappingFileParams) Set the MasterPageUrl property for the device channel on the MasterPageMappingsFile object. $mappingFile["PowerShell"].MasterPageUrl = "/_catalogs/masterpage/oslo.master" Save the changes using the UpdateSingleChannel method. $mappingFile.UpdateSingleChannel("PowerShell") Applying a master page to a device channel with code using the server-side object model Follow these steps to apply a master page to a device channel with code using the server-side object model: A reference to the Microsoft.SharePoint.Publishing.dll assembly is required for this recipe. Get the site collection in a using statement. using (var site = new SPSite("http://sharepoint/sitecollection")) Get the root site of the site collection in a using statement. using (var web = site.RootWeb) Get the object type that will be used when getting the class constructor for the MasterPageMappingsFile object and later instantiating the object. MasterPageMappingsFile object and later instantiating the object.var typeMappingFile =Type.GetType("Microsoft.SharePoint.Publishing.Mobile.MasterPageMappingsFile, Microsoft.SharePoint.Publishing,Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"); Get the class constructor for the MasterPageMappingsFile object. var consMappingFile =typeMappingFile.GetConstructor(new Type[] { typeof(SPWeb),typeof(bool), typeof(SPWeb) }); Invoke the constructor to create an instance of the MasterPageMappingsFile object. var mappingFile = consMappingFile.Invoke(new object[] { web, false, null }); Get the mappings field of the MasterPageMappingsFile object, and cast the field as an IDictionary. var mappings = (IDictionary)typeMappingFile.GetField("mappings",BindingFlags.Instance | BindingFlags.NonPublic).GetValue(mappingFile); Set the MasterPageUrl property for the device channel on the mappings field. mappings["PowerShell"].GetType().GetProperty("MasterPageUrl",BindingFlags.Instance |BindingFlags.Public).SetValue(mappings["PowerShell"],"/_catalogs/masterpage/seattle.master", null); Set the mappings field of the MasterPageMappingsFile object. typeMappingFile.GetField("mappings", BindingFlags.Instance |BindingFlags.NonPublic).SetValue(mappingFile, mappings); Get the UpdateSingleChannel method from the type of the MasterPageMappingsFile object. var updateMethod = typeMappingFile.GetMethod("UpdateSingleChannel",BindingFlags.Instance | BindingFlags.Public, null, new Type[]{ typeof(string) }, null); Save the changes by invoking the UpdateSingleChannel method. updateMethod.Invoke(mappingFile, new object[] { "Code" });
Read more
  • 0
  • 0
  • 4767

article-image-sneak-peek-ios-touch-id
Packt
23 Dec 2014
4 min read
Save for later

Sneak peek into iOS Touch ID

Packt
23 Dec 2014
4 min read
This article, created by Mayank Birani, the author of Learning iOS 8 for Enterprise, Apple introduced a new feature in iOS 7 called Touch ID authentication. Previously, there was only four-digit passcode security in iPhones; now, Apple has extended security and introduced a new security pattern in iPhones. In Touch ID authentication, our fingerprint acts as a password. After launching the Touch ID fingerprint-recognition technology in the iPhone 5S last year, Apple is now providing it for developers with iOS 8. Now, third-party apps will be able to use Touch ID for authentication in the new iPhone and iPad OSes. Accounting apps, and other apps that contain personal and important data, will be protected with Touch ID. Now, you can protect all your apps with your fingerprint password. (For more resources related to this topic, see here.) There are two ways to use Touch ID as an authentication mechanism in our iOS 8 applications. They are explained in the following sections. Touch ID through touch authentication The Local Authentication API is an API that returns a Boolean value to accept and decline the fingerprint. If there is an error, then an error code gets executed and tells us what the issue is. Certain conditions have to be met when using Local Authentication. They are as follows: The application must be in the foreground (this doesn't work with background processes) If you're using the straight Local Authentication method, you will be responsible for handling all the errors and properly responding with your UI to ensure that there is an alternative method to log in to your apps Touch ID through Keychain Access Keychain Access includes the new Touch ID integration in iOS 8. In Keychain Access, we don't have to work on implementation details; it automatically handles the passcode implementation using the user's passcode. Several keychain items can be chosen to use Touch ID to unlock the item when requested in code through the use of the new Access Control Lists (ACLs). ACL is a feature of iOS 8. If Touch ID has been locked out, then it will allow the user to enter the device's passcode to proceed without any interruption. There are some features of Keychain Access that make it the best option for us. They are listed here: Keychain Access uses Touch ID, and its attributes won't be synced by any cloud services. So, these features make it very safe to use. If users overlay more than one query, then the system gets confused about correct user, and it will pop up a dialog box with multiple touch issues. How to use the Local Authentication framework Apple provides a framework to use Touch ID in our app called Local Authentication. This framework was introduced for iOS 8. To make an app, including the Touch ID authentication, we need to import this framework in our code. It is present in the framework library of Apple. Let's see how to use the Local Authentication framework: Import the Local Authentication framework as follows: #import<localAuthentication/localAuthentication.h> This framework will work on Xcode 6 and above. To use this API, we have to create a Local Authentication context, as follows: LAContext *passcode = [[LAContext alloc] init]; Now, check whether Touch ID is available or not and whether it can be used for authentication: - (BOOL)canEvaluatePolicy:(LAPolicy)policy error: (NSError * __autoreleasing *)error; To display Touch ID, use the following code: - (void)evaluatePolicy:(LAPolicy)policy localizedReason: (NSString *)localizedReason    reply:(void(^)(BOOL success, NSError *error))reply; Take a look at the following example of Touch ID: LAContext *passcode = [[LAContext alloc] init]; NSError *error = nil; NSString *Reason = <#String explaining why our app needs authentication#>; if ([passcode canEvaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { [passcode evaluatePolicy:      LAPolicyDeviceOwnerAuthenticationWithBiometrics    localizedReason:Reason reply:^(BOOL success, NSError      *error) {        if (success)        {          // User authenticated successfully        } else        {          // User did not authenticate successfully,            go through the error        }    }]; } else {    // could not go through policy look at error and show an appropriate message to user } Summary In this article, we focused on the Touch ID API, which was introduced in iOS 8. We also discussed how Apple has improved its security feature using this API. Resources for Article: Further resources on this subject: Sparrow iOS Game Framework - The Basics of Our Game [article] Updating data in the background [article] Physics with UIKit Dynamics [article]
Read more
  • 0
  • 0
  • 4765
article-image-oracle-integration-and-consolidation-products
Packt
09 Aug 2011
11 min read
Save for later

Oracle Integration and Consolidation Products

Packt
09 Aug 2011
11 min read
Oracle Information Integration, Migration, and Consolidation The definitive book and eBook guide to Oracle information integration and migration in a heterogeneous world Data services Data services are at the leading edge of data integration. Traditional data integration involves moving data to a central repository or accessing data virtually through SQL-based interfaces. Data services are a means of making data a 'first class' citizen in your SOA. Recently, the idea of SOA-enabled data services has taken off in the IT industry. This is not any different than accessing data using SQL, JDBC, or ODBC. What is new is that your service-based architecture can now view any database access service as a web service. Service Component Architecture (SCA) plays a big role in data services as now data services created and deployed using Oracle BPEL, Oracle ESB, and other Oracle SOA products can be part of an end-to-end data services platform. No longer do data services deployed in one of the SOA products have to be deployed in another Oracle SOA product. SCA makes it possible to call a BPEL component from Oracle Service Bus and vice versa. Oracle Data Integration Suite Oracle Data Integration (ODI)Suite includes the Oracle Service Bus to publish and subscribe messaging capabilities. Process orchestration capabilities are provided by Oracle BPEL Process Manager, and can be configured to support rule-based, event-based, and data-based delivery services. The Oracle Data Quality for Data Integrator, Oracle Data Profiling products, and Oracle Hyperion Data Relationship Manager provide best-in-class capabilities for data governance, change management hierarchical data management, and provides the foundation for reference data management of any kind. ODI Suite allows you to create data services that can be used in your SCA environment. These data services can be created in ODI, Oracle BPEL or the Oracle Service Bus. You can surround your SCA data services with Oracle Data Quality and Hyperion Data Relationship to cleanse your data and provide master data management. ODI Suite effectively serves two purposes: Bundle Oracle data integration solutions as most customers will need ODI, Oracle BPEL, Oracle Service Bus, and data quality and profiling in order to build a complete data services solution Compete with similar offerings from IBM (InfoSphere Information Server) and Microsoft (BizTalk 2010) that offer complete EII solutions in one offering The ODI Suite data service source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsERPs, CRMs, B2B systems, flat files, XML data, LDAP, JDBC, ODBCAny data sourceSQL, Java, GUI The most likely instances or use cases when ODI Suite would be the Oracle product or tool selected are: SCA-based data services An end-to-end EII and data migration solution Data services can be used to expose any data source as a service. Once a data service is created, it is accessible and consumable by any web service-enabled product. In the case of Oracle, this is the entire set of products in the Oracle Fusion Middleware Suite. Data consolidation The mainframe was the ultimate solution when it came to data consolidation. All data in an enterprise resided in one or several mainframes that were physically located in a data center. The rise of the hardware and software appliance has created a 'what is old is new again' situation; a hardware and software solution that is sold as one product. Oracle has released the Oracle Exadata appliance and IBM acquired the pure database warehouse appliance company Netezza, HP, and Microsoft announced work on an SQL Server database appliance, and even companies like SAP, EMC, and CICSO are talking about the benefits of database appliances. The difference is (and it is a big difference) that the present architecture is based upon open standards hardware platforms, operating systems, client devices, network protocols, interfaces, and databases. So, you now have a database appliance that is not based upon proprietary operating systems, hardware, network components, software, and data disks. Another very important difference is that enterprise software COTS packages, management tools, and other software infrastructure tools will work across any of these appliance solutions. One of the challenges for customers that run their business on the mainframe is that they are 'locked into' vendor- specific sorting, reporting, job scheduling, system management, and other products usually only offered from IBM, CA, BMC, or Compuware. Mainframe customers also suffer from a lack of choice when it comes to COTS applications. Since appliances are based upon open systems, there is an incredibly large software ecosystem. Oracle Exadata Oracle Exadata is the only database appliance that runs both data warehouse and OLTP applications. Oracle Exadata is an appliance that includes every component an IT organization needs to process information—from a grid database down to the power supply. It is a hardware and software solution that can be up and running in an enterprise in weeks instead of months for typical IT database solutions. Exadata provides high speed data access using a combination of hardware and a database engine that runs at the storage tier. Typical database solutions have to use indexes to retrieve data from storage and then pull large volumes of data into the core database engine, which churns through millions of rows of data to send a handful of row results to the client. Exadata eliminates the need for indexes and data engine processing by placing a lightweight database engine at the storage tier. Therefore, the database engine is only provided with the end result and does not have to utilize complicated indexing schemes, large amounts of CPU, and memory to produce the end results set. Exadata's capabilities to run large OLTP and data warehouse applications, or a large number of smaller OLTP and data warehouse applications on one machine make it a great platform for data consolidation. The first release of Oracle Exadata was based upon HP hardware and was for data warehouses only. The second release came out shortly before Oracle acquired Sun. This release was based upon Sun hardware, but ironically not on Sun Sparc or Solaris (Solaris is now an OS option). The Exadata source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsAny (depending upon the data source this may involve an intensive migration effort)Oracle ExadataSQL, PL/SQL, Java The most likely instances or use cases when Exadata would be the Oracle product or tool selected are: A move from hundreds of standalone database hardware and software nodes to one database machine A reduction in hardware and software vendors, and one vendor for hardware and software support Keepin It Real The database appliance has become the latest trend in the IT industry. Data warehouse appliances like Netezza have been around for a number of years. Oracle has been the first vendor to offer an open systems database appliance for both DW and OLTP environments. Data grid Instead of consolidating databases physically or accessing the data where it resides, a data grid places the data into an in-memory middle tier. Like physical federation, the data is being placed into a centralized data repository. Unlike physical federation, the data is not placed into a traditional RDBMS system (Oracle database), but into a high-speed memory-based data grid. Oracle offers both a Java and SQL-based data grid solution. The decision of what product to implement often depends on where the corporations system, database, and application developer skills are strongest. If your organization has strong Java or .Net skills and is more comfortable with application servers than databases, then Oracle Coherence is typically the product of choice. If you have strong database administration and SQL skills, then Oracle TimesTen is probably a better solution. The Oracle Exalogic solution takes the data grid to another level by placing Oracle Coherence, along with other Oracle hardware and software solutions, into an appliance. This appliance provides an 'end-to-end' solution or data grid 'in a box'. It reduces management, increases performance, reduces TCO, and eliminates the need for the customer having to build their own hardware and software solution using multiple vendor solutions that may not be certified to work together. Oracle Coherence Oracle Coherence is an in-memory data grid solution that offers next generation Extreme Transaction Processing (XTP). Organizations can predictably scale mission critical applications by using Oracle Coherence to provide fast and reliable access to frequently used data. Oracle Coherence enables customers to push data closer to the application for faster access and greater resource utilization. By automatically and dynamically partitioning data in memory across multiple servers, Oracle Coherence enables continuous data availability and transactional integrity, even in the event of a server failure. Oracle Coherence was purchased from Tangosol Software in 2007. Coherence was an industry-leading middle tier caching solution. The product only offered a Java solution at the time of acquisition, but a .NET offering was already scheduled before the acquisition took place. The Oracle Coherence source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsJDBC, any data source accessible through Oracle SOA adaptersCoherenceJava, .Net The most likely instances or use cases when Oracle Coherence would be the Oracle product or tool selected are: When it is necessary to replace custom, hand-coded solutions that cache data in middle tier Java or .NET application servers Your company's strengths are in application servers Java or .NET Oracle TimesTen Oracle TimesTen is a data grid/cache offering that has similar characteristics to Oracle Coherence. Both of the solutions offer a product that caches data in the middle tier for high throughput and high transaction volumes. The technology implementations are much different. TimesTen is an in-memory database solution that is accessed through SQL and the data storage mechanism is a relational database. The TimesTen solution data grid can be implemented across a wide area network (WAN) and the nodes that make up the data grid are kept in sync with your back end Oracle database using Oracle Cache Connect. Cache Connect is also used to automatically refresh the TimesTen database on a push or pull basis from your Oracle backend database. Cache Connect can also be used to keep TimesTen databases spread across the global in sync. Oracle TimesTen offers both read and update support, unlike other database in- memory solutions. This means that Oracle TimesTen can be used to run your business even if your backend database is down. The transactions that occur during the downtime are queued and applied to your backend database once it is restored. The other similarity between Oracle Coherence and TimesTen is that they both were acquired technologies. Oracle TimesTen was acquired from the company TimesTen in 2005. The Oracle TimesTen source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsOracleTimesTenSQL, CLI The most likely instances or use cases when Oracle TimesTen would be the Oracle product or tool selected are: For web-based read-only applications that require a millisecond responseand data close to where request is made For applications where updates need not be reflected back to the user in real-time Oracle Exalogic A simplified explanation of Oracle Exalogic is that it is Exadata for the middle tier application infrastructure. While Exalogic is optimized for enterprise Java, it is also a suitable environment for the thousands of third-party and custom Linux and Solaris applications widely deployed on Java, .NET, Visual Basic, PHP, or any other programming language. The core software components of Exalogic are WebLogic, Coherence, JRocket or Java Hotspot, and Oracle Linux or Solaris. Oracle Exalogic has an optimized version of WebLogic to run Java applications more efficiently and faster than a typical WebLogic implementation. Oracle Exalogic is branded with the Oracle Elastic cloud as an enterprise application consolidation platform. This means that applications can be added on demand and in real-time. Data can be cached in Oracle Coherence for a high speed, centralized, data grid sharable on the cloud. The Exalogic source and target data sources along with development languages and tools supported are: Data sourceData targetDevelopment languages and toolsAny data sourceCoherenceAny language The most likely instances or use cases when Exalogic would be the Oracle product or tool selected are: Enterprise consolidated application server platform Cloud hosted solution Upgrade and Consolidation of hardware or software Oracle Coherence is the product of choice for Java and .NET versed development shops. Oracle TimesTen is more applicable to database-centric and shops more comfortable with SQL.
Read more
  • 0
  • 0
  • 4765

article-image-performance-enhancements-aspnet
Packt
26 Jul 2013
40 min read
Save for later

Performance enhancements to ASP.NET

Packt
26 Jul 2013
40 min read
ASP.NET performance Performance is one of the primary goals for any system. For a server, the throughput /time actually specifies the performance of the hardware or software in the system. It is important to increase performance and decrease the amount of hardware used for the throughput. There must be a balance between the two. Performance is one of the key elements of web development. In the last phase of ASP.NET 4.5, performance was one of the key concerns for Microsoft. They made a few major changes to the ASP.NET system to make it more performant. Performance comes directly, starting from the CPU utilization all the way back to the actual code you write. Each CPU cycle you consume for producing your response will affect performance. Consuming a large number of CPU cycles will lead you to add more and more CPUs to avoid site unavailability. As we are moving more and more towards the cloud system, performance is directly related to the cost. Here, CPU cycles costs money. Hence to make a more cost effective system running on the cloud, unnecessary CPU cycles should always be avoided. .NET 4.5 addresses the problem to its core to support background GC. The background GC for the server introduces support for concurrent collection without blocking threads; hence the performance of the site is not compromised because of garbage collection as well. The multicore JIT in addition improves the start-up time of pages without additional work. By the way, some of the improvements in technology can be really tangible to developers as well as end users. They can be categorized as follows. CPU and JIT improvements ASP.NET feature improvements The first category is generally intangible while the second case is tangible. The CPU and JIT improvements, as we have already discussed, are actually related to server performance. JIT compilations are not tangible to the developers which means they will automatically work on the system rather than any code change while the second category is actually related to code. We will focus here mainly on the tangible improvements in this recipe. Getting ready To get started, let us start Visual Studio 2012 and create an ASP.NET project. If you are opening the project for the first time, you can choose the ASP.NET Web Forms Application project template. Visual Studio 2012 comes with a cool template which virtually creates the layout of a blank site. Just create the project and run it and you will be presented with a blank site with all the default behaviors you need. This is done without writing a single line of code. Now, if you look into Solution Explorer, the project is separated into folders, each representing its identification. For instance, the Scripts folder includes all the JavaScript associated with the site. You can also see the Themes folder in Content, which includes the CSS files. Generally, for production-level sites, we have large numbers of JavaScript and CSS files that are sometimes very big and they download to the client browser when the site is initially loaded. We specify the file path using the script or link path. If you are familiar with web clients you will know that, the websites request these files in a separate request after getting the HTTP response for the page. As most browsers don't support parallel download, the download of each file adds up to the response. Even during the completion of each download there is a pause, which we call network latency. So, if you see the entire page response of a website, you will see that a large amount of response time is actually consumed by the download of these external files rather than the actual website response. Let us create a page on the website and add few JavaScript files and see the response time using Fiddler: The preceding screenshot shows how the browser requests the resources. Just notice, the first request is the actual request made by the client that takes half of a second, but the second half of that second is consumed by the requests made by the response from the server. The server responds with a number of CSS and JavaScript requests in the header, which have eventually been called to the same web server one by one. Sometimes, if the JavaScript is heavy, it takes a lot of time to load these individual files to the client which results in delay in response time for the web page. It is the same with images too. Even though external files are downloaded in separate streams, big images hurt the performance of the web page as well: Here you can see that the source of the file contains the call to a number of files that corresponds to each request. When the HTML is processed on the browser, it invokes each of these file requests one by one and replaces the document with the reference of those files. As I have already told you, making more and more resources reduces the performance of a page. This huge number of requests makes the website very slow. The screenshot depicts the actual number of requests, the bytes sent and received, and the performance in seconds. If you look at some big applications, the performance of the page is reduced by a lot more than this. To address this problem we take the following two approaches: Minimizing the size of JavaScript and CSS by removing the whitespaces, newlines, tab spaces, and so on, or omitting out the unnecessary content Bundling all the files into one file of the same MIME type to reduce the requests made by the browser ASP.NET addresses both of these problems and introduces a new feature that can both minimize the content of the JavaScript and CSS files as well as bundle all the JavaScript or CSS files together to produce one single file request from the site. To use this feature you need to first install the package. Open Visual Studio 2012, select View | Other Windows | Package Manager Console as shown in the following screenshot. Package Manager Console will open the PowerShell window for package management inside Visual Studio: Once the package manager is loaded, type the following command. Install-Package Microsoft.Web.Optimization This will load the optimizations inside Visual Studio. On the other hand, rather than opening Package Manager Console, you can also open Nuget package manager by right-clicking on the references folder of the project and select Add Library Package Reference. This will produce a nice dialog box to select and install the appropriate package. In this recipe, we are going to cover how to take the benefits of bundling and minification of website contents in .NET 4.5. How to do it... In order to move ahead with the recipe, we will use a blank web solution instead of the template web solution that I have created just now. To do this, start Visual Studio and select the ASP.NET Empty Web Application template. The project will be created without any pages but with a web.config file (a web.config file is similar to app.config but works on web environments). Add a new page to the project and name it as home.aspx. Leave it as it is, and go ahead by adding a folder to the solution and naming it as Resources. Inside resources, create two folders, one for JavaScript named js and another for stylesheets name css. Create a few JavaScript files inside js folder and a few CSS files inside the css folder. Once you finish the folder structure will look like below: Now let us add the files on the home page. Just drag-and-drop the js files one by one into the head section of the page. The page IDE will produce the appropriate tags for scripts and CSS automatically. Now run the project. You will see that the CSS and the JavaScript are appropriately loaded. To check, try using Fiddler. When you select the source of a page, you will see links that points to the JavaScript, CSS, or other resource files. These files are directly linked to the source and hence if we navigate to these files, it will show the raw content of the JavaScript. Open Fiddler and refresh the page keeping it open in Internet Explorer in the debug mode. You will see that the browser invokes four requests. Three of them are for external files and one for the actual HTML file. The Fiddler shows how the timeframe of the request is maintained. The first request being for the home.aspx file while the others are automatically invoked by the browser to get the js and css files. You can also take a note at the total size of the whole combined request for the page. Let's close the browser and remove references to the js and css files from the head tag, where you have dragged and added the following code to reference folders rather than individual files: <script src = "Resources/js"></script> <link rel="stylesheet" href="Resources/css" /> Open the Global.asax file (add if not already added) and write the following line in Application_Start: void Application_Start(object sender, EventArgs e) { //Adds the default behavior BundleTable.Bundles.EnableDefaultBundles(); } Once the line has been added, you can now run the project and see the output. If you now see the result in Fiddler, you will see all the files inside the scripts are clubbed into a single file and the whole file gets downloaded in a single request. If you have a large number of files, the bundling will show considerable performance gain for the web page. Bundling is not the only performance gain that we have achieved using Optimization. Press F5 to run the application and try to look into the actual file that has been downloaded as js and css. You will see that the bundle has been minified already by disregarding comments, blank spaces, new lines, and so on. Hence, the size of the bundles has also been reduced physically. You can also add your custom BundleTable entries. Generally, we add them inside the Application_Start section of the Global.asax file, like so: Bundle mybundle = new Bundle("~/mycustombundle", typeof(JsMinify)); mybundle.AddFile("~/Resources/Main.js"); mybundle.AddFile("~/Resources/Sub1.js"); mybundle.AddDirectory("/Resources/Files", "*.js", false); BundleTable.Bundles.Add(mybundle); The preceding code creates a new bundle for the application that can be referenced later on. We can use AddFile to add individual files to the Bundle or we can also use AddDirectory to specify a whole directory for a particular search pattern. The last argument for AddDirectory specifies whether it needs to search for a subdirectory or not. JsMinify is the default Rule processor for the JavaScript files. Similar to JsMinify is a class called CssMinfy that acts as a default rule for CSS minification. You can reference your custom bundle directly inside your page using the following directive: <script src = "mycustombundle" type="text/javascript" /> You will notice that the directive appropriately points to the custom bundle that has been created. How it works... Bundling and minification works with the introduction of the System.Web.Optimization namespace. BundleTable is a new class inside this namespace that keeps track of all the bundles that have been created in the solution. It maintains a list of all the Bundle objects, that is, list of JavaScript or CSS files, in a key-value pair collection. Once the request for a bundle is made, HttpRuntime dynamically combines the files and/or directories associated with the bundle into a single file response. Let us consider some other types that helps in transformation. BundleResponse: This class represents the response after the resources are bundled and minified. So BundleResponse keeps track of the actual response of the combined file. IBundleTransform: This type specifies the contract for transformation. Its main idea is to provide the transformation for a particular resource. JsMinfy or CssMinify are the default implementations of IBundleTransform. Bundle: The class represents a resource bundle with a list of files or directories. The IBundleTransform type specifies the rule for producing the BundleResponse class. To implement custom rules for a bundle, we need to implement this interface. public class MyCustomTransform : IBundleTransform { public void Process(BundleResponse bundleresponse) { // write logic to Bundle and minfy… } } Here, the BundleResponse class is the actual response stream where we need to write the minified output to. Basically, the application uses the default BundleHandler class to initiate the transform. BundleHandler is an IHttpHandler that uses ProcessRequest to get the response for the request from the browser. The process is summarized as follows: HttpRuntime calls the default BundleHandler.ProcessRequest method to handle the bundling and minification request initiated by the browser. ProcessRequest gets the appropriate bundle from the BundleTable class and calls Bundle.ProcessRequest. The Bundle.ProcessRequest method first retrieves the bundle's Url and invokes Bundle.GetBundleResponse. GetBundleResponse first performs a cache lookup. If there is no cache available, it calls GenerateBundleResponse. The GenerateBundleResponse method creates an instance of BundleResponse, sets the files to be processed in correct order, and finally invokes IBundleTransform.Process. The response is then written to BundleResponse from this method and the output is thrown back to the client. The preceding flow diagram summarizes how the transformation is handled by ASP.NET. The final call to IBundleTransform returns the response back to the browser. There's more... Now let's talk about some other options, or possibly some pieces of general information that are relevant to this task. How to configure the compilation of pages in ASP.NET websites Compilation also plays a very vital role in the performance of websites. As we have already mentioned, we have background GC available to the servers with .NET 4.5 releases, which means when GC starts collecting unreferenced objects, there will be no suspension of executing threads on the server. The GC can start collecting in the background. The support of multicore JIT will increase the performance of non-JITed files as well. By default, .NET 4.5 supports multicore JIT. If you want to disable this option, you can use the following code. <system.web> <compilation profileGuidedOptimizations="None" /> </system.web> This configuration will disable the support of spreading the JIT into multiple cores. The server enables a Prefetcher technology, similar to what Windows uses, to reduce the disk read cost of paging during application startup. The Prefetcher is enabled by default, you can also disable this using the following code: <system.web> <compilation enablePrefetchOptimization ="false" /> </system.web> This settings will disable the Prefetcher technology on the ASP.NET site. You can also configure your server to directly manipulate the amount of GC: <runtime> <performanceScenario value="HighDensityWebHosting" /> The preceding configuration will make the website a high density website. This will reduce the amount of memory consumed per session. What is unobtrusive validation Validation plays a very vital role for any application that employs user input. We generally use ASP.NET data validators to specify validation for a particular control. The validation forms the basis of any input. People use validator controls available in ASP.NET (which include RequiredFieldValidator, RangeValidator, and so on) to validate the controls when either a page is submitted or when the control loses its focus or on any event the validator is associated with. Validators being most popular server-side controls that handles client-side validation by producing an inline JavaScript block inside the actual page that specifies each validator. Let us take an instance: <asp:TextBox ID="Username" runat="server"></asp:TextBox> <asp:RequiredFieldValidator ErrorMessage="Username is required!" ControlToValidate="Username" runat="server"></asp:RequiredFieldValidator> <asp:RegularExpressionValidator ErrorMessage="Username can only contain letters!" ControlToValidate="Username" ValidationExpression="^[A-Za-z]+$" runat="server"></asp:RegularExpressionValidator> The validator handles both the client-side and server-side validations. When the preceding lines are rendered in the browser, it produces a mess of inline JavaScript. .NET 4.5 uses unobtrusive validation. That means the inline JavaScript is replaced by the data attributes in the HTML. This is a normal HTML-only code and hence performs better than the inline HTML and is also very understandable, neat, and clean. You can also turn off the default behavior of the application just by adding the line in Application_Start of the Global.asax file: void Application_Start(object sender, EventArgs e) { //Disable UnobtrusiveValidation application wide ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None; } The preceding code will disable the feature for the application. Applying appSettings configuration key values Microsoft has implemented the ASP.NET web application engine in such a way that most of its configurations can be overridden by the developers while developing applications. There is a special configuration file named Machine.config that provides the default configuration of each of the config sections present for every application. web.config is specific to an application hosted on IIS. The IIS reads through the configuration of each directory to apply for the pages inside it. As configuring a web application is such a basic thing for any application, there is always a need to have a template for a specific set of configuration without rewriting the whole section inside web.config again. There are some specific requirements from the developers perspective that could be easily customizable without changing too much on the config.ASP.NET 4.5 introduces magic strings that could be used as configuration key values in the appSettings element that could give special meaning to the configuration. For instance, if you want the default built-in JavaScript encoding to encode & character, you might use the following: <appSettings> <add key="aspnet:JavaScriptDoNotEncodeAmpersand" value="false" /> </appSettings> This will ensure that & character is encoded as "u0026" which is the JavaScript-escaped form of that character. When the value is true, the default JavaScript string will not encode &. On the other hand, if you need to allow ScriptResource.axd to serve arbitrary static files other than JavaScript, you can use another magic appSettings key to handle this: <appSettings> <add key="aspnet:ScriptResourceAllowNonJsFiles" value="false" /> </appSettings> The configuration will ensure that ScriptResource.axd will not serve any file other than the .js extension even if the web page has a markup . Similar to this, you can also enable UnobtrusiveValidationMode on the website using a separate magic string on appSetting too: <appSettings> <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" /> </appSettings> This configuration will make the application to render HTML5 data-attributes for validators. There are a bunch of these appSettings key magic strings that you can use in your configuration to give special meaning to the web application. Refer to http://bit.ly/ASPNETMagicStrings for more information. DLL intern in ASP.NET servers Just like the reusability of string can be achieved using string intern tables, ASP.NET allows you to specify DLL intern that reduces the use of loading multiple DLLs into memory from different physical locations. The interning functionality introduced with ASP.NET reduces the RAM requirement and load time-even though the same DLL resides on multiple physical locations, they are loaded only once into the memory and the same memory is being shared by multiple processes. ASP.NET maintains symbolic links placed on the bin folder that map to a shared assembly. Sharing assemblies using a symbolic link requires a new tool named aspnet_intern.exe that lets you to create and manage the stored interned assemblies. To make sure that the assemblies are interned, we need to run the following code on the source directory: aspnet_inturn –mode exec –sourcedir "Temporary ASP.NET files" – interndir "c:assemblies" This code will put the shared assemblies placed inside assemblies directory interned to the temporary ASP.NET files. Thus, once a DLL is loaded into memory, it will be shared by other requests. How to work with statically-typed model binding in ASP.NET applications Binding is a concept that attaches the source with the target such that when something is modified on the source, it automatically reflects to the target. The concept of binding is not new in the .NET framework. It was there from the beginning. On the server-side controls, when we set DataSource, we generally don't expect DataSource to automatically produce the output to be rendered onto the actual HTML. We expect to call a DataBind method corresponding to the control. Something magical happens in the background that generates the actual HTML from DataSource and produces the output. DataSource expects a collection of items where each of the items produces single entry on the control. For instance, if we pass a collection as the data source of a grid, the data bind will enumerate the collection and each entry in the collection will create a row of DataGrid. To evaluate each property from within the individual element, we use DataBinder.Eval that uses reflection to evaluate the contextual property with actual data. Now we all know, DataBinder actually works on a string equivalent of the actual property, and you cannot get the error before you actually run the page. In case of model binding, the bound object generates the actual object. Model binding does have the information about the actual object for which the collection is made and can give you options such as IntelliSense or other advanced Visual Studio options to work with the item. Getting ready DataSource is a property of the Databound element that takes a collection and provides a mechanism to repeat its output replacing the contextual element of the collection with generated HTML. Each control generates HTML during the render phase of the ASP.NET page life cycle and returns the output to the client. The ASP.NET controls are built so elegantly that you can easily hook into its properties while the actual HTML is being created, and get the contextual controls that make up the HTML with the contextual data element as well. For a template control such as Repeater, each ItemTemplate property or the AlternateItemTemplate property exposes a data item in its callback when it is actually rendered. This is basically the contextual object of DataSource on the nth iteration. DataBinder.Eval is a special API that evaluates a property from any object using Reflection. It is totally a runtime evaluation and hence cannot determine any mistakes on designer during compile time. The contextual object also doesn't have any type-related information inherent inside the control. With ASP.NET 4.5, the DataBound controls expose the contextual object as generic types so that the contextual object is always strongly typed. The control exposes the ItemType property, which can also be used inside the HTML designer to specify the type of the contextual element. The object is determined automatically by the Visual Studio IDE and it produces proper IntelliSense and provides compile-time error checking on the type defined by the control. In this recipe we are going to see step by step how to create a control that is bound to a model and define the HTML using its inherent Item object. How to do it... Open Visual Studio and start an ASP.NET Web Application project. Create a class called Customer to actually implement the model. For simplicity, we are just using a class as our model: public class Customer { public string CustomerId { get; set; } public string Name { get; set; } } The Customer class has two properties, one that holds the identifier of the customer and another the name of the customer. Now let us add an ASPX file and add a Repeater control. The Repeater control has a property called ModelType that needs the actual logical path of the model class. Here we pass the customer. Once ModelType is set for the Repeater control, you can directly use the contextual object inside ItemTemplate just by specifying it with the : Item syntax: <asp:Repeater runat="server" ID="rptCustomers" ItemType="SampleBinding.Customer"> <ItemTemplate> <span><%# :Item.Name %></span> </ItemTemplate> </asp:Repeater> Here in this Repeater control we have directly accessed the Name property from the Customer class. So here if we specify a list of Customer values to its data source, it will bind the contextual objects appropriately. The ItemType property is available to all DataBound controls. The Databound controls in ASP.NET 4.5 also support CRUD operations. The controls such as Gridview, FormView, and DetailsView expose properties to specify SelectMethod, InsertMethod, UpdateMethod, or DeleteMethod. These methods allow you to pass proper methods that in turn allow you to specify DML statements. Add a new page called Details.aspx and configure it as follows: <asp:DetailsView SelectMethod="dvDepartments_GetItem" ID="dvDepartments" UpdateMethod="dvDepartments_ UpdateItem" runat="server" InsertMethod="dvDepartments_ InsertItem" DeleteMethod="dvDepartments_DeleteItem" ModelType="ModelBindingSample.ModelDepartment" AutoGenerateInsertB utton="true"> </asp:DetailsView> Here in the preceding code, you can see that I have specified all the DML methods. The code behind will have all the methods and you need to properly specify the methods for each operation. How it works... Every collection control loops through the Datasource control and renders the output. The Bindable controls support collection to be passed to it, so that it can make a template of itself by individually running the same code over and over again with a contextual object passed for an index. The contextual element is present during the phase of rendering the HTML. ASP.NET 4.5 comes with the feature that allows you to define the type of an individual item of the collection such that the template forces this conversion, and the contextual item is made available to the template. In other words, what we have been doing with Eval before, can now be done easily using the Item contextual object, which is of same type as we define in the ItemType property. The designer enumerates properties into an IntelliSense menu just like a C# code window to write code easier. Each databound control in ASP.NET 4.5 allows CRUD operations. For every CRUD operation there is a specific event handler that can be configured to handle operations defined inside the control. You should remember that after each of these operations, the control actually calls DataBind again so that the data gets refreshed. There's more... ModelBinding is not the only thing that is important. Let us discuss some of the other important concepts deemed fit to this category. ModelBinding with filter operations ModelBinding in ASP.NET 4.5 has been enhanced pretty much to support most of the operations that we regularly need with our ASP.NET pages. Among the interesting features is the support of filters in selection of control. Let us use DetailsView to introduce this feature: <asp:DropDownList ID="ddlDepartmentNames" runat="server" ItemType="ModelBindingSample.ModelDepartment" AutoPostBack="true" DataValueField="DepartmentId" DataTextField="DepartmentName" SelectMethod="GetDepartments"> </asp:DropDownList> <asp:DetailsView SelectMethod="dvDepartments_GetItems" ID="dvDepartments" UpdateMethod="dvDepartments_UpdateItem" runat="server" InsertMethod="dvDepartments_InsertItem" DeleteMethod="dvDepartments_DeleteItem" ItemType="ModelBindingSample.ModelCustomer" AutoGenerateIn sertButton="true"> </asp:DetailsView> Here you can see the DropDownList control calls Getdepartments to generate the list of departments available. The DetailsView control on the other hand uses the ModelCustomer class to generate the customer list. SelectMethod allows you to bind the control with the data. Now to get the filter out of SelectMethod we use the following code: public IQueryable<ModelCustomer> dvDepartments_GetItems([Control("ddlD epartmentNames")]string deptid) { // get customers for a specific id } This method will be automatically called when the drop-down list changes its value. The departmentid of the selected DropDownItem control is automatically passed into the method and the result is bound to DetailsView automatically. Remember, the dvDepartments_GetItems method always passes a Nullable parameter. So, if departmentid is declared as integer, it would have been passed as int? rather than int. The attribute on the argument specifies the control, which defines the value for the query element. You need to pass IEnumerable (IQueryable in our case) of the items to be bound to the control. You can also specify a filter using Querystring. You can use the following code: public IQueryable<Customer> GetCustomers([QueryString]string departmentid) { return null; }   This code will take departmentid from the query string and load the DataBound control instead of the control specified within the page. Introduction to HTML5 and CSS3 in ASP.NET applications Web is the media that runs over the Internet. It's a service that has already has us in its grasp. Literally, if you think of the Web, the first thing that can come into your mind is everything about HTML, CSS, and JavaScript. The browsers are the user agents that are used to communicate with the Web. The Web has been there for almost a decade and is used mostly to serve information about business, communities, social networks, and virtually everything that you can think of. For such a long period of time, users primarily use websites to see text-based content with minimum UI experiences and texts that can easily be consumed by search engines. In those websites, all that the browsers do is send a request for a page and the server serves the client with the appropriate page which is later rendered on the browser. But with the introduction to modern HTMLs, websites are gradually adopting interactivity in terms of CSS, AJAX, iFrame, or are even using sandboxed applications with the use of Silverlight, Flash, and so on. Silverlight and Adobe AIR (Flash) are specifically likely to be used when the requirement is great interactivity and rich clients. They totally look like desktop applications and interact with the user as much as they can. But the problems with a sandboxed application are that they are very slow and need every browser to install the appropriate plugin before they can actually navigate to the application. They are heavyweight and are not rendered by the browser engine. Even though they are so popular these days, most of the development still employs the traditional approach of HTML and CSS. Most businesses cannot afford the long loading waits or even as we move along to the lines of devices, most of these do not support them. The long term user requirements made it important to take the traditional HTML and CSS further, ornamenting it in such a way that these ongoing requirements could easily be solved using traditional code. The popularity of the ASP.NET technology also points to the popularity of HTML. Even though we are dealing with server-side controls (in case of ASP.NET applications), internally everything renders HTML to the browser. HTML5, which was introduced by W3C and drafted in June 2004, is going to be standardized in 2014 making most of the things that need desktop or sandboxed plugins easily carried out using HTML, CSS, and JavaScript. The long term requirement to have offline web, data storage, hardware access, or even working with graphics and multimedia is easily possible with the help of the HTML5 technology. So basically what we had to rely on (the sandbox browser plugins) is now going to be standardized. In this recipe, we are going to cover some of the interesting HTML5 features that need special attention. Getting ready HTML5 does not need the installation of any special SDK to be used. Most of the current browsers already support HTML5 and all the new browsers are going to support most of these features. The official logo of HTML5 has been considered as follows. HTML5 has introduced a lot of new advanced features but yet it also tries to simplify things that we commonly don't need to know but often need to remember in order to write code. For instance, the DocType element of an HTML5 document has been simplified to the following one line: <!DOCTYPE html> So, for an HTML5 document, the document type that specifies the page is simply HTML. Similar to DocType, the character set for the page is also defined in very simple terms. <meta charset="utf-8" /> The character set can be of any type. Here we specified the document to be UTF – 8. You do not need to specify the http-equiv attribute or content to define charset for the page in an HTML5 document according to the specification. Let us now jot down some of the interesting HTML5 items that we are going to take on in this recipe. Semantic tags, better markups, descriptive link relations, micro-data elements, new form types and field types, CSS enhancements and JavaScript enhancements. Not all browsers presently support every feature defined in HTML5. There are Modernizr scripts that can help as cross-browser polyfills for all browsers. You can read more information about it here. How to do it... The HTML5 syntax has been adorned with a lot of important tags which include header, nav, aside, figure, and footer syntaxes that help in defining better semantic meaning of the document: <body> <header> <hgroup> <h1>Page title</h1> <h2>Page subtitle</h2> </hgroup> </header> <nav> <ul> Specify navigation </ul> </nav> <section> <article> <header> <h1>Title</h1> </header> <section> Content for the section </section> </article> <article> <aside> Releated links </aside> <figure> <img src = "logo.jpg"/> <figcaption>Special HTML5 Logo</figcaption> </figure> <footer> Copyright © <time datetime="2010-11-08">2010</time>. </footer> </body> By reading the document, it clearly identifies the semantic meaning of the document. The header tag specifies the header information about the page. The nav tag defines the navigation panel. The Section tag is defined by articles and besides them, there are links. The img tag is adorned with the Figure tag and finally, the footer information is defined under the footer tag. A diagrammatic representation of the layout is shown as follows. The vocabulary of the page that has been previously defined by div and CSS classes are now maintained by the HTML itself and the whole document forms a meaning to the reader. HTML5 not only improves the semantic meaning of the document, it also adds new markup. For instance, take a look at the following code: <input list="options" type="text"/> <datalist id="options"> <option value="Abhishek"/> <option value="Abhijit"/> <option value="Abhik"/> </datalist> datalist specifies the autocomplete list for a control. A datalist item automatically pops up a menu while we type inside a textbox. The input tag specifies the list for autocomplete using the list attribute. Now if you start typing on the textbox, it specifies a list of items automatically. <details> <summary>HTML 5</summary> This is a sliding panel that comes when the HTML5 header is clicked </details> The preceding markup specifies a sliding panel container. We used to specify these using JavaScript, but now HTML5 comes with controls that handle these panels automatically. HTML5 comes with a progress bar. It supports the progress and meter tags that define the progress bar inside an HTML document: <meter min="0" max="100" low="40" high="90" optimum="100" value="91">A+</meter> <progress value="75" max="100">3/4 complete</progress> The progress shows 75 percent filled in and the meter shows a value of 91. HTML5 added a whole lot of new attributes to specify aria attributes and microdata for a block. For instance, consider the following code: <div itemscope itemtype="http://example.org/band"> <ul id="tv" role="tree" tabindex="0" aria-labelledby="node1"> <li role="treeitem" tabindex="-1" aria-expanded="true">Inside Node1</li> </li> </ul> Here, Itemscope defines the microdata and ul defines a tree with aria attributes. These data are helpful for different analyzers or even for automated tools or search engines about the document. There are new Form types that have been introduced with HTML5: <input type="email" value="some@email.com" /> <input type="date" min="2010-08-14" max="2011-08-14" value="2010-08-14"/> <input type="range" min="0" max="50" value="10" /> <input type="search" results="10" placeholder="Search..." /> <input type="tel" placeholder="(555) 555-5555" pattern="^(?d{3})?[-s]d{3}[-s]d{4}.*?$" /> <input type="color" placeholder="e.g. #bbbbbb" /> <input type="number" step="1" min="-5" max="10" value="0" /> These inputs types give a special meaning to the form. The preceding figure shows how the new controls are laid out when placed inside a HTML document. The controls are email, date, range, search, tel, color, and number respectively. HTML5 supports vector drawing over the document. We can use a canvas to draw 2D as well as 3D graphics over the HTML document: <script> var canvasContext = document.getElementById("canvas"). getContext("2d"); canvasContext.fillRect(250, 25, 150, 100); canvasContext.beginPath(); canvasContext.arc(450, 110, 100, Math.PI * 1/2, Math.PI * 3/2); canvasContext.lineWidth = 15; canvasContext.lineCap = 'round'; canvasContext.strokeStyle = 'rgba(255, 127, 0, 0.5)'; canvasContext.stroke(); </script> Consider the following diagram. The preceding code creates an arc on the canvas and a rectangle filled with the color black as shown in the diagram. The canvas gives us the options to draw any shape within it using simple JavaScript. As the world is moving towards multimedia, HTML5 introduces audio and video tags that allow us to run audio and video inside the browser. We do not need any third-party library or plugin to run audio or video inside a browser: <audio id="audio" src = "sound.mp3" controls></audio> <video id="video" src = "movie.webm" autoplay controls></video> The audio tag runs the audio and the video tag runs the video inside the browser. When controls are specified, the player provides superior browser controls to the user. With CSS3 on the way, CSS has been improved greatly to enhance the HTML document styles. For instance, CSS constructs such as .row:nth-child(even) gives the programmer control to deal with a particular set of items on the document and the programmer gains more granular programmatic approach using CSS. How it works... HTML5 is the standardization to the web environments with W3C standards. The HTML5 specifications are still in the draft stage (a 900-page specification available at http://www.w3.org/html/wg/drafts/html/master/), but most modern browsers have already started supporting the features mentioned in the specifications. The standardization is due in 2014 and by then all browsers need to support HTML5 constructs. Moreover, with the evolution of smart devices, mobile browsers are also getting support for HTML5 syntaxes. Most smart devices such as Android, iPhone, or Windows Phone now support HTML5 browsers and the HTML that runs over big devices can still show the content on those small browsers. HTML5 improves the richness of the web applications and hence most people have already started shifting their websites to the future of the Web. There's more... HTML5 has introduced a lot of new enhancements which cannot be completed using one single recipe. Let us look into some more enhancements of HTML5, which are important to know. How to work with web workers in HTML5 Web workers are one of the most awaited features of the entire HTML5 specification. Generally, if we think of the current environment, it is actually turning towards multicore machines. Today, it's verbal that every computer has at least two cores installed in their machine. Browsers are well capable of producing multiple threads that can run in parallel in different cores. But programmatically, we cannot have the flexibility in JavaScript to run parallel tasks in different cores yet. Previously, developers used setTimeout, setInterval, or XMLHttprequst to actually create non-blocking calls. But these are not truly a concurrency. I mean, if you still put a long loop inside setTimeout, it will still hang the UI. Actually these works asynchronously take some of the UI threads time slices but they do not actually spawn a new thread to run the code. As the world is moving towards client-side, rich user interfaces, we are prone to develop codes that are capable of computation on the client side itself. So going through the line, it is important that the browsers support multiple cores to be used up while executing a JavaScript. Web workers are actually a JavaScript type that enable you to create multiple cores and run your JavaScript in a separate thread altogether, and communicate the UI thread using messages in a similar way as we do for other languages. Let's look into the code to see how it works. var worker = new Worker('task.js'); worker.onmessage = function(event) { alert(event.data); }; worker.postMessage('data'); Here we will load task.js from Worker.Worker is a type that invokes the code inside a JavaScript in a new thread. The start of the thread is called using postMessage on the worker type. Now we have already added a callback to the event onmessage such that when the JavaScript inside task.js invokes postMessage, this message is received by this callback. Inside task.js we wrote. self.onmessage = function(event) { // Do some CPU intensive work. self.postMessage("recv'd: " + event.data); }; Here after some CPU-intensive work, we use self.postMessage to send the data we received from the UI thread and the onmessage event handler gets executed with message received data. Working with Socket using HTML5 HTML5 supports full-duplex bidirectional sockets that run over the Web. The browsers are capable of invoking socket requests directly using HTML5. The important thing that you should note with sockets is that it sends only the data without the overload of HTTP headers and other HTTP elements that are associated with any requests. The bandwidth using sockets is dramatically reduced. To use sockets from the browsers, a new protocol has been specified by W3C as a part of the HTML5 specification. WebSocket is a new protocol that supports two-way communication between the client and the server in a single TCP channel. To start socket server, we are going to use node.js for server side. Install node.js on the server side using the installer available at http://nodejs.org/dist/v0.6.6/node-v0.6.6.msi. Once you have installed node.js, start a server implementation of the socket. var io = require('socket.io'); //Creates a HTTP Server var socket = io.listen(8124); //Bind the Connection Event //This is called during connection socket.sockets.on('connection',function(socket){ //This will be fired when data is received from client socket.on('message', function(msg){ console.log('Received from client ',msg); }); //Emit a message to client socket.emit('greet',{hello: 'world'}); //This will fire when the client has disconnected socket.on('disconnect', function(){ console.log('Server has disconnected'); }); }); In the preceding code, the server implementation has been made. The require('socket.io') code snippet specifies the include module header. socket.io provides all the APIs from node.js that are useful for socket implementation. The Connection event is fired on the server when any client connects with the server. We have used to listen at the port 8124 in the server. socket.emit specifies the emit statement or the response from the server when any message is received by it. Here during the greet event, we pass a JSON object to the client which has a property hello. And finally, the disconnect event is called when the client disconnects the socket. Now to run this client implementation, we need to create a HTML file. <html> <title>WebSocket Client Demo</title> <script src = "http://localhost:8124/socket.io/socket.io.js"></ script> <script> //Create a socket and connect to the server var socket = io.connect('http://localhost:8124/'); socket.on("connect",function(){ alert("Client has connected to the server"); }); socket.on('greet', function (data) { alert(data.hello); } ); </script </html> Here we connect the server at 8124 port. The connect event is invoked first. We call an alert method when the client connects to the server. Finally, we also use the greet event to pass data from the server to the client. Here, if we run both the server and the client, we will see two alerts; one when the connection is made and the other alert to greet. The greet message passes a JSON object that greets with world. The URL for the socket from the browser looks like so. [scheme] '://' [host] '/' [namespace] '/' [protocol version] '/' [transport id] '/' [session id] '/' ( '?' [query] ) Here, we see. Scheme: This can bear values such as http or https (for web sockets, the browser changes it to ws:// after the connection is established, it's an upgrade request) host: This is the host name of the socket server namespace: This is the Socket.IO namespace, the default being socket.io protocol version: The client support default is 1 transport id: This is for the different supported transports which includes WebSockets, xhr-polling, and so on session id: This is the web socket session's unique session ID for the client Getting GeoLocation from the browser using HTML5 As we are getting inclined more and more towards devices, browsers are trying to do their best to actually implement features to suit these needs. HTML5 introduces GeoLocation APIs to the browser that enable you to get the location of your position directly using JavaScript. In spite of it being very much primitive, browsers are capable of detecting the actual location of the user using either Wi-Fi, satellite, or other external sources if available. As a programmer, you just need to call the location API and everything is handled automatically by the browser. As geolocation bears sensitive information, it is important to ask the user for permission. Let's look at the following code. if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { var latLng = "{" + position.coords.latitude + "," + position.coords. longitude + "with accuracy: " + position.coords.accuracy; alert(latLng); }, errorHandler); } Here in the code we first detect whether the geolocation API is available to the current browser. If it is available, we can use getCurrentPosition to get the location of the current device and the accuracy of the position as well. We can also use navigator.geolocation.watchPosition to continue watching the device location at an interval when the device is moving from one place to another.   Resources for Article: Further resources on this subject: Planning for a successful integration .NET 4.5 Extension Methods on IQueryable Core .NET Recipes
Read more
  • 0
  • 1
  • 4760

article-image-voice-menus-and-ivr-asterisknow
Packt
16 Oct 2009
3 min read
Save for later

Voice Menus and IVR in AsteriskNOW

Packt
16 Oct 2009
3 min read
Four Rules of IVR IVR systems can be hell to use; the main reason for this is that people designing IVR systems tend to complicate their functionality beyond the normal usage scope of a human being. The following four rules will enable you to implement a usable, humanly accessible, and maintainable IVR. Rule 1—Keep it narrow: Your IVR should be kept as simple as possible. Make sure that each of your steps in the IVR environment is not longer than five options. Most IVR users aren't able to remember all the options of an IVR system, when presented with a multitude of IVR options. Rule 2—Keep it shallow: Your IVR system's depth is in direct relation to the complexity of the IVR application. If your application has more than four levels, you need to revise your IVR plan. Most people (including yours truly) become extremely aggravated when confronted with an IVR system that is asking for too much information. Rule 3—Enable escape routes: Always give your IVR user the ability to break out of the IVR flow and talk to a live person. Some people simply can't handle the usage of an IVR system. Rule 4—If it works, don't fix it!: For some reason, companies tend to change their IVR flows every other day to support a new business model. An IVR system that constantly changes is a nightmare for users, as they never get used to the options of the system. If you must perform an update, make sure that your update doesn't affect that system in such a way that the users need to re-learn the system. Voice Menus—AsteriskNOW's IVR Generator AsteriskNOW provides a highly simplistic IVR generator, rightfully named—Voice Menus. The main usage of an IVR in a PBX is the implementation of an "Auto Attendant". Some PBX systems refer to auto-attendant and IVR as two different things. In AsteriskNOW, they are one and the same. At this point, click the Voice Menus link, located on your left-hand main menu. The following should appear on your screen: This interface enables editing, creation, or deletion of voice menus. Each menu is built from a set of operational directives (Steps) and functional keys (Keypress Events). Each voice menu also receives a mandatory name (Name), a form of logical entity description, and an Extension number (optional). The extension number enables PBX extensions or external users to dial into the specific voice menu indicated by the extension number. Voice Menu Steps—The Voice Menu Flow Steps are performed one after the other, in the order they appear on the screen. There are seventeen possible steps, available through the AsteriskNOW GUI. Once a step had been selected, the GUI will change, indicating the requirement for additional fields to be filled. The seventeen available steps are as follows:
Read more
  • 0
  • 0
  • 4754
article-image-advanced-shiny-functions
Packt
08 Jan 2016
14 min read
Save for later

Advanced Shiny Functions

Packt
08 Jan 2016
14 min read
In this article by Chris Beeley, author of the book, Web Application Development with R using Shiny - Second Edition, we are going to extend our toolkit by learning about advanced Shiny functions. These allow you to take control of the fine details of your application, including the interface, reactivity, data, and graphics. We will cover the following topics: Learn how to show and hide parts of the interface Change the interface reactively Finely control reactivity, so functions and outputs run at the appropriate time Use URLs and reactive Shiny functions to populate and alter the selections within an interface Upload and download data to and from a Shiny application Produce beautiful tables with the DataTables jQuery library (For more resources related to this topic, see here.) Summary of the application We're going to add a lot of new functionality to the application, and it won't be possible to explain every piece of code before we encounter it. Several of the new functions depend on at least one other function, which means that you will see some of the functions for the first time, whereas a different function is being introduced. It's important, therefore, that you concentrate on whichever function is being explained and wait until later in the article to understand the whole piece of code. In order to help you understand what the code does as you go along it is worth quickly reviewing the actual functionality of the application now. In terms of the functionality, which has been added to the application, it is now possible to select not only the network domain from which browser hits originate but also the country of origin. The draw map function now features a button in the UI, which prevents the application from updating the map each time new data is selected, the map is redrawn only when the button is pushed. This is to prevent minor updates to the data from wasting processor time before the user has finished making their final data selection. A Download report button has been added, which sends some of the output as a static file to a new webpage for the user to print or download. An animated graph of trend has been added; this will be explained in detail in the relevant section. Finally, a table of data has been added, which summarizes mean values of each of the selectable data summaries across the different countries of origin. Downloading data from RGoogleAnalytics The code is given and briefly summarized to give you a feeling for how to use it in the following section. Note that my username and password have been replaced with XXXX; you can get your own user details from the Google Analytics website. Also, note that this code is not included on the GitHub because it requires the username and password to be present in order for it to work: library(RGoogleAnalytics) ### Generate the oauth_token object oauth_token <- Auth(client.id = "xxxx", client.secret = "xxxx") # Save the token object for future sessions save(oauth_token, file = "oauth_token") Once you have your client.id and client.secret from the Google Analytics website, the preceding code will direct you to a browser to authenticate the application and save the authorization within oauth_token. This can be loaded in future sessions to save from reauthenticating each time as follows: # Load the token object and validate for new run load("oauth_token") ValidateToken(oauth_token) The preceding code will load the token in subsequent sessions. The validateToken() function is necessary each time because the authorization will expire after a time this function will renew the authentication: ## list of metrics and dimensions query.list <- Init(start.date = "2013-01-01", end.date = as.character(Sys.Date()), dimensions = "ga:country,ga:latitude,ga:longitude, ga:networkDomain,ga:date", metrics = "ga:users,ga:newUsers,ga:sessions, ga:bounceRate,ga:sessionDuration", max.results = 10000, table.id = "ga:71364313") gadf = GetReportData(QueryBuilder(query.list), token = oauth_token, paginate_query = FALSE) Finally, the metrics and dimensions of interest (for more on metrics and dimensions, see the documentation of the Google Analytics API online) are placed within a list and downloaded with the GetReportData() function as follows: ...[data tidying functions]... save(gadf, file = "gadf.Rdata") The data tidying that is carried out at the end is omitted here for brevity, as you can see at the end the data is saved as gadf.Rdata ready to load within the application. Animation Animation is surprisingly easy. The sliderInput() function, which gives an HTML widget that allows the selection of a number along a line, has an optional animation function that will increment a variable by a set amount every time a specified unit of time elapses. This allows you to very easily produce a graphic that animates. In the following example, we are going to look at the monthly graph and plot a linear trend line through the first 20% of the data (0–20% of the data). Then, we are going to increment the percentage value that selects the portion of the data by 5% and plot a linear through that portion of data (5–25% of the data). Then, increment again from 10% to 30% and plot another line and so on. There is a static image in the following screenshot: The slider input is set up as follows, with an ID, label, minimum value, maximum value, initial value, step between values, and the animation options, giving the delay in milliseconds and whether the animation should loop: sliderInput("animation", "Trend over time", min = 0, max = 80, value = 0, step = 5, animate = animationOptions(interval = 1000, loop = TRUE) ) Having set this up, the animated graph code is pretty simple, looking very much like the monthly graph data except with the linear smooth based on a subset of the data instead of the whole dataset. The graph is set up as before and then a subset of the data is produced on which the linear smooth can be based: groupByDate <- group_by(passData(), YearMonth, networkDomain) %>% summarise(meanSession = mean(sessionDuration, na.rm = TRUE), users = sum(users), newUsers = sum(newUsers), sessions = sum(sessions)) groupByDate$Date <- as.Date(paste0(groupByDate$YearMonth, "01"), format = "%Y%m%d") smoothData <- groupByDate[groupByDate$Date %in% quantile(groupByDate$Date, input$animation / 100, type = 1): quantile(groupByDate$Date, (input$animation + 20) / 100, type = 1), ] We won't get too distracted by this code, but essentially, it tests to see which of the whole date range falls in a range defined by percentage quantiles based on the sliderInput() values. See ?quantile for more information. Finally, the linear smooth is drawn with an extra data argument to tell ggplot2 to base the line only on the smaller smoothData object and not the whole range: ggplot(groupByDate, aes_string(x = "Date", y = input$outputRequired, group = "networkDomain", colour = "networkDomain") ) + geom_line() + geom_smooth(data = smoothData, method = "lm", colour = "black" ) Not bad for a few lines of code. We have both ggplot2 and Shiny to thank for how easy this is. Streamline the UI by hiding elements This is a simple function that you are certainly going to need if you build even a moderately complex application. Those of you who have been doing extra credit exercises and/or experimenting with your own applications will probably have already wished for this or, indeed, have already found it. conditionalPanel() allows you to show/hide UI elements based on other selections within the UI. The function takes a condition (in JavaScript, but the form and syntax will be familiar from many languages) and a UI element and displays the UI only when the condition is true. This has actually used a couple of times in the advanced GA application, and indeed in all the applications, I've ever written of even moderate complexity. We're going to show the option to smooth the trend graph only when the trend graph tab is displayed, and we're going to show the controls for the animated graph only when the animated graph tab is displayed. Naming tabPanel elements In order to allow testing for which tab is currently selected, we're going to have to first give the tabs of the tabbed output names. This is done as follows (with the new code in bold): tabsetPanel(id = "theTabs", # give tabsetPanel a name tabPanel("Summary", textOutput("textDisplay"), value = "summary"), tabPanel("Trend", plotOutput("trend"), value = "trend"), tabPanel("Animated", plotOutput("animated"), value = "animated"), tabPanel("Map", plotOutput("ggplotMap"), value = "map"), tabPanel("Table", DT::dataTableOutput("countryTable"), value = "table") As you can see, the whole panel is given an ID (theTabs) and then each tabPanel is also given a name (summary, trend, animated, map, and table). They are referred to in the server.R file very simply as input$theTabs. Finally, we can make our changes to ui.R to remove parts of the UI based on tab selection: conditionalPanel( condition = "input.theTabs == 'trend'", checkboxInput("smooth", label = "Add smoother?", # add smoother value = FALSE) ), conditionalPanel( condition = "input.theTabs == 'animated'", sliderInput("animation", "Trend over time", min = 0, max = 80, value = 0, step = 5, animate = animationOptions(interval = 1000, loop = TRUE) ) ) As you can see, the condition appears very R/Shiny-like, except with the . operator familiar to JavaScript users in place of $. This is a very simple but powerful way of making sure that your UI is not cluttered with an irrelevant material. Beautiful tables with DataTable The latest version of Shiny has added support to draw tables using the wonderful DataTables jQuery library. This will enable your users to search and sort through large tables very easily. To see DataTable in action, visit the homepage at http://datatables.net/. The version in this application summarizes the values of different variables across the different countries from which browser hits originate and looks as follows: The package can be installed using install.packages("DT") and needs to be loaded in the preamble to the server.R file with library(DT). Once this is done using the package is quite straightforward. There are two functions: one in server.R (renderDataTable) and other in ui.R (dataTableOutput). They are used as following: ### server. R output$countryTable <- DT::renderDataTable ({ groupCountry <- group_by(passData(), country) groupByCountry <- summarise(groupCountry, meanSession = mean(sessionDuration), users = log(sum(users)), sessions = log(sum(sessions)) ) datatable(groupByCountry) }) ### ui.R tabPanel("Table", DT::dataTableOutput("countryTable"), value = "table") Anything that returns a dataframe or a matrix can be used within renderDataTable(). Note that as of Shiny V. 0.12, the Shiny functions renderDataTable() and dataTableOutput() functions are deprecated: you should use the DT equivalents of the same name, as in the preceding code adding DT:: before each function name specifies that the function should be drawn from that package. Reactive user interfaces Another trick you will definitely want up your sleeve at some point is a reactive user interface. This enables you to change your UI (for example, the number or content of radio buttons) based on reactive functions. For example, consider an application that I wrote related to survey responses across a broad range of health services in different areas. The services are related to each other in quite a complex hierarchy, and over time, different areas and services respond (or cease to exist, or merge, or change their name), which means that for each time period the user might be interested in, there would be a totally different set of areas and services. The only sensible solution to this problem is to have the user tell you which area and date range they are interested in and then give them back the correct list of services that have survey responses within that area and date range. The example we're going to look at is a little simpler than this, just to keep from getting bogged down in too much detail, but the principle is exactly the same, and you should not find this idea too difficult to adapt to your own UI. We are going to allow users to constrain their data by the country of origin of the browser hit. Although we could design the UI by simply taking all the countries that exist in the entire dataset and placing them all in a combo box to be selected, it is a lot cleaner to only allow the user to select from the countries that are actually present within the particular date range they have selected. This has the added advantage of preventing the user from selecting any countries of origin, which do not have any browser hits within the currently selected dataset. In order to do this, we are going to create a reactive user interface, that is, one that changes based on data values that come about from user input. Reactive user interface example – server.R When you are making a reactive user interface, the big difference is that instead of writing your UI definition in your ui.R file, you place it in server.R and wrap it in renderUI(). Then, point to it from your ui.R file. Let's have a look at the relevant bit of the server.R file: output$reactCountries <- renderUI({ countryList = unique(as.character(passData()$country)) selectInput("theCountries", "Choose country", countryList) }) The first line takes the reactive dataset that contains only the data between the dates selected by the user and gives all the unique values of countries within it. The second line is a widget type we have not used yet, which generates a combo box. The usual id and label arguments are given, followed by the values that the combo box can take. This is taken from the variable defined in the first line. Reactive user interface example – ui.R The ui.R file merely needs to point to the reactive definition, as shown in the following line of code (just add it in to the list of widgets within sidebarPanel()): uiOutput("reactCountries") You can now point to the value of the widget in the usual way as input$subDomains. Note that you do not use the name as defined in the call to renderUI(), that is, reactCountries, but rather the name as defined within it, that is, theCountries. Progress bars It is quite common within Shiny applications and in analytics generally to have computations or data fetches that take a long time. However, even using all these tools, it will sometimes be necessary for the user to wait some time before their output is returned. In cases like this, it is a good practice to do two things: first, to inform that the server is processing the request and has not simply crashed or otherwise failed, and second to give the user some idea of how much time has elapsed since they requested the output and how much time they have remaining to wait. This is achieved very simply in Shiny using the withProgress() function. This function defaults to measuring progress on a scale from 0 to 1 and produces a loading bar at the top of the application with the information from the message and detail arguments of the loading function. You can see in the following code, the withProgress function is used to wrap a function (in this case, the function that draws the map), with message and detail arguments describing what is happened and an initial value of 0 (value = 0, that is, no progress yet): withProgress(message = 'Please wait', detail = 'Drawing map...', value = 0, { ... function code... } ) As the code is stepped through, the value of progress can steadily be increased from 0 to 1 (for example, in a for() loop) using the following code: incProgress(1/3) The third time this is called, the value of progress will be 1, which indicates that the function has completed (although other values of progress can be selected where necessary, see ?withProgess()). To summarize, the finished code looks as follows: withProgress(message = 'Please wait', detail = 'Drawing map...', value = 0, { ... function code... incProgress(1/3) .. . function code... incProgress(1/3) ... function code... incProgress(1/3) } ) It's very simple. Again, have a look at the application to see it in action. Summary In this article, you have now seen most of the functionality within Shiny. It's a relatively small but powerful toolbox with which you can build a vast array of useful and intuitive applications with comparatively little effort. In this respect, ggplot2 is rather a good companion for Shiny because it too offers you a fairly limited selection of functions with which knowledgeable users can very quickly build many different graphical outputs. Resources for Article: Further resources on this subject: Introducing R, RStudio, and Shiny[article] Introducing Bayesian Inference[article] R ─ Classification and Regression Trees[article]
Read more
  • 0
  • 0
  • 4752

article-image-jsf2-composite-component-primefaces
Packt
31 Jul 2013
9 min read
Save for later

JSF2 composite component with PrimeFaces

Packt
31 Jul 2013
9 min read
(For more resources related to this topic, see here.) The Contacts tab is where users can connect with their friends, family, and colleagues and chat online. For this screen let's write a JSF2 composite component that can render any list of User objects for desktop and mobile browsers. In preceding screenshot, we use a JSF2 composite component to render groups of contacts for the user. When a contact has signed in, his or her avatar image is highlighted to show presence. Clicking on a contact opens a live chat dialog that showcases the PrimeFaces Push technology. We enable our JSF2 composite component to be integrated in a mobile UI based on PrimeFaces Mobile. In this mode, our component renders a simpler, mobile-friendly UI with some special CSS and JavaScript to leverage the PrimeFaces Mobile API. Our contactList composite component has three attributes: header: Specifies the text to be displayed above the contacts value: Binds the component to any list of Userobjects mobile: Set to true for mobile display mode We can use our <mycompany:contactList> tag to display a list of friends, family, and colleagues. Notice that we use the PrimeFaces poll component to check every 10 seconds to see if one of our contacts has logged in. <h:form id="contactsForm"><p:poll update="contactsPanel" interval="10" />...<p:accordionPanel id="contactsPanel" multiple="true"><p:tab title="Friends"><mycompany:contactList header="Friends" value="#{contactsController.friends}" /></p:tab>...</p:accordionPanel></h:form> Let's see how we developed this component. First we declared the composite component's interface: <composite:interface><composite:attribute name="value" required="true" /><composite:attribute name="header" required="false" default="People" /><composite:attribute name="mobile" required="false" default="false" /></composite:interface> Next, we implement the composite component using the PrimeFaces carousel component for desktop, and the simpler PrimeFaces dataList component for mobile. Notice that we use the boolean mobile attribute declared in our component interface in our rendering logic by using the #{cc.attrs.mobile} EL expression. If the mobile attribute is true, we render the mobile UI, otherwise we show the desktop UI. <composite:implementation><p:carousel style="width:100%" value="#{cc.attrs.value}" var="person" numVisible="4" rendered="#{not empty cc.attrs.value and not cc.attrs.mobile}" itemStyleClass="person-item"><f:facet name="header"><h:outputText value="#{cc.attrs.header}" /></f:facet><h:panelGrid columns="1" style="width:100%"><p:commandLink value="Chat" onclick="chatDialogWidget.show()" update=":chatForm:chatPanel" actionListener="#{chatController.beginChat}" disabled="#{!userController.isUserPresent(person)}" /><h:outputText value="#{person.firstName}" /><p:graphicImage value="#{resource['images:user-icon.png']}" width="75" rendered="#{userController.isUserPresent(person)}" /><p:graphicImage value="#{resource['images:offline-user- icon.png']}"width="75" rendered="#{!userController.isUserPresent(person)}" /></h:panelGrid><f:facet name="footer"><h:outputText value="Total: #{cc.attrs.value.size()}" /></f:facet></p:carousel><!-- Mobile UI --><p:dataList style="width:110%" value="#{cc.attrs.value}" var="person" id="mobileContactList" rendered="#{not empty cc.attrs.value and cc.attrs.mobile}" itemStyleClass="mobile-person-item"><f:attribute name="filter" value="true" /><h:panelGroup rendered="#{userController.isUserPresent(person)}"><h:outputLink value="#chat" onclick="beginMobileChat()"><p:graphicImage value="#{resource['images:user-icon.png']}" width="50" style="text-align:left; vertical-align:middle; margin-top:15px" /><h:outputText value="#{person.firstName}" style="display:block; margin-top:18px; font-size:0.9em" /></h:outputLink></h:panelGroup><h:panelGroup rendered="#{!userController.isUserPresent(person)}"><p:graphicImage value="#{resource['images:offline-user- icon.png']}" width="50" style="text-align:left; vertical-align:middle; margin-top:15px" /><h:outputText value="#{person.firstName}" style="display:block; margin-top:18px; font-size:0.9em" /></h:panelGroup></p:dataList></composite:implementation> Chat feature with PrimeFaces Push One of the most interesting features of PrimeFaces is the Prime Push API. Designed by Atmosphere Framework creator Jean-François Arcand, the Prime Push API supports asynchronous communication from the web server to the web browser on desktop or mobile using various transports such as WebSocket and Comet. Prime Push technology opens up a whole new set of possibilities for web developers. We will implement a simple chat feature for our web application based on Prime Push. What is WebSocket? WebSocket is a standardized, full-duplex communication protocol based on TCP that can be used to establish a persistent, bidirectional communication channel between a web browser and a web server. WebSocket has better performance than Comet techniques such as long polling and HTTP streaming, and is well supported by modern browsers and application servers. WebSocket support can be enabled in GlassFish 3 with a simple command: $GLASSFISH_HOME/bin/asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-1.http.websockets-support-enabled=true Once WebSocket support is enabled in GlassFish, we are ready to use Prime Push in our web application. Chat room Before we can see the power of Prime Push in action, we need to implement a chat room feature in our application. The PrimeFaces showcase application includes a chat room example, so we have adapted it for our purposes and integrated it into our application. One of the coolest things about PrimeFaces is the ability to push updates to desktop and mobile users at the same time from the server using PrimeFaces Mobile and Prime Push technologies. The previous screenshot shows a live chat session in our web application between a mobile and desktop user. Getting started with Prime Push The first step in using Prime Push is configuring the Prime Push servlet in web.xml: <servlet><servlet-name>PushServlet</servlet-name><servlet-class>org.primefaces.push.PushServlet</servlet-cla<init-param><param-name>org.primefaces.push.rules</param-name><param-value>com.mycompany.websocket.DefaultPushRule</paramvalue></init-param> ...<load-on-startup>1</load-on-startup><async-supported>true</async-supported></servlet><servlet-mapping><servlet-name>PushServlet</servlet-name><url-pattern>/primepush/*</url-pattern></servlet-mapping> An important point about this configuration is the use of a custom push rule implemented in the com.mycompany.websocket.DefaultPushRule class. This class provides some GlassFish-specific support that was necessary to ensure Prime Push worked properly on GlassFish. Opening a WebSocket communication channel The next step in using Prime Push is to establish the WebSocket communication channel between the web page and the web server. In our application, when the user clicks on the Chat link on the contact screen, we call the following method in our ChatController using Ajax to begin the chat: public void beginChat() { User user = userController.getUser(); RequestContext requestContext = RequestContext.getCurrentInstance(); // ... requestContext.execute("socketWidget.connect( '/" + user.getUsername() + "')"); pushContext.push(CHANNEL + "*", user.getUsername() + " joined the channel.");} Notice that we use the very cool PrimeFaces RequestContext API to invoke some JavaScript in the browser when the response is completed. We can do a lot more with the RequestContext API, such as update a DOM element, scroll to a component, and execute arbitrary JavaScript. Definitely check it out. Here we call connect() to tell the browser to listen for messages on the WebSocket communication channel. Use of a PrimeFaces socket component The PrimeFaces socket component establishes a WebSocket connection with the PushServlet running in our web application. Here it uses a communication channel named /chat for sending and receiving Push messages. p:socket onMessage="handleMessage" channel="/chat" autoConnect="false" widgetVar="socketWidget" /><script type="text/javascript"> //<![CDATA[function handleMessage(data) {// append chat messages to output panel var chatContent = $(PrimeFaces.escapeClientId('chatForm:chatPanel'));chatContent.append(data + '<br />');//keep scrollchatContent.scrollTop(chatContent.height()); } //]]></script> When a chat message is received, our handleMessage() JavaScript function is called and the chat message is appended to the chat content panel. Implementation of the chat room dialog for desktop web browsers To provide a chat room user interface for desktop users, we implemented the following modal dialog using the PrimeFaces dialog component. It renders the list of active users on our website. <p:dialog header="Chat" modal="true" showEffect="fade" hideEffect="fade" widgetVar="chatDialogWidget" width="700" position="center" appendToBody="false" height="400" draggable="true" resizable="false"id="chatDialog"> ...<p:outputPanel id="chatPanel" layout="block" styleClass="ui-corner-all ui-widget-content chatlogs"/><p:dataList id="users" var="user" value="#{activeUsers}" styleClass="usersList"><f:facet name="header"> Users</f:facet> #{user.username}</p:dataList> Next, we need to provide an input field for users to enter a chat message. <p:inputText value="#{chatController.globalMessage}" styleClass="messageInput" style="width:300px" /><p:spacer width="5" /><p:commandButton value="Send" actionListener="#{chatController.sendGlobal}" oncomplete="$('.messageInput').val('').focus()"/> ... <p:commandButton value="Close" style="margin-top:20px" actionListener="#{chatController.endChat}" onclick="chatDialogWidget.hide()" global="false" /> When the user clicks on the Send button, the chat message text is submitted using Ajax and our ChatController.sendGlobal() method is invoked to push the message to the WebSocket channel. private static final String CHANNEL = "/chat/";public void sendGlobal() { String username = getLoggedInUser().getUsername(); pushContext.push(CHANNEL + "*", username + ": " + globalMessage);} On the client side, the browser will receive the message over the WebSocket channel and our handleMessage() JavaScript function will append the text to the chat panel. Summary This article helped you understand JSF2 composite component with PrimeFaces and chat feature with PrimeFaces Push. It also helped you understand about opening a WebSocket communication channel, use of PrimeFaces socket component, and implementation of chat rooms for web browsers. Resources for Article: Further resources on this subject: Integrating Images with JSF, CSS with JSF and, JS with JSF [Article] Apache MyFaces Extensions Validator [Article] Getting Started with PrimeFaces [Article]
Read more
  • 0
  • 0
  • 4752
Modal Close icon
Modal Close icon