Tuesday, September 7, 2010

MS Pivot

Recently I had this opportunity to work with a radically new tool called MS Pivot or simply Pivot. I know many of you may be thinking what is this stuff called pivot? Is it something to do with the Pivot table? No it has nothing to do with pivot table, rather it is a new technology from the Microsoft’ live lab.

What is Pivot?

I would say Pivot is new way of searching information on the net. Till now we use to search information based on text. With Pivot one can search information based on images and text.Using the various features of Pivot one cab narrow down the search based on various filters as well. Pivot is a new technology to look at the vast amount of information scattered around us. It is a pictorial plus textual representation of information in graph and other format which make more sense to a human being than large chunks of textual data. The information can be anything which one can dream of. There is no limit to what you can display as a Pivot content as long as you have images and data for it. To display content in pivot one has to convert the data into a format which is understandable by Pivot. The format which Pivot understand is in the form of an XML and the format of that XML is called CXML. CXML stands for “CollectionXML”. The images which are rendered by the Pivot control needs to be converted into a format called “Deep Zoom Format”. Now you may be saying “Oh! no two new formats needs to be learnt?”. Don’t worry these two, CXML and Deep Zoom Format, are not difficult. “Deep Zoom Format” is the same technology used in “Seadragon”. In “Deep Zoom Format” the image is converted to a pyramid of images i.e. the original image is converted to very minute image, increasing in size to the original image. This is done to help the Pivot control to seamlessly zoom the image. To know more about the “Deep Zoom Format” please refer the following site.

http://www.seadragon.com

Since pivot is all about pictorial representation I would like you to have a look at the below video and get amazed.

Get Microsoft Silverlight

What is CXML?

As specified above CXML stands for “Collection XML”. It is the format which defines what should be displayed by pivot. Now let us understand what constitutes a CXML. As it is with any XML the content of a CXML is enclosed in a root element called “Collection”. The “Collection” root node has a “Name” attribute the value of which is displayed as title in the title bar of pivot control. “Icon” and “BrandImage” are the few other attributes for displaying icon and brand image related to the collection.

<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns:p="http://schemas.microsoft.com/livelabs/pivot/collection/2009" 
SchemaVersion="1.0" Name="First excel collection images" p:AdditionalSearchText="Ms-Pivot" 
xmlns="http://schemas.microsoft.com/collection/metadata/2009">
  <FacetCategories>
    <FacetCategory Name="Living Being" Type="String"></FacetCategory>    
    <FacetCategory Name="Others" Type="String"></FacetCategory>    
    <FacetCategory Name="Count" Type="Number"></FacetCategory>    
    <FacetCategory Name="Link" Type="Link"></FacetCategory>
  </FacetCategories>
  <Items ImgBase="First_Excel_Collection_files\tgpdq4lj.ano.xml">
    <Item Id="0" Img="#0" Name="Owl">
      <Description>The image is that of an owl. Owl is a nocturnal bird.</Description>
      <Facets>
        <Facet Name="Living Being">
          <String Value="Bird"></String>          
        </Facet>        
        <Facet Name="Link">
            <Link Name="Link" Href="http://www.google.com"/>
        </Facet>
      </Facets>
    </Item>
    <Item Id="1" Img="#1" Name="Headphone">
      <Description>Philips headphone.</Description>
      <Facets>        
        <Facet Name="Others">
          <String Value="Gadget"/>
        </Facet>
        <Facet Name="Count">
            <Number Value="2"/>
        </Facet>
        <Facet Name="Link Test">
            <Link Name="Link test2" Href="about:none"/>
        </Facet>
      </Facets>
    </Item>
  </Items>
</Collections>

FacetCategories & FacetCategory

Next in hierarchy is the “FacetCategories” node which is nothing but a collection of “FacetCategory” nodes. “FacetCategories” as such don’t have any attributes. “FacteCategories” have “FacetCategory” as their child nodes. “FacetCategory” is nothing but a classification of you collection data into different categories. All “FacetCategory” is displayed in the Pivot filter panel on the left hand side of the Pivot control. I would say they serve as group heading and under each “FacetCategories” you have sub classification which is nothing but “Facet”. Following are the attributes of FacetCategory.

Name: Name to be given to the FacetCategory. The name is displayed in the filter panel on the left.

Format: Format attribute takes .NET numeric format strings as their value.

Type: Data type of the FacetCategory. The data types supported are string, long string, numeric, DateTime and link.

Items & Item

Next in hierarchy is Items node. Again from the name one can make it out that it acts as a collection for Item node. It has got only one attribute called ImgBase to specify relative path to a DZC (Deep Zoom Collection) or XML file which contains the collection’ image details.

Item node holds each item which is displayed in the main window of the pivot control. Item node can have a Description node and a Facets node. Following are the attributes in a Item node.

Img: Hold the uri of the image. Normally Img attribute has a “#” symbol followed by a number. This number corresponds to the Id attribute in the DZC or XML file specified in the ImgBase attribute of the Items node. To understand better lets see the typical content of DZC or XML file mentioned in the ImgBase attribute of the Items node.


<?xml version="1.0" encoding="utf-8"?>
<Collection MaxLevel="7" TileSize="256" Format="jpg" NextItemId="8" ServerFormat="Default" xmlns="http://schemas.microsoft.com/deepzoom/2009">
  <Items>
    <I Id="0" N="0" Source="images/53794121.GreatHornedOwlCloseUp.xml">
      <Size Width="800" Height="554" />
    </I>
    <I Id="1" N="1" Source="images/Commercial-product-photography-of-headphones.xml">
      <Size Width="950" Height="485" />
    </I>
    <I Id="2" N="2" Source="images/GreatCrestedGrebe20.xml">
      <Size Width="800" Height="566" />
    </I>
    <I Id="3" N="3" Source="images/great-northern-diver-dsg.xml">
      <Size Width="700" Height="500" />
    </I>    
  </Items>
</Collection>

You can see from the above DZC or XML file content that it uses numbers starting from 0 to whatever the max number as the Id attribute. Whatever is mentioned in the Img attribute of the Item node relates to the Id attribute in this DZC file. The logic is that the XML file url mentioned in the Source attribute will hold some image related attributes and there will be a folder with the same name as that of the XML file mentioned in the Source attribute. The folder with the same name as that of the XML file mentioned in the Source attribute will hold all the images for the particular Item. Huff explaining this simple logic is really a pain. Anyways lets see the content of the XML file mentioned in the Source attribute.


<?xml version="1.0" encoding="utf-8"?>
<Image TileSize="254" Overlap="1" Format="jpg" ServerFormat="Default" 
xmlns="http://schemas.microsoft.com/deepzoom/2009">
   <Size Width="800" Height="554" />
</Image>

The above XML contents details about the images like its format, TileSize, Width etc. The other attributes of the item node are as follows.

Id: Next attribute in the Item node is Id which gives an unique ID to the item in the Items collection.

Href: Href attribute will have a url clicking on which the user will navigated to the url. The url can be anything which gives more info about the product.

Name: The name of the item. Name attribute will be displayed in the info panel on the right side of the pivot control.

Description node

The Description node is child node in the Item node. The Description node has an explanation about the node and this description gets displayed in the info panel just below the header name in the info panel.

Facets

The next child node in the CXML is the Facets node. The node is just a collection container which contains one or more Facet node.

Facet

Facet node is the child element of the Facets node in a Item node. The Facet node has only one attribute called Name. Name provided in this attribute should match the Name attribute of the FacetCategory node. Facet node acts as a container for defining the various properties of the FacetCategory of an item. You can think Facet as container which defines the sub categories of the FacetCategory to which the Item belongs. An Item can belong to more than one FacetCategory. The Facet can have only any of the following as child elements.

  • String: Can contain a string value for the Facet node.
  • LongString: The value provided in the value string will not be displayed in the filter panel. LongString value will be displayed on the info panel on the right side of the pivot control. LongString is used to display long descriptions about the item in the info panel.
  • Number: Used to provide number value for the item. If number type is used one will get a slider in the filter panel to drag and filter between the numbers values defined.
  • DateTime: Needs to be used to provide DateTime value.
  • Link: The Link node has two attributes namely Name and Href. Href takes a URL or “about:none” text as the value. Name can be used to provide name to the Link node.

That’s about the CXML. There are other nodes as well but just for the beginning this will serve the purpose.

To create Deep Zoom Images one can make use Deep Zoom Composer or Deep Zoom Tools command line utilities. Deep Zoom Composer is a Graphical User Interface (GUI) for creating DZCs where as Deep Zoom Tools command line utilities are part of the Deep Zoom tools library which can be freely downloaded. It consists of two executable name DZConvert.exe to convert image files into DZI formats and DZCollection.exe to convert DZI to DZC. Now developers will ask how they can programmatically convert images to DZI and DZC formats. Developers can make use of the DeepZoomTools.dll to convert images to the required format.

Whenever you have search requirement where you want to give a different experience to the end user with the help of images then go ahead and download Pivot control for Silverlight and convert your data to CXML and there you go. Silverlight PivotViewer can be downloaded from here.

Wednesday, May 5, 2010

Calling web service using javascript. Part -3

In the part 1 of this blog we saw how to invoke web service methods using pure javascript and in part 2 we made use of web service behavior to invoke web methods. The previous two blogs were not dependent on server technologies used by the user but this blog will have that constraint because we will have a look at how to invoke web methods using “ScriptManager”. “ScriptManager” is an ASP.NET server side control which is key to AJAX functionality in ASP.NET. Without any further delay let’ see our first web method invocation using “ScriptManager”. For this blog we will making use of the same web service as we have used in our previous two blogs. Below is the code for the first web service method we are going to invoke.

namespace ScriptManagerService
{
    //The attribute which makes the web service callable from script.
    [System.Web.Script.Services.ScriptService]
    public class TestService : System.Web.Services.WebService
    {
        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }
    }
}

The above web service code is pretty straight forward. We have a simple “HelloWorld” method which returns a string. What makes this web service special is the “[System.Web.Script.Services.ScriptService]” attribute added on top of the “TestService” web service class. The attribute makes the web service callable from JavaScript. Also when the proxy classes are generated the attribute generates JavaScript object corresponding to the web service class. Once the web service is created now we need to create our web page to invoke the web method. Create a new aspx page and add a “ScriptManager” control to it. Sample aspx page with the “ScriptManager” tag is added below.

<body>
<script language="javascript" type="text/javascript">
function invokeSimpleWebMethod()
{
    ScriptManagerService.TestService.HelloWorld(handleResult);    
} 
 
function handleResult(result)
{
    alert(result);
}
</script>
   <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="scrMgr" runat="server">
            <Services>
                <asp:ServiceReference Path="TestService.asmx" />                
            </Services>
        </asp:ScriptManager>
        <asp:Button ID="btnHW" runat="server" Text="Hello World" OnClientClick="invokeSimpleWebMethod();" />
    </div>
    </form> 
</body>

In the above code we can see that we have a “ScriptManager” server control added. And inside the “Services” tag we have added reference to our local web service using the “ServiceReference” tag. The path attribute of the “ServiceReference” tag has the url of the web service which needs to be invoked. You can add multiple web services by adding additional “ServiceReference” tags. What ASP.NET does here is that it generates JavaScript proxy classes for each of the web services mentioned in the “ServiceReference” tag. All the auto generated JavaScript proxy classes derive from “Sys.Net.WebServiceProxy”.

Also we have an ASP.NET Button server control which calls a “invokeSimpleWebMethod” javascript method on its “OnClientClick” event. In the “invokeSimpleWebMethod” javascript method we have made use of the namespace (in which the web service is defined) followed by the web service name and finally the method name which needs to be invoked. Behind the scene ASP.NET has done the extra work of registering the namespace and creating the proxy classes and also adding the methods defined inside the web service into a proxy JavaScript class. If you notice the “HelloWorld” method takes an argument. The argument is nothing but the name of the JavaScript function which needs to be invoked when the web service method has been successfully executed and results are returned to the browser. You can also pass the name of the function which needs to be invoked when the web service method invocation request fails. We will see the same shortly. The “handleResult” JavaScript method gets called when the asynchronous request is successfully returned. The method gracefully displays the result in an alert message box.

That’ about how to use the “ScriptManager” server control to invoke a web service methods i.e. namespace followed by class name followed by the method name. One thing to note is that “ScriptManager” control can only be used to call web services in the same domain. Now lets see how to pass parameters to web methods.

Passing parameters to web method

We will use the following web method to see how we can pass parameters by using “ScriptManager”.

[WebMethod]
public string CombineName(string firstName, string midleName, string lastName)
{
      return string.Concat(string.Concat(firstName, " - ", midleName), " - ", lastName);
}

The above method is pretty straight and it is the same method which I have used in my previous blog. The method takes three string arguments and concatenates them and returns them as a single string. Now lets see how we can pass the three parameters from JavaScript.

Below is the JavaScript method which invokes the web method with the three string parameters.

function webMethodWithParams()
{    
    ScriptManagerService.TestService.CombineName("Sandeep", " ", "P.R", handleResult, handleError);
}

In the above JavaScript function we are invoking the “CombineName” method the same way we invoked the “HelloWorld” web method. But the difference here is that instead of the callback function as the first argument we are passing the arguments first, followed by the success callback function name and then the failure callback function. The funda behind is simple, if your web method accepted three parameters pass them first in the same order as defined in the web method followed by the callback methods. Similarly if the web method takes different number of parameters then make sure that, that many number of parameters are passed first followed by the success callback function. Success callback and error callback functions are optional. Our “handleError” javascript function looks something like this.
function handleError(error)
{
    alert(error.get_message());
}

The above “handleError” javascript function is pretty straight forward. It takes an error object as one of the argument. The error object passed by the system has various methods and properties to retrieve the details of the exception happened on the server side. Some of the methods and properties are as follows.

  1. get_exceptionType method or _exceptionType field/property can be used to get the type of exception raised by the server like “System.Exception”.
  2. get_message method or _message field/property can be used to get the error message returned by the server.
  3. _stackTrace field/property or get_stackTrace method can be used to get the stack trace of the error from the server.
  4. get_statusCode method or _statusCode field/property can be used to retrieve the HTML status code returned from the server.

The error object which is passed to the “handleError” JavaScript function is of type “Sys.Net.WebServiceError”. “Sys.Net.WebServiceError” is a simple class with the above explained methods or fields/properties.

Now the next step is to pass complex objects from JavaScript to a web method. Lets see how that can be accomplished.

Passing complex objects

Let see the code of the web method which accepts a complex object and processes it.

[WebMethod]
public string GetCar(Car car)
{
    return "Model: " + car.Model + ", Color: " + car.Color; //", Cubic capacity: ";//+ car.CC + 
}

The above web method doesn’t have rocket science in it, it just takes a complex object of type “Car” and concatenates the properties and returns it as a string. Now lets the “Car” class. Its same as that we have used in our previous examples.

public class Car
{
    public string Model
    {   get; set; }          
 
    public string Color
    { get; set; }
 
    public Engine CarEngine
    { get; set; }
}
 
public class Engine
{
    public int CC
    { get; set; }
    public int Cylinders
    { get; set; }
}

The “Car” class has three properties namely “Model”, “Color” and “CarEngine”. “Model” and “Color” are of type string and “CarEngine” is again a complex object of type “Engine”. The “Engine” class has two properties of type int namely “CC” and “Cylinders”. The above “Car” class is the one which we will be passing to the web method from within JavaScript using ScripManager. The code is pasted below.

function sendComplexObject()
{
    //Create a new Object and assign the same properties as those in the Car class.
    var car = new Object();
    car.Model = "Ferrari California"
    car.Color = "Ferrari Red"
    car.CarEngine = new Object()
    car.CarEngine.CC = 4500
    car.CarEngine.Cylinders = 12
    //Execute the web method.
    ScriptManagerService.TestService.GetCar(car, handleResult, handleError);
}

In the “sendComplexObject” method we are first creating a “Car” object by creating an object of type “Object”. Then to that object we are adding all the properties that the “Car” class has. Since JavaScript is a dynamic language you can add all the properties by just giving the name and the value. As the “Car” class has another complex object, Engine, as one of its property named “CarEngine” we are also creating the complex engine object also the same way. Once we have created the object we are finally executing the web method in the final line of code. Isn’t simple to pass complex objects from JavaScript to server. To help us to do write such a simple code the ScriptManager does the extra work converting the JavaScript objects to server objects.

Below is the JSON way of creating the complex Car object.

function sendComplexObject()
{
    //Create an object of type "ScriptManagerService.Car" and pass all the properties 
    //as a javascript string array.
    var car = new ScriptManagerService.Car({"Model" : "Ferrari California", "Color" : "Ferrari Red", "CarEngine" : {"CC" : "100", "Cylinders" : "5"}})
    //Invoke the web method.
    ScriptManagerService.TestService.GetCar(car, handleResult, handleError);
}

In the above code we are trying to create a “ScriptManagerService.Car” object. This is possible because the ScriptManager generates the Proxy classes automatically for us. Now lets see handling a complex type returned from the server. It also is quite simple.

Handling a complex object returned by the server

Lets see the web service which returns the complex object.

[WebMethod]
public Car GetCarObject()
{
    return new Car
    {
        Model = "Ferrari",
        Color = "Ferrari Red",
        CarEngine = new Engine { CC = 2500, Cylinders = 8 },
        test = "test"
    };
}

The above web method does the hard work of creating a car object and returning the same. We are going to invoke the above web method using the ScriptManager and use the very complex object in JavaScript. The JavaScript code is pasted below.

function receiveUseComplexObject()
{
    //Invoking the web method that returns complex object.
    ScriptManagerService.TestService.GetCarObject(handleResult, handleError);
}
 
//Modified handleResult function
function handleResult(result)
{
    //Using the complex object returned by the web method in JavaScript.
    var carDef = "Model: " + result.Model + ", Color: " + result.Color + ", Engine-CC: " + result.CarEngine.CC;
    carDef += ", Engine-Cylinders: " + result.CarEngine.Cylinders;
    alert(carDef);
}

In the “receiveUseComplexObject” we are not doing any drastic than invoking the “GetCarObject” web method. The main work is done by the modified “handleResult” function. The web method returns a “Car” object, the parameter of the “handleResult” also is the JavaScript proxy “Car” object representing the server object. The ScriptManager does all the work of converting the returned object as a JSON “Car” object. This is why we are able to use the properties of the “Car” object as we would do in a normal OOPS programming language.

Calling methods in a page

Using “ScriptManager” one can access method of a web page as well. One catch here is that you can execute only static page methods. To call a page method from JavaScript by making use of “ScriptManger” you need to add the “WebMethod” attribute to the method you want to call. Lets see “.cs” file of a web page.

public partial class TestPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {    }
 
    [System.Web.Services.WebMethod]
    public static string HelloWorld()
    {
        return "Hello world";
    }        
}

As mentioned above, we have added the “WebMethod” attribute to a static method and that’ it you need to do to make a page method callable by “ScriptManager”. In “ScriptManager” you need to set “EnablePageMethods” property to “true”. What this property does is it generates a “PageMethods” JavaScript class which has the necessary code to call all the static page methods which are decorated by the “WebMethod” attribute. Lets see the ASPX page and the JavaScript.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebSerCalServiceMngr.aspx.cs" Inherits="WebServiceUsingJS.WebSerCalServiceMngr" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
<script language="javascript" type="text/javascript">
function callPageMethods()
{
    PageMethods.HelloWorld(handleResult);
}
</script>
 
<form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="scrMgr" runat="server" EnablePageMethods="true">   
        </asp:ScriptManager>
<asp:Button ID="Button3" runat="server" Text="Call page method." OnClientClick="callPageMethods();" />
    </div>
    </form>
</body>
</html>

In the above code we have set “EnablePageMethods” property to true and on the click of a button we are calling “callPageMethods()” JavaScript function. Inside the “callPageMethods” JavaScript function we are making use of “PageMethods” proxy class to execute our page method. So with “ScriptManager” doing all the extra work at the back, as a developer we are having great time.


Try to know more


Sandeep.