3 tips if you want to use crystal report. Net 2010:


1. Crystal Reports .NET is no longer included with Visual Studio .NET 2010. it is a separate download. Use this link to download it to your application and install it after you have installed Visual Studio .NET 2010.

http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_13_0_1.exe

2. You will find that the Crystal Reports viewer is strangely missing from the Visual Studio toolbox. To fix this go to Project > Properties > Compile > Advanced Compiler Settings > Target framework(all configurations) > .NET

Framework 4. Set the Target Framework to be .NET Framework 4. After doing so, you application will close and re-open and the viewer will now be in the toolbox.

3. The Crystal Reports DLLs were written with .NET Framework 2 and they are compatible with Framework 4 as wel. But your application needs to have mixed-mode compatibility turned on for it to use the Crystal assemblies. To fix

this go to Solution Explorer > app.config.  You should add this property to the Startup tag in the app.config file.

useLegacyV2RuntimeActivationPolicy=”true”

Detail as follows:
….

<startup useLegacyV2RuntimeActivationPolicy=”true”><supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.0″/></startup></configuration>

Biography of BillGates


William H. Gates
Chairman
Microsoft CorporationWilliam (Bill) H. Gates III

William (Bill) H. Gates is chairman of Microsoft Corporation, the worldwide leader in software, services and solutions that help people and businesses realize their full potential. Microsoft had revenues of US$39.79 billion for the fiscal year ending June 2005, and employs more than 61,000 people in 102 countries and regions.

On June 15, 2006, Microsoft announced that effective July 2008 Gates will transition out of a day-to-day role in the company to spend more time on his global health and education work at the Bill & Melinda Gates Foundation. After July 2008 Gates will continue to serve as Microsoft’s chairman and an advisor on key development projects. The two-year transition process is to ensure that there is a smooth and orderly transfer of Gates’ daily responsibilities. Effective June 2006, Ray Ozzie has assumed Gates’ previous title as chief software architect and is working side by side with Gates on all technical architecture and product oversight responsibilities at Microsoft. Craig Mundie has assumed the new title of chief research and strategy officer at Microsoft and is working closely with Gates to assume his responsibility for the company’s research and incubation efforts.

Born on Oct. 28, 1955, Gates grew up in Seattle with his two sisters. Their father, William H. Gates II, is a Seattle attorney. Their late mother, Mary Gates, was a schoolteacher, University of Washington regent, and chairwoman of United Way International.

Gates attended public elementary school and the private Lakeside School. There, he discovered his interest in software and began programming computers at age 13.

In 1973, Gates entered Harvard University as a freshman, where he lived down the hall from Steve Ballmer, now Microsoft’s chief executive officer. While at Harvard, Gates developed a version of the programming language BASIC for the first microcomputer – the MITS Altair.

In his junior year, Gates left Harvard to devote his energies to Microsoft, a company he had begun in 1975 with his childhood friend Paul Allen. Guided by a belief that the computer would be a valuable tool on every office desktop and in every home, they began developing software for personal computers. Gates’ foresight and his vision for personal computing have been central to the success of Microsoft and the software industry.

Under Gates’ leadership, Microsoft’s mission has been to continually advance and improve software technology, and to make it easier, more cost-effective and more enjoyable for people to use computers. The company is committed to a long-term view, reflected in its investment of approximately $6.2 billion on research and development in the 2005 fiscal year.

In 1999, Gates wrote Business @ the Speed of Thought, a book that shows how computer technology can solve business problems in fundamentally new ways. The book was published in 25 languages and is available in more than 60 countries. Business @ the Speed of Thought has received wide critical acclaim, and was listed on the best-seller lists of the New York TimesUSA Today, the Wall Street Journal and Amazon.com. Gates’ previous book, The Road Ahead, published in 1995, held the No. 1 spot on the New York Times‘ bestseller list for seven weeks.
In addition to his love of computers and software, Gates founded Corbis, which is developing one of the world’s largest resources of visual information – a comprehensive digital archive of art and photography from public and private collections around the globe. He is also a member of the board of directors of Berkshire Hathaway Inc., which invests in companies engaged in diverse business activities.Gates has donated the proceeds of both books to non-profit organizations that support the use of technology in education and skills development.

Philanthropy is also important to Gates. He and his wife, Melinda, have endowed a foundation with more than $28.8 billion (as of January 2005) to support philanthropic initiatives in the areas of global health and learning, with the hope that in the 21st century, advances in these critical areas will be available for all people. The Bill and Melinda Gates Foundation has committed more than $3.6 billion to organizations working in global health; more than $2 billion to improve learning opportunities, including the Gates Library Initiative to bring computers, Internet Access and training to public libraries in low-income communities in the United States and Canada; more than $477 million to community projects in the Pacific Northwest; and more than $488 million to special projects and annual giving campaigns.

Gates was married on Jan. 1, 1994, to Melinda French Gates. They have three children. Gates is an avid reader, and enjoys playing golf and bridge.

Javascript Differences in Mozilla Firefox and Internet Explorer


document.all

Internet Explorer 4 introduced the document.all DOM (document object model) to allow access to the various parts of the web page. Soon after that the standard DOM method getElementById was introduced and is therefore available in all version 5+ browsers. This means that the document.all references are only needed to support IE4.

document.all doesn’t work  mozilla why?

Some proprietary document objects such as document.all and document.layers are not part of the W3C DOM and are not supported in Mozilla. (There is partial undetectable support for document.all, though, in newer versions of Mozilla. However, that functionality only exists for compatibility with sites authored specifically for IE. You should not rely on Mozilla’s document.all support on new pages.) The method document.getElementById()can be used instead.

In the Standards mode Mozilla does not generate implicit top-level JavaScript variable bindings for elements with the id or name attribute. The correct way to access an element by id is to call the document.getElementById()method with the id as a string as the argument.

Also, old client sniffers can shut out new browsers. The point of having a common API (the W3C DOM) is interoperability, and checking for a particular browser defeats that purpose. When working with the DOM, it is better to check for the existence of the methods and objects you are planning on using. For example, the existence ofdocument.getElementById() can be checked as follows:

if(document.getElementById) {
/* code that uses document.getElementById() */
}

1. Window/Body OnLoad

When dealing with a site that uses Master Pages, you lose some control, including the ability to declare a page specific event handler. There are ways around this, and I found that the following code example works pretty well.

<script language=”javascript” type=”text/javascript” for=”window” event=”onload“>
if (document.all)
{
initialize();
}
else
{
window.document.addEventListener(“DOMContentLoaded”, initialize, true);
}
</script>

2. Get Control Inner Text

Retrieving the text of an element is done by using element.innerText in Internet Explorer and element.textContentin Mozilla Firefox.

function getText(control)
{
if (document.all)
{
return control.innerText;
}
else
{
return control.textContent;
}
}

function setText(control, value)
{
if (document.all)
{
control.innerText = value;
}
else
{
control.textContent = value;
}
}

3. Element Height and Width

To retrieve an element’s height and width, use element.currentStyle for Internet Explorer and element.style forMozilla Firefox.

if (document.all)
{
top += parseValue(element.currentStyle.borderTopWidth);

}
else
{
top += parseValue(element.style.borderTopWidth);

}

4. Source Elements

To get a reference to the element that fired an event within an event handler, use event.srcElement for Internet Explorer and event.target for Mozilla Firefox.

function getSourceElement(event)
{
if (document.all)
{
return event.srcElement;
}
else
{
return event.target;
}
}

5. Firing Events

You can call fireEvent on an element in Internet Explorer, but it’s more complicated in Mozilla Firefox, requiring an event to be instantiated, initialized, and dispatched.

function fireClickEvent(control)
{
if (document.all)
{
control.fireEvent(“onclick”);
}
else
{
var clickEvent = window.document.createEvent(“MouseEvent“);
clickEvent.initEvent(“click“, false, true);
control.dispatchEvent(clickEvent);
}
}

6. Window Height and Width

Internet Explorer exposes the visible content area dimensions using document.body.offsetHeight anddocument.body.offsetWidth, whereas Mozilla Firefox uses document.body.offsetWidth and window.innerWidth.

function getWindowHeight()
{
if (document.all)
{
return document.body.offsetHeight;
}
else
{
return window.innerHeight;
}
}

function getWindowWidth()
{
if (document.all)
{
return document.body.offsetWidth;
}
else
{
return window.innerWidth;
}
}

7. Why doesn’t Mozilla display my alt tooltips?

Contrary to a popular belief stemming from the behavior of a couple browsers running on the Windows platform,alt isn’t an abbreviation for ‘tooltip’ but for ‘alternative’. The value of the alt attribute is a textual replacement for the image and is displayed when the image isn’t.

Mozilla doesn’t display the alt attribute as a tooltip, because it has been observed that doing so encourages authors to misuse the attribute.

  • * When the alternative text is shown in a tooltip, some authors write bad alt texts, because they intend the text as auxiliary tooltip text and not as a replacement for the image. (‘Bad’ in the sense that the textual alternative is less useful for people who don’t see the image.)
  • * When the alternative text is shown in a tooltip, other authors don’t want to supply textual alternatives at all, because they don’t want tooltips to appear. (Again, making things harder for people who don’t see the image.)

There is another attribute that Mozilla shows as a tooltip: title. In fact, the HTML 4.01 specification suggests that the title attribute may be displayed as a tooltip. However, this particular display method is not required and some other browsers show the title attribute in the browser status bar, for example.

At this point some people feel compelled to post a “But IE…” rant in the newsgroups or in Bugzilla. Please note that Mac IE 5 behaves in the same way as Mozilla when it comes to the alt and title attributes. Windows IE also shows the title attribute in a tooltip.

8. Does Mozilla support downloadable fonts?

Downloadable fonts are not supported.

Downloadable fonts are usually used on sites using writing systems for which proper support has been missing in browsers in the past. These sites (for example some Indian sites) code the text in Latin gibberish and then use a font that to the browser and operating system seems to be a Latin font but has eg. Devanagari glyphs, so that when the Latin gibberish is rendered with the font it seems to a human reader to be intelligible text in some language.

Obviously, that kind of ad hockery falls apart when Unicode-savvy browsers come along and render Latin gibberish as Latin gibberish (since that’s what is coded in the file from the Unicode point of view). Instead of providing support for downloadable fonts, Mozilla is addressing the real issue: support for various Unicode ranges.

However, there are still bugs related to support for Indic scripts on some platforms. For example, on Mac OS X Mozilla does not use the Devanagari font that comes with the system but can use a third-party font like TITUS Cyberbit.

lot of work has been put into Mozilla’s Unicode support. Supporting downloadable fonts in a cross-platform way would also be a lot of work and would potentially require navigating past a bunch of patents but the rewards would be small. For the purpose of rendering non-ISO-8859-1 characters Mozilla already provides Unicode support that, in the long run, is a lot better approach than using pseudo-Latin downloadable fonts separately on each site.

9. In Mozilla Firefox my style sheet doesn’t work! Why?

Here’s the check list:

  • 1. Does the HTML document validate? Styling misnested markup may cause strange effects.
    • * The <link> and <style> elements should be inside the <head> element.
  • 2. Does the CSS style sheet pass the syntax check? The CSS error handling rules require erroneous parts to be ignored rather than fixed by guessing.
    • * Lengths other than zero should be followed by a proper unit without a space between the number and the unit (eg. 1.2em).
    • * The character to use between the property name and the value is the colon—not the equal sign.
    • * HTML markup, such as <style>, does not belong in .css files.
    • * font-face is not a real CSS property. The property is font-family and @font-face is an at-rule.
    • * If @import is used, it should be the first thing in a CSS file.
    • * In Mozilla 1.8a4 and later (not in Firefox 1.0) CSS parsing errors are reported to the JavaScript console.
  • 3. Is the server sending the proper Content-Type header for CSS style sheets?
  • 4. Class names and ids are case-sensitive.
  • 5. The element selectors are case-sensitive with XML.
  • 6. Style sheet processing instructions are only allowed in the prolog of XML documents. Also, they only work in XML documents—not in documents served as text/html.
  • 7. width and height do not apply to non-replaced inline elements such as (by default) <span>.
  • 8. text-align: center; centers inline content within a block. It does not (and should not) center the block box itself. A block is centered by setting its margin-left and margin-right to auto and its width to a value that makes the block narrower than its containing block.

It is also possible, although not very likely, that you are seeing a bug.

Create an EXE or Setup File in .NET Windows Application


Hi Friends!

Visual Studio 2005 Setup and deployment Projects provides to make an exe or installer file in .NET windows application is easy and rapidly.

Visual Studio provides templates for four types of deployment projects: Merge Module Project, Setup Project, Web Setup Project, and Cab Project. In addition, a Setup wizard is provided to help step you through the process of creating deployment projects. You can see the templates and the wizard in the New Project dialog box under theSetup and Deployment Projects node.

The following are guidelines for choosing the right type of deployment project for your project.

1)Merge Module Project : Packages components that might be shared by multiple applications.

2)Setup Project : Builds an installer for a Windows-based application.

3)Web Setup Project : Builds an installer for a Web application.

4)Cab Project : Creates a cabinet file for downloading to a legacy Web browser.

5)Smart Device Cab Project : Creates a Cab project to deploy device applications.

This topic demonstrates deployment using a Setup and Deployment Project.

Setup Projects

Setup projects allow you to create installers in order to distribute an application. The resulting Windows Installer (.msi) file contains the application, any dependent files, information about the application such as registry entries, and instructions for installation. When the .msi file is distributed and run on another computer, you can be assured that everything necessary for installation is included; if for any reason the installation fails (for example, the target computer does not have the required operating system version), the installation will be rolled back and the computer returned to its pre installation state.

The following steps will gives the elegant guidance to create an executable or installer file.

1, Go to file menu > click Add > new project >now “Add New Project” dialog will appear.

2.Select the “Other Project Types” and click “Setup and Deployment” projects,Choose “Setup Project”give name project name in name text box finally click OK.

3.New project appear in solution explorer,for eg., you have give the name “MyEXE” file will be displays with given name.

4.Right click the MyEXE > go View > click “File System”

5.You can see the “File System on TargetMachine”under  three folders
Application Folder
User’s Desktop
User’s Program Menu

6.Select Application Folder and right click Add>Project Output>select Primary output

7. Select User’s Desktop richt click on the second window>click create new shortcut>select output file from Application folder>change the file name from  primary output name to MyEXE

next >>

same procedure follows the user’s program menu also

8.If you want to change the Manufactures name f,just right click the project go to properties

change the properties as per you requirement

9.Finally Build the new project After successfully Build the project myEXE(Setup) will be appear in Application Debug or Release folder(depend upon the properties settings)

EXE or installer will be available on his physical path…

When you want to install  the EXE on the client machine,you should be installed .NET Framework on that machine because, Applications and controls written for the .NET Framework v2.0 requires the .NET Framework Redistributable Package version 2.0 to be installed on the computer where the application or control runs.

Simple Silverlight 4 Example Using oData and RX Extensions


Introduction

This is part II to the previous clog (http://openlightgroup.net/Blog/tabid/58/EntryId/98/OData-Simplified.aspx) where we looked at a simple ODataexample. This time, we will make a simple Silverlight application that talks to an oData service.

Note, for this tutorial, you will also need to download and install RX Extensions from: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx, and the Silverlight Toolkit from: http://silverlight.codeplex.com.

As with the last tutorial, we will not use a database, just a simple collection that we are creating programmatically. This will allow you to see just the oData parts.

First, open up the project, in Visual Studio 2010 (or higher), from the zip file at the bottom of this link.

Select Add, then New Project…

Create a new Silverlight Application.

Add a Service Reference.

Click Discover.

Create a reference called wsSampleCustomerData.

Next, add assembly references in your Silverlight project to:

  • System.CoreEx
  • System.Observable
  • System.Reactive

In the Silverlight project, delete the MainPage.xaml.

Open the project in Expression Blend 4 (or higher).

In Expression Blend, select File then New Item…

Select the UserControl with ViewModel template, and create a file called MainPage.xaml.

It will create the ViewModel pages (MainPage.xaml and MainPage.xaml.cs with a MainPageModel.cs View Model page that is already wired-up).

Create a folder called Model and a class called Model.cs.

Replace all the code with the following code:

 Collapse
using System;
using System.Linq;
using System.Collections.Generic;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;

namespace SilverlightODataSample
{
    public class Model
    {
        #region GetCustomers
        public static IObservable < IEvent < LoadCompletedEventArgs> > 
            GetCustomers(int intPage)
        {
            // Create a URI that points to the OData Service
            Uri objUri = new Uri(GetBaseAddress(), UriKind.RelativeOrAbsolute);

            // Set up oData service call
            SampleDataSource SDS = new SampleDataSource(objUri);

            // Construct a Query
            var query = (from SampleCustomerData in SDS.SampleCustomerData
                         where SampleCustomerData.CustomerNotes.Contains("3")
                         select SampleCustomerData).Skip(intPage).Take(10);

            // Set up a DataServiceCollection to hold the results
            DataServiceCollection< CustomerRecord > CustomerRecords = 
                new DataServiceCollection< CustomerRecord >();

            // Set up a Rx Observable (in a variable called observable) 
            // that will contain the results of
            // the "LoadCompleted" event that CustomerRecords will fire
            // When LoadAsync(query) is fired in the following statement
            IObservable< IEvent < LoadCompletedEventArgs> > observable =
                Observable.FromEvent< LoadCompletedEventArgs >(CustomerRecords,
                "LoadCompleted");

            // Execute the LoadAsync on CustomerRecords passing
            // the query that was constructed earlier
            CustomerRecords.LoadAsync(query);

            // Return observable
            return observable;
        }
        #endregion

        #region GetBaseAddress
        private static string GetBaseAddress()
        {
            // This gets the address of the webservice by 
            // getting the AbsoluteUri and then stripping out the 
            // name of the .xap file
            string strXapFile = @"/ClientBin/SilverlightODataSample.xap";
            string strBaseWebAddress =
                App.Current.Host.Source.AbsoluteUri.Replace(strXapFile, "");
            return string.Format(@"{0}/{1}", strBaseWebAddress, @"Service.svc");
        }
        #endregion
    }
}

Open MainPageModel.cs and replace all the code with the following code:

 Collapse
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;

namespace SilverlightODataSample
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
            // When the Control loads
            // Get the Customers
            GetCustomers();
        }

        #region GetCustomers
        private void GetCustomers()
        {
            // Call the Model to get the Customers
            // Passing in 0 to get the first page
            // Paging could easily be done here
            // You could also pass in other criteria
            Model.GetCustomers(0).Subscribe(p = >
            {
                // Check for an error in the Service
                if (p.EventArgs.Error == null)
                {
                    // loop thru each item in the
                    // DataServiceCollection< CustomerRecord >
                    // Collection
                    foreach (CustomerRecord Customer in
                        (DataServiceCollection< CustomerRecord >)p.Sender)
                    {
                        // Add to the Customer to the colCustomerRecord 
                        // Collection so the View can bind to it
                        colCustomerRecord.Add(Customer);
                    }
                }
            });

        }
        #endregion

        #region CustomerRecord
        // The View will bind to this collection and automatically be notified if 
        // The collection changes. The Designer can bind any UI element that 
        // can hold a collection
        private ObservableCollection< CustomerRecord > _colCustomerRecord
            = new ObservableCollection< CustomerRecord >();
        public ObservableCollection< CustomerRecord > colCustomerRecord
        {
            get { return _colCustomerRecord; }
            private set
            {
                if (colCustomerRecord == value)
                {
                    return;
                }

                _colCustomerRecord = value;
                this.NotifyPropertyChanged("colCustomerRecord");
            }
        }
        #endregion

        #region INotifyPropertyChanged
        // This is a supporting method to raise a notification for any
        // Element that is subscribed to a Property that implements
        // NotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

Grab a DataGrid and drop it on the design surface.

Widen it so it fills the page.

Click on the Data tab so that you see the Data Context.

Drag and drop the colCustomerRecord collection onto the DataGrid.

Build and run the project.

OData and RX extensions are pretty impressive:

  • RX extensions were used because it decouples the oData Service calls from the View Model. This allows the methods in the model to be easily called by multiple View Models.
  • We are only grabbing the first page of the results, but we could easily implement paging by passing the page number to the method.
  • We are also only creating a simple query. We could easily create a more complex query of the oData Service.

RIATasks: A Simple Silverlight CRUD Example (using View Model)


A Simple Silverlight CRUD Example

Live example: http://silverlight.adefwebserver.com/RIATasks/

Also see: Silverlight RIA Tasks 2: Dynamic View Models

img32.jpg

The reason for this tutorial, is that I have noticed my friends are getting stuck when trying to learn Silverlight. They spend a lot of time “learning about Silverlight” but have a hard time actually getting started.

I also wanted to show them how to use View Model Style programming because I believe that using View Model, you will write LESS CODE (you probably didn’t expect that one!). Don’t believe me? Let me show you…

Silverlight is different because it communicates with the website that launches it using asynchronous communication. Learning how to design applications this way can be a bit challenging.

So I created an end-to-end example, that achieves these goals:

  • Creates, Reads, Updates, and Deletes records from the database
  • Implements Forms based security
  • Implements “Granular Security” (“only allow User One to see, edit, and create their own Tasks“)
  • Implements View Model Style

View Model Style

View Model Style allows a programmer to create an application that has absolutely no UI (user interface). The programmer only creates a View Modeland a Model. A designer with no programming ability at all, is then able to start with a blank page and completely create the View (UI) in Microsoft Expression Blend 4 (or higher). If you are new to View Model Style it is suggested that you read Silverlight View Model Style : An (Overly) Simplified Explanation for an introduction.

The Application

First, let’s look at the sample application.

When you first start the application, you are “Logged Out”. You can use the drop down to log in as User One or User Two.

Click the Add button to add a new Task.

Clicking the Update button will save the Task.

  • Clicking on the Task in the list box will display the Task.
  • Clicking the Update button will save any changes
  • Clicking the Delete button will delete the Task.

Create The Application

We will now create the Application. You will need:

  • Visual Studio 2010 (or higher)
  • Expression Blend 4 (or higher)
  • SQL Server (2005 or higher)

Setting Up The Database

Create a new database called RIATasks

Create a table called Tasks, using the following script:

 Collapse
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Tasks]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Tasks](
    [TaskID] [int] IDENTITY(1,1) NOT NULL,
    [TaskName] [nvarchar](50) NOT NULL,
    [TaskDescription] [nvarchar](max) NOT NULL,
    [UserID] [int] NOT NULL,
 CONSTRAINT [PK_Tasks] PRIMARY KEY CLUSTERED 
(
    [TaskID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Tasks]') AND name = N'IX_Tasks_UserID')
CREATE NONCLUSTERED INDEX [IX_Tasks_UserID] ON [dbo].[Tasks] 
(
    [UserID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, 
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

You will also need to set security so that you will be able to connect to the database in the next step.

(If SQL server is too hard for you to set it up, you can cover similar material in: Silverlight View Model Style File Manager and View Model Style: Silverlight Video Player)

Create The Web Application Project

Open Visual Studio and select File then New Project…

Create a Silverlight Application project.

Accept the defaults and click OK.

The project will be created.

Enable Forms Authentication

We need to set-up the web application to use Forms Authentication. When the user logs in, they will create an encrypted authentication ‘token’ in their web browser, that contains their UserID. This ‘token’ will be used by the Silverlight application when making web service calls. The web service methods (created in a later step) will check this ‘token’ to enforce security.

Open the Web.config file.

Add <authentication mode=”Forms”/> to the file. Then save and close it.

Create Default Page

Create a Web Form page called Default.aspx in the RIATasks.Web project.

Open the RIATasksTestPage.aspx page and switch to Source view.

Copy everything from <!DOCTYPE to the end of the page…

… and paste it in the source for the Default.aspx page, replacing everything from <!DOCTYPE to the end of the page.

We need to convert the Div tag the Silverlight control is in, to a Panel control so that it can be programmatically hidden if the user is not logged in.

  • Replace: <div id=”silverlightControlHost”>
    • With: <asp:panel id=”silverlightControlHost” runat=”server”>
  • Replace: </div>
    • With: </asp:panel>

Now, we need to add a drop-down so a user can log in (in a real application you would use a normal Login Form).

Insert the following code in the page under the Form tag:

 Collapse
<asp:DropDownList ID="ddlUser" runat="server" AutoPostBack="True" 
onselectedindexchanged="ddlUser_SelectedIndexChanged">
<asp:ListItem Selected="True" Value="0">Logged Out</asp:ListItem>
<asp:ListItem Value="1">User One</asp:ListItem>
<asp:ListItem Value="2">User Two</asp:ListItem>
</asp:DropDownList>

Open the Default.aspx.cs file and replace ALL the code with the following code:

 Collapse
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;

namespace RIATasks.Web
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                LogOut();
            }
        }

        #region ddlUser_SelectedIndexChanged
        protected void ddlUser_SelectedIndexChanged(object sender, EventArgs e)
        {
            int intSelectedUser = Convert.ToInt32(ddlUser.SelectedValue);
            if (intSelectedUser > 0)
            {
                LogUserIntoSite(Convert.ToInt32(ddlUser.SelectedValue));
            }
            else
            {
                LogOut();
            }
        }
        #endregion

        #region LogUserIn
        private void LogUserIntoSite(int intUser)
        {
            // Log the user into the site
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
              intUser.ToString(),
              DateTime.Now,
              DateTime.Now.AddDays(30),
              false,
              "Role One",
              FormsAuthentication.FormsCookiePath);

            // Encrypt the ticket.
            string encTicket = FormsAuthentication.Encrypt(ticket);

            // Create the cookie.
            Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

            // Show the Silverlight control
            silverlightControlHost.Visible = true;
        }
        #endregion

        #region LogOut
        protected void LogOut()
        {
            FormsAuthentication.SignOut();

            // Hide the Silverlight control
            silverlightControlHost.Visible = false;
        }
        #endregion
    }
}

Right-click on the Default.aspx page and select Set As Start Page…

Hit F5 to run the project.

The project will run and open in the web browser.

You will be able to change the drop down to log in as a user.

Close the web browser.

Create the Data Layer

Add a Linq to SQL class to the RIATaks.Web site called RIATasksDB.dbml.

Note: You could use Entity Framework instead of Linq to SQL (or any other data access technology). We use Linq to SQL only because it is easier to set-up.

Select the Server Explorer.

Create a connection to the RIATasks database, and drag the Tasks table to the Object Relational Designer surface.

The data layer is complete.

Save and close the file.

Create The Web Service

Add a Web Service file to the RIATaks.Web site called Webservice.asmx.

Open the WebService.asmx.cs file that is created and replace ALL the code with the following code:

 Collapse
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace RIATasks.Web
{
    [WebService(Namespace = "http://OpenLightGroup.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class WebService : System.Web.Services.WebService
    {
        #region GetCurrentUserID
        private int GetCurrentUserID()
        {
            int intUserID = -1;
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                // Get the current user
                intUserID = Convert.ToInt32(HttpContext.Current.User.Identity.Name);
            }
            return intUserID;
        }
        #endregion

        // Web Methods

        #region GetTasks
        [WebMethod]
        public List<Task> GetTasks()
        {
            // Create a collection to hold the results
            List<Task> colResult = new List<Task>();

            RIATasksDBDataContext DB = new RIATasksDBDataContext();

            var colTasks = from Tasks in DB.Tasks
                           where Tasks.UserID == GetCurrentUserID()
                           select Tasks;

            // Loop thru the Tasks
            foreach (var item in colTasks)
            {
                // Create a Task
                Task tmpTask = new Task();

                // Set only the TaskID and the Name
                // We do this because Description could be 
                // a large amount of data that will slow down
                // the application and we don't need it now
                tmpTask.TaskID = item.TaskID;
                tmpTask.TaskName = item.TaskName;

                // Add to the final results
                colResult.Add(tmpTask);
            }

            return colResult;
        }
        #endregion

        #region GetTask
        [WebMethod]
        public Task GetTask(int TaskID)
        {
            RIATasksDBDataContext DB = new RIATasksDBDataContext();

            var result = (from Tasks in DB.Tasks
                          where Tasks.TaskID == TaskID
                          where Tasks.UserID == GetCurrentUserID()
                          select Tasks).FirstOrDefault();

            return result;
        }
        #endregion

        #region DeleteTask
        [WebMethod]
        public string DeleteTask(int TaskID)
        {
            string strError = "";
            RIATasksDBDataContext DB = new RIATasksDBDataContext();

            try
            {
                var result = (from Tasks in DB.Tasks
                              where Tasks.TaskID == TaskID
                              where Tasks.UserID == GetCurrentUserID()
                              select Tasks).FirstOrDefault();

                if (result != null)
                {
                    DB.Tasks.DeleteOnSubmit(result);
                    DB.SubmitChanges();
                }
            }
            catch (Exception ex)
            {
                strError = ex.Message;
            }

            return strError;
        }
        #endregion

        #region UpdateTask
        [WebMethod]
        public string UpdateTask(Task objTask)
        {
            string strError = "";
            RIATasksDBDataContext DB = new RIATasksDBDataContext();

            try
            {
                var result = (from Tasks in DB.Tasks
                              where Tasks.TaskID == objTask.TaskID
                              where Tasks.UserID == GetCurrentUserID()
                              select Tasks).FirstOrDefault();

                if (result != null)
                {
                    result.TaskDescription = objTask.TaskDescription;
                    result.TaskName = objTask.TaskName;

                    DB.SubmitChanges();
                }
            }
            catch (Exception ex)
            {
                strError = ex.Message;
            }

            return strError;
        }
        #endregion

        #region InsertTask
        [WebMethod]
        public Task InsertTask(Task objTask)
        {
            RIATasksDBDataContext DB = new RIATasksDBDataContext();

            try
            {
                Task InsertTask = new Task();

                InsertTask.TaskDescription = objTask.TaskDescription;
                InsertTask.TaskName = objTask.TaskName;
                InsertTask.UserID = GetCurrentUserID();

                DB.Tasks.InsertOnSubmit(InsertTask);
                DB.SubmitChanges();

                // Set the TaskID 
                objTask.TaskID = InsertTask.TaskID;
            }
            catch (Exception ex)
            {
                // Log the error
                objTask.TaskID = -1;
                objTask.TaskDescription = ex.Message;
            }

            return objTask;
        }
        #endregion
    }
}

Note that the web service methods call GetCurrentUserID(), that uses Convert.ToInt32(HttpContext.Current.User.Identity.Name), to get the current user.

The current UserID is set when the user logs in and creates a authentication “token“. The user’s web browser passes this token on all requests, including the web service requests that will be made by the Silverlight application.

To check that everything is set up correctly, you can right-click on the WebService.asmx file, and select View in Browser.

The web methods will display.

Note: You could use WCF instead. We use .asmx web services because they are easier to deploy.

The Silverlight Project

We will now complete the RIATasks Silverlight project. first, we need to create a reference, from the Silverlight project, to the web service we just created.

Then, we need to make a Model to call the web service we created, and an ICommand support class, that will allow us to easily raise events in theView Model.

Create the Web Service Reference

In the Silverlight Project, Right-click on References and select Add Service Reference…

  • Click the Discover button
  • Enter wsRIATasks for Namespace
  • Click the OK button

The connection between the Silverlight project and the website is complete. We will implement code, in a later step, that will use this reference to call the web service we created.

Add References

Add a Reference to Microsoft.VisualBasic

ICommand Support Class

Add a new folder and call it Classes. and then right-click on it and select New Item…

Create a class called DelegateCommand.cs.

Replace ALL the code with the following code:

 Collapse
using System.Windows.Input;
using System;

// From http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/
namespace RIATasks
{
    public class DelegateCommand : ICommand
    {
        Func<object, bool> canExecute;
        Action<object> executeAction;
        bool canExecuteCache;

        public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
        {
            this.executeAction = executeAction;
            this.canExecute = canExecute;
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            bool temp = canExecute(parameter);

            if (canExecuteCache != temp)
            {
                canExecuteCache = temp;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, new EventArgs());
                }
            }

            return canExecuteCache;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            executeAction(parameter);
        }

        #endregion
    }
}

This class allows us to easily invoke ICommands. You can get more information on this class at: http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/

The Model

Create a folder called Models, and a class called TasksModel.cs.

Replace all the code with the following code:

 Collapse
using Microsoft.VisualBasic;
using System.Linq;
using System;
using System.Collections.Generic;
using System.ServiceModel;
using RIATasks.wsRIATasks;

namespace RIATasks
{
    public class TasksModel
    {
        #region GetTask
        public static void GetTask(int TaskID, EventHandler<GetTaskCompletedEventArgs> eh)
        {
            // Set up web service call
            WebServiceSoapClient WS = new WebServiceSoapClient();

            // Set the EndpointAddress
            WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

            WS.GetTaskCompleted += eh;
            WS.GetTaskAsync(TaskID);
        }
        #endregion

        #region GetTasks
        public static void GetTasks(EventHandler<GetTasksCompletedEventArgs> eh)
        {
            // Set up web service call
            WebServiceSoapClient WS = new WebServiceSoapClient();

            // Set the EndpointAddress
            WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

            WS.GetTasksCompleted += eh;
            WS.GetTasksAsync();
        }
        #endregion

        #region DeleteTask
        public static void DeleteTask(int TaskID, EventHandler<DeleteTaskCompletedEventArgs> eh)
        {
            // Set up web service call
            WebServiceSoapClient WS = new WebServiceSoapClient();

            // Set the EndpointAddress
            WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

            WS.DeleteTaskCompleted += eh;
            WS.DeleteTaskAsync(TaskID);
        }
        #endregion

        #region UpdateTask
        public static void UpdateTask(Task objTask, EventHandler<UpdateTaskCompletedEventArgs> eh)
        {
            // Set up web service call
            WebServiceSoapClient WS = new WebServiceSoapClient();

            // Set the EndpointAddress
            WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

            WS.UpdateTaskCompleted += eh;
            WS.UpdateTaskAsync(objTask);
        }
        #endregion

        #region InsertTask
        public static void InsertTask(Task objTask, EventHandler<InsertTaskCompletedEventArgs> eh)
        {
            // Set up web service call
            WebServiceSoapClient WS = new WebServiceSoapClient();

            // Set the EndpointAddress
            WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

            WS.InsertTaskCompleted += eh;
            WS.InsertTaskAsync(objTask);
        }
        #endregion

        // Utility

        #region GetBaseAddress
        private static Uri GetBaseAddress()
        {
            // Get the web address of the .xap that launched this application     
            string strBaseWebAddress = App.Current.Host.Source.AbsoluteUri;
            // Find the position of the ClientBin directory        
            int PositionOfClientBin =
                App.Current.Host.Source.AbsoluteUri.ToLower().IndexOf(@"/clientbin");
            // Strip off everything after the ClientBin directory         
            strBaseWebAddress = Strings.Left(strBaseWebAddress, PositionOfClientBin);
            // Create a URI
            Uri UriWebService = new Uri(String.Format(@"{0}/WebService.asmx", strBaseWebAddress));
            // Return the base address          
            return UriWebService;
        }
        #endregion
    }
}

Note: GetBaseAddress() is a method that determines where the user launched the .xap (that the Silverlight application is contained in), and uses that to determine where the WebService.asmx file is at. The Web Service methods use that address to call the Web Service.

We have now created methods in the Model that communicate with the methods created in the Web Service created earlier.

Create a folder called ViewModels, and add class called MainPageModel.cs.

Replace all the code with the following code:

 Collapse
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows;
using RIATasks.wsRIATasks;

namespace RIATasks
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
            // Set the command property
            GetTasksCommand = new DelegateCommand(GetTasks, CanGetTasks);
            GetTaskCommand = new DelegateCommand(GetTask, CanGetTask);
            DeleteTaskCommand = new DelegateCommand(DeleteTask, CanDeleteTask);
            UpdateTaskCommand = new DelegateCommand(UpdateTask, CanUpdateTask);
            AddNewTaskCommand = new DelegateCommand(AddNewTask, CanAddNewTask);

            // The following line prevents Expression Blend
            // from showing an error when in design mode
            if (!DesignerProperties.IsInDesignTool)
            {
                // Get the Tasks for the current user
                GetTasks();

                // Set Visibility
                HasCurrentTask = Visibility.Collapsed;
                AddVisibility = Visibility.Visible;
                UpdateVisibility = Visibility.Collapsed;
                DeleteVisibility = Visibility.Collapsed;
            }
        }

        // Utility

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

This code implements INotifyPropertyChanged that will be used by Properties (created in a later step), to automatically notify the View when they have been updated.

The constructor, MainPageModel(), sets up some ICommands (that will be fully implemented in a later step). It also calls the GetTasks(), method, that will call the Model (that will then call the web service), and retrieve any Tasks for the logged in user.

Note: You will see wavy red lines underneath most of the lines in the code because it sets properties and commands that have not been created yet.

Add the following code to the class:

 Collapse
// Properties

        #region CurrentTask
        private Task _CurrentTask = new Task();
        public Task CurrentTask
        {
            get { return _CurrentTask; }
            private set
            {
                if (CurrentTask == value)
                {
                    return;
                }
                _CurrentTask = value;
                this.NotifyPropertyChanged("CurrentTask");
            }
        }
        #endregion

        #region AddVisibility
        private Visibility _AddVisibility = Visibility.Visible;
        public Visibility AddVisibility
        {
            get { return _AddVisibility; }
            private set
            {
                if (AddVisibility == value)
                {
                    return;
                }
                _AddVisibility = value;
                this.NotifyPropertyChanged("AddVisibility");
            }
        }
        #endregion

        #region UpdateVisibility
        private Visibility _UpdateVisibility = Visibility.Visible;
        public Visibility UpdateVisibility
        {
            get { return _UpdateVisibility; }
            private set
            {
                if (UpdateVisibility == value)
                {
                    return;
                }
                _UpdateVisibility = value;
                this.NotifyPropertyChanged("UpdateVisibility");
            }
        }
        #endregion

        #region DeleteVisibility
        private Visibility _DeleteVisibility = Visibility.Visible;
        public Visibility DeleteVisibility
        {
            get { return _DeleteVisibility; }
            private set
            {
                if (DeleteVisibility == value)
                {
                    return;
                }
                _DeleteVisibility = value;
                this.NotifyPropertyChanged("DeleteVisibility");
            }
        }
        #endregion

        #region HasTasks
        private Visibility _HasTasks = Visibility.Collapsed;
        public Visibility HasTasks
        {
            get { return _HasTasks; }
            private set
            {
                if (HasTasks == value)
                {
                    return;
                }
                _HasTasks = value;
                this.NotifyPropertyChanged("HasTasks");
            }
        }
        #endregion

        #region HasCurrentTask
        private Visibility _HasCurrentTask = Visibility.Collapsed;
        public Visibility HasCurrentTask
        {
            get { return _HasCurrentTask; }
            private set
            {
                if (HasCurrentTask == value)
                {
                    return;
                }
                _HasCurrentTask = value;
                this.NotifyPropertyChanged("HasCurrentTask");
            }
        }
        #endregion

        #region Message
        private string _Message;
        public string Message
        {
            get { return _Message; }
            private set
            {
                if (Message == value)
                {
                    return;
                }
                _Message = value;
                this.NotifyPropertyChanged("Message");
            }
        }
        #endregion

This looks like a lot of code, but it is only Properties that will hold values that will be set and consumed by the View. All of them raiseNotifyPropertyChanged when they are changed.

Add the following code to the class:

 Collapse
        // Collections

        #region colTasks
        private ObservableCollection<Task> _colTasks
            = new ObservableCollection<Task>();
        public ObservableCollection<Task> colTasks
        {
            get { return _colTasks; }
            private set
            {
                if (colTasks == value)
                {
                    return;
                }
                _colTasks = value;
                this.NotifyPropertyChanged("colTasks");
            }
        }
        #endregion

This is like a Property, but it holds a Collection of Tasks instead of a single value.

Add the following code to the class:

 Collapse
        
        // Operations

        #region GetTasks
        private void GetTasks()
        {
            // Clear the current Tasks
            colTasks.Clear();
            // Call the Model to get the collection of Tasks
            TasksModel.GetTasks((Param, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    // loop thru each item
                    foreach (var Task in EventArgs.Result)
                    {
                        // Add to the colTasks collection
                        colTasks.Add(Task);
                    }

                    // Count the records returned
                    if (colTasks.Count == 0)
                    {
                        // If there are no records, indicate that
                        Message = "No Records Found";

                        // Set HasCurrentTask
                        HasCurrentTask = Visibility.Collapsed;

                        // We have no Tasks so set HasTasks
                        HasTasks = Visibility.Collapsed;
                    }
                    else
                    {
                        // We have Tasks so set HasTasks
                        HasTasks = Visibility.Visible;
                    }
                }
            });
        }
        #endregion

        #region GetTask
        private void GetTask(int intTaskID)
        {
            // Call the Model to get the Task
            TasksModel.GetTask(intTaskID, (Param, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    // Set the CurrentTask Property
                    CurrentTask = EventArgs.Result;

                    // Set Visibility
                    HasCurrentTask = Visibility.Visible;
                    AddVisibility = Visibility.Visible;
                    UpdateVisibility = Visibility.Visible;
                    DeleteVisibility = Visibility.Visible;
                }
            });
        }
        #endregion

        #region DeleteTask
        private void DeleteTask(Task objTask)
        {
            // Call the Model to delete the Task
            TasksModel.DeleteTask(objTask.TaskID, (Param, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    // Set the Error Property
                    Message = EventArgs.Result;

                    // Set current Task to null
                    CurrentTask = null;

                    // Update the Tasks list
                    GetTasks();

                    // Set Visibility
                    HasCurrentTask = Visibility.Collapsed;
                    AddVisibility = Visibility.Visible;
                    UpdateVisibility = Visibility.Collapsed;
                    DeleteVisibility = Visibility.Collapsed;
                }
            });
        }
        #endregion

        #region UpdateTask
        private void UpdateTask(Task objTask)
        {
            // Call the Model to UpdateTask the Task
            TasksModel.UpdateTask(objTask, (Param, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    // Set the Error Property
                    Message = EventArgs.Result;

                    // Update the Tasks list
                    GetTasks();

                    // Set Visibility
                    HasCurrentTask = Visibility.Visible;
                    AddVisibility = Visibility.Visible;
                    UpdateVisibility = Visibility.Visible;
                    DeleteVisibility = Visibility.Visible;
                }
            });
        }
        #endregion

        #region InsertTask
        private void InsertTask(Task objTask)
        {
            // Call the Model to Insert the Task
            TasksModel.InsertTask(objTask, (Param, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    // Set the CurrentTask Property
                    CurrentTask = EventArgs.Result;

                    // Update the Tasks list
                    GetTasks();

                    // Set Visibility
                    HasCurrentTask = Visibility.Visible;
                    AddVisibility = Visibility.Visible;
                    UpdateVisibility = Visibility.Visible;
                    DeleteVisibility = Visibility.Visible;
                }
            });
        }
        #endregion

        #region SetToNewTask
        private void SetToNewTask()
        {
            // Create a empty Task
            // so form will be blank
            Task objTask = new Task();

            // Set TaskID = -1 so we know it's 
            // a new Task
            objTask.TaskID = -1;

            // Set the CurrentTask Property
            CurrentTask = objTask;

            // Set Visibility
            HasCurrentTask = Visibility.Visible;
            AddVisibility = Visibility.Collapsed;
            UpdateVisibility = Visibility.Visible;
            DeleteVisibility = Visibility.Collapsed;
        }
        #endregion

These are the operations that the View Model will perform. These are the methods that do the actual work. Mostly these methods simply call the methods in the Model.

Add the following code to the class:

 Collapse
     // Commands

        #region GetTasksCommand
        public ICommand GetTasksCommand { get; set; }
        public void GetTasks(object param)
        {
            GetTasks();
        }

        private bool CanGetTasks(object param)
        {
            return true;
        }
        #endregion

        #region GetTaskCommand
        public ICommand GetTaskCommand { get; set; }
        public void GetTask(object param)
        {
            // Get the Task that was passed as a parameter
            Task objTask = (Task)param;

            // Call GetTask to get and set
            // the CurrentTask property
            GetTask(objTask.TaskID);
        }

        private bool CanGetTask(object param)
        {
            // Only allow this ICommand to fire 
            // if a Task was passed as a parameter
            return ((param as Task) != null);
        }
        #endregion

        #region DeleteTaskCommand
        public ICommand DeleteTaskCommand { get; set; }
        public void DeleteTask(object param)
        {
            if (CurrentTask.TaskID == -1)
            {
                // This is a new Task
                SetToNewTask();
            }
            else
            {
                // This is an Existing Task
                DeleteTask(CurrentTask);
            }
        }

        private bool CanDeleteTask(object param)
        {
            // Do not allow if there is no Current Task
            return (CurrentTask != null);
        }
        #endregion

        #region UpdateTaskCommand
        public ICommand UpdateTaskCommand { get; set; }
        public void UpdateTask(object param)
        {
            if (CurrentTask.TaskID == -1)
            {
                // This is a new Task
                InsertTask(CurrentTask);
            }
            else
            {
                // This is an Update
                UpdateTask(CurrentTask);
            }
        }

        private bool CanUpdateTask(object param)
        {
            // Do not allow if there is no Current Task
            return (CurrentTask != null);
        }
        #endregion

        #region AddNewTaskCommand
        public ICommand AddNewTaskCommand { get; set; }
        public void AddNewTask(object param)
        {
            SetToNewTask();
        }

        private bool CanAddNewTask(object param)
        {
            return true;
        }
        #endregion

These are the ICommands. They will be called from the View.

In Visual Studio, select Build, then Build RIATasks.

The project should build without any errors.

Open the MainPage.xaml file in Expression Blend 4 (or higher).

The project will open in Expression Blend.

Click on LayoutRoot in the Objects and Timeline window, and in the Properties window, type DataContext in the Search box.

Next, Click the New button next to DataContext.

Select MainPageModel and click OK.

Click the Data tab and expand MainPageModel (under the Data Context section).

You will all the public PropertiesCollections, and ICommands that are in the MainPageModel.

Create Sample Data

It will be easier to design the form if we are also able to see sample data.

In the Data window, Click on the Create sample data icon.

Select Create Sample Data from Class…

Select the MainPageModel and click OK

You will now see the MainPageModelSampleData class.

Build the View

Click on colTasks in the Sample Data section…

…and drop it on the page.

It will create a ListBox with sample data. Note: At run-time the real data will show not the Sample Data.

In the Properties for the ListBox, set the HorizontalAlignment to Left, and the VerticalAlignment to Top

Right-click on the ListBox and select:

Edit additional Templates > Edit Generated Items > Edit Current

Click on the third TextBlock in the Objects and Timeline window

In the Properties for the TextBlock, select Advanced options next to Text

Select Data Binding

We see that this is bound to the TaskName. This is the only TextBlock that we want to show in the ListBox

In the Objects and Timeline window, delete the other three TextBlocks

Click the Return scope icon

The ListBox is now formatted

Now, select the Grid control

Draw a Grid next to the ListBox

Hover the mouse near the edge of the Grid, and click with the left mouse button, to make cells

From the Tools Bar, grab a TextBox

Draw a TextBox on the Grid

From the Data window, grab TaskName

Drag TaskName onto the TextBox

In the Properties for the TextBox:

  • Set the Width and Height to Auto
  • Set Horizontal and Vertical Alignment
  • Set all Margins to 0

Draw another TextBox on the Grid

In the Properties for the TextBox:

  • Set the Width and Height to Auto
  • Set Horizontal and Vertical Alignment
  • Set all Margins to 0

From the Data window, drag TaskDescription onto the TextBox

Drag TextBlocks onto the Grid for Name and Description labels, and set their Text Properties.

Click on Button in the Tools Bar

Draw a Button above the ListBox

Set the Content of the button to Add

Add an Update and Delete button

(we will set the button’s Click events in a later step)

Setting Visibility

We now have all the controls on the page, we will now hook up the Visibility for the various controls

Click on the Grid in the Objects and Timeline window

In the Properties for the Grid, select Advanced options for Visibility

Select Data Binding…

Bind to HasCurrentTask and click OK

Hook up the remaining Visibility Properties according to the diagram above.

Note: If binding the Visibility causes some elements to disappear in Design mode, you can edit the sample data file…

…and set them to Visible

Using Behaviors

We will now use the InvokeCommandAction behavior to allow the buttons to raise ICommands in the View Model.

Add Button

Get an InvokeCommandAction Behavior.

Drop it on the Add button in the Objects and Timeline window

In the Properties for the Behavior:

  • Select Click for EventName
  • Click Data bind icon next to Command (under Common Properties)

Select the Data Context tab and then select AddNewTaskCommand and click OK.

Add InvokeCommandAction Behaviors to the Update and Delete buttons according to the diagram above.

Selecting A Task From The ListBox

  • Drop an InvokeCommandAction behavior to the ListBox.
  • Set the EventName to SelectionChanged
  • Click Data bind next to Command

Select GetTaskCommand and click OK

Click Advanced options next to CommandParameter

Select the SelectedItem from the ListBox and click OK

Add Styling

image

See the article at this link to obtain the ResourceDictionary for the style, and the directions on how to apply it.

Build And Run The Project

In the Projects window, right-click on the RIATasks.Web project and select Startup Project

Right-click on the Default.aspx page and select Startup

Hit F5 to Build and Run the project

The project is complete.

Use View Model When You Want To Write Less Code

Bindings combined with INotifyPropertyChanged, can save you from writing a lot of code. Using View Model allows you to leverage a lot of the helpful features in Microsoft Expressions BlendView Model is also a simple pattern to follow, so you can quickly and easily implement Properties,Collections and ICommands.

The actual “custom code” is contained in the “Operations” section of the View Model. You will see that it is not a lot of code and most of it is simply calling the Model and setting a Property in the View Model. Also note, that when an object such as “Task” is set as the current Task selected, we never need to split out each of the fields in the Task object and process each separately, we just pass the actual “Task” object between the Model,View Model, and View.

It is very helpful that we can expose Properties, such as custom objects like Task and Visibility, to the View as they are, and let the Designer worry about how to actually implement them. Even if we are also the Designer, we can use the drag and drop features of Expression Blend to quickly, and accurately assemble the UI.

The programmer can simply concentrate on getting the data in and out of the View Model, through the Model, and enforcing business rules. This allows the Programmer to focus on a clear easily testable task. The UI issues are abstracted away.

This I believe is where a programmer will discover that they will use LESS CODE than if they did not use View Model. At the very least, many programmers I have worked with, find the experience more enjoyable because they can focus on the procedural logic.

4 Simple Steps to Consume WCF Service using Silverlight


4 Simple Steps to Consume WCF Service using Silverlight

Video demonstration One Way, Two Way and One Time Bindings using Silver light

Introduction

This article will talk about 4 simple steps which will assist you to consume WCF service in a Silverlight application. It also has a simple sample source code which demonstrates all the 4 steps practically.

I have collected around 400 FAQ questions and answers in WCF, WPF, WWF, SharePoint, design patterns, UML, etc. Feel free to download these FAQ PDFs from my site http://www.questpond.com.

Step 1: Create Your WCF Service

The first step is to create your WCF service. When we create a WCF service, by default it creates ‘GetData’ function which takes in an integer value and returns back a string saying “You entered 10” , in case you passed ‘10’ as value to the function. We will try to consume this service in Silverlight in the coming steps:

 Collapse
public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
}

Step 2: Enable Cross Domain for Your WCF Service

For this example, our WCF service and the Silverlight web application will be hosted in different IIS websites. In other words, they will be hosted in different domains. When we talk about different website, in other words they are hosted in different domains. For instance, it’s possible that your Silverlight web application is hosted in one domain like www.xyz.com  and your WCF service is hosted in different domain i.e. www.pqr.com.

The WCF service needs to enable cross domain facility so that other domains can consume the WCF service.

Figure: Cross domain

We need to create two XML files (clientaccesspolicy.xml and crossdomain.xml) in the root directory of the WCF service to enable cross domain functionality.
Below is the XML code snippet for clientaccesspolicy.xml:

 Collapse
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource include-subpaths="true" path="/"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

Below is the XML code snippet for crossdomain.xml:

 Collapse
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM 
	"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

Step 3: Add the WCF Service Reference

Create a simple Silverlight application and add the service reference to your Silverlight project. In order to call the WCF service, we need to define event handlers.

To consume the WCF service is a three step procedure.

  • In the first step, refer to the name space.
  • In the second step, create the object of your WCF service.
  • In the final step, we need to create an event handler which will get the results sent by the WCF service.

One of the important points to note is that the function ‘GetData’ is called asynchronously.

Step 4: Call the Service

Finally compile the program and enjoy the output.

A Simple Sample: WCF Service


Introduction

This article discusses the simplest way to write, configure and consume Windows Communication Foundation (WCF) service, using Visual Studio 2010. This would help gain a better understanding to WCF services which is slightly different from ASP.NET web services.

Background

We would look into writing and consuming a simple service using VS2010. Scenario: Book store service that would fetch the book information. At the end of the article you would know:

  • How to build a WCF service
  • How to consume WCF service in Windows Forms
  • How to bind custom object with DataGridView
  • How to configure WCF Service while publishing
  • How to convert XElement to custom object using LINQ

Also you might be interested in Why use MessageContract when DataContract is there?; an article that I wrote some time back. Btw, we will use both in this example.

Steps to Follow

Lets create a WCF Service Library project. Visual Studio 2010 stubs-in a default service which it calls Service1.  Lets ignore this existing service for a while now. We would create a separate service that would return the list of books requested by the client end.

Note that to just to keep things simple, we would use XML file as our data store; taken from MSDN

The XML has columns: Author, Title, Genre, Price, Publish Date, Description, and Book ID.

The Book ID, which is a string shall be used as primary key to identify the book.

We would add an book interface that shall define what this service provides as book service. So, we want to provide a service that returns the list of books found based upon user criteria.

Add a new item as interface called IBookService under namespace Store. Add the directive, using System.ServiceModel;
Decorate the interface with service contract attribute as [ServiceContract].

We want the following functionality as a scope of this sample:

  • List of all books
  • Filter functionality; return a book or a list of books given its ID or Title or Genre or Author

Note that we will also look into the .NET default/optional arguments functionality that is provided in C# v4.0, as a part of this sample while we implement the above methods.

The interface shall contain the methods

Let’s define the operations for IBookService interface:

 Collapse
namespace Store
{
    [ServiceContract]
    interface IBookService
    {
        [OperationContract]
        List GetAllBooks();//Get all books; returns list of books

        [OperationContract]
        List GetBookByID(string BookID);//Gets a(single) book by ID

        [OperationContract]
        List Filter(string Author, string Genre, string Title); //Returns list of books by specified filter
    }
}

Lets add a Book type and define the attributes of the book that we want for the client to have. For now its all those attributes that are there in the XML data.

Right click on the Book return type, and select Generate Class for Book. This shall generate the class of type Book. Note that you also write the attributes where it is to be used and VS shall add those attributes in the class automatically.

fig1.jpg

FIG1: Book service interface

If you select the generate new type it will show the following window and provide you with the options about class. Its Access specifier, Kind (class, struct, etc), and either to create a new file and stub the code in the current file. We would select a separate file.
fig2.jpg

FIG2: Add Book data type

Right click on the Book return type and select Goto Definition.

Add the directive using ServiceModel, and using System.Runtime.Serialization;. And DataContract attribute on Book class; it would look like following:

fig3.jpg

FIG3: List of book attributes, similar to XML element attributes.In figure 3, note that the ID is of type string, ideally ID’s should be of integer type, when using as primary keys, integers keys works faster than the string keys. The reason we are using the string type primary key, is that we have string data in the XML data store.

Lets decorate the Book class with DataContract attribute.

A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged. That is, to communicate, the client and the service do not have to share the same types, only the same data contracts. A data contract precisely defines, for each parameter or return type, what data is serialized (turned into XML) to be exchanged.

Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML). All .NET Framework primitive types, such as integers and strings, as well as certain types treated as primitives, such as DateTime and XmlElement, can be serialized with no other preparation and are considered as having default data contracts.

Lets add the types that are required ID, Title, Author, Description, Genre, Price, and Publish Date and tag all members with[DataMember] attribute.

Now we will add a class BookService that implements the IBookService interface;

The book service shall contain the definition

fig4.jpg

FIG4: Implement book service interface

Note, in case if you plan on using the database(and not the xml which is a part of this example), you can use Enterprise Library, Data Application Block for your data transactions; you will need to add a reference to the Data.dll file, generally available in the DRIVE:\Program Files\Microsoft Enterprise Library 4.1 – October 2008\Bin.

Now lets add the implementation of the methods. First, there this is a small GetDb() method, that loads the data from given XML and into the XDocument object.

Then, since we interested in the book nodes, therefore we select all the books.

The select new Book() creates a new object and copies the data from book attribute into our defined book object attribute. So by the end of the book structure “}” is complete we have our book object ready to be inserted into the List object.

Implementing both the methods using XDocument and LINQ, answers the question, how to convert XElement to custom object using LINQ.

 Collapse
public List GetAllBooks()
{
    XDocument db = GetDb();
    List lstBooks
         =
        (from book in db.Descendants("book")
         select new Book()
         {
             ID = book.Attribute("id").Value //Get attribute from XML and set into the Book object attribute.
             ,
             Author = book.Element("author").Value
             ,
             Genre = book.Element("genre").Value
             ,
             Price = Convert.ToDecimal(book.Element("price").Value)
             ,
             Description = book.Element("description").Value
             ,
             PublishDate = Convert.ToDateTime(book.Element("publish_date").Value)
             ,
             Title = book.Element("title").Value
         }).ToList(); //Cast it into the list

    return lstBooks;
}

The above is the method that gets all of the books in the datastore. Now, lets add the definition for GetBookByID(). The method is same as get all books, except for the where clause. Note that, this shall be only one book in this case, so the list shall contain only one item.

 Collapse
public List GetBookByID(string BookID)
{
    XDocument db = GetDb();

    //Howto: Convert XElements to Custom Object
    List lstBooks =
        (from book in db.Descendants("book")
         where book.Attribute("id").Value.Equals(BookID)
         select new Book() //Instantiate a new object 
         {
             ID = book.Attribute("id").Value
            ,
             Author = book.Element("author").Value
            ,
             Genre = book.Element("genre").Value
            ,
             Price = Convert.ToDecimal(book.Element("price").Value)
            ,
             Description = book.Element("description").Value
            ,
             PublishDate = Convert.ToDateTime(book.Element("publish_date").Value)
            ,
             Title = book.Element("title").Value
         }).ToList();

    return lstBooks;
}

The above code gets a book given its ID using LINQ.

Configuration and Deployment

Add the service definition in app.config file under system.serviceModel/services tag.

The system.serviceModel/services tag contains the classes, enumerations, and interfaces necessary to build service and client applications that can be used to build widely distributed applications.

 Collapse
<service name="Store.BookService">
        <endpoint binding="basicHttpBinding" contract="Store.IBookService"></endpoint>
      </service>

basicHttpBinding Represents a binding that a service can use to configure and expose endpoints that are able to communicate with ASMX-based Web services and clients and other services that conform to the WS-I Basic Profile 1.1 [^] . Contract is the name of the interface that we expose.

Note that a WCF service requires an application host, in order to run and be accessible to clients.

We have couple of options here, for instance:

  • Create a custom host application
  • Build a Windows service application
  • Using IIS

In our case we would use IIS to simply publish the service.

Right click on the project and select Publish, would generate following directory structure in IIS.

fig5.jpg
Fig5: Configure WCF Service in IIS

Just for your interest, if you are using a version prior to VS2010 to configure a WCF service, following is the manual process.

  • Ensure that you have the binary files being built inside the \bin folder, rather than \debug or \release folder.
  • Add a service definition file, a file having .svc extension.
  • Add a new item, select the Text File template; rename the file to BookService.Svc. This shall contain the service definitions.

Fortuntely Visual Studio 2010 does that for us.

We also need to tell the IIS that our service is going to use the .NET Framework version 4.0. So that it does not use its default .NET framwork.

Fig6 shows how to change the framework that IIS is going to use for our app.

fig6.jpg
Fig6: Change app’s framework in IIS

Publish in IIS

In order to be able to be accessible to the outside world, we need to allow access. You can open the url in IE and see it works. In my case, for instance, I have it under WCF folder http://localhost/WCF/Store.BookService.svc.

fig7.jpg

FIG7: Open service url in the browser

Note the highlighted text in the above image. This requires a service behavior to be added in the config file, which Visual Studio 2010 stubs in for us automatically.

You will need to set the httpGetEnabled attribute to true, in order to publish your service metadata. Its a Boolean value that specifies whether to publish service metadata for retrieval using an HTTP/Get request. The default is false.

To save and publish the service into IIS, click on

SavePublish.

Now you can open the url again in IE, and you should be able to see your service’s meta.

fig8.jpg
Fig8: Book service in IE Quick way to see the wsdl, type ?wsdl in the address bar to see the wsdl, like:http://localhost/WCF/Store.BookService.svc?wsdl

fig9.jpg
Fig9: Book service WSDL listing

How to Consume WCF Service?

We would create a small forms based client app, that would show a couple of filter options, and provide a search button that requests the service for books based upon the filter provided by the user.

Add a Windows Forms project and design the form.

fig10.jpg
Fig10: Client user interface (UI) To be able to consume the service we will need to add a reference to that service. So when you try to add the service reference, the IDE discovers all the services on your system. Alternatively, you can provide the path that you have of the service.

Note that web services, by nature, are of public type. Though, WCF adds the Service, Message, and Data level contracts; but the service itself is public.

So Right click on the WCF Client project and add a service reference. In your client app, add the service reference.

Add following as the service reference uri: http://localhost/WCF/Store.BookService.svc?wsdl. I would rename the reference toSvcBookstore.

fig11.jpg
Fig11: Client user interface (UI)

Since, at this point, we have already added the service reference, therefore we can access it by adding the using directive in the forms class, and then declaring the object of the service; exactly similar to how we add/declare other .NET objects. Lets declare the service object in our form. And addusing directives.

One important thing: What if you are in the middle of developing real world WCF Services, and now you want to test it. And while testing using a demo client app, your service is throwing exception that you have hell no idea of. So in that case, a “natural” scenario a developer wants is that you should able to “step into (F11)” the service code and see if for yourself. Thats is going be to a great help. So, if this is the case you can always go back to your service configuration file and add the a serviceDebug within behavior element.

 Collapse

serviceDebug allows the client app receive exception details in faults for debugging purposes, when set to true. DONOT, forget to set to falsebefore deployment to avoid disclosing exception information.

So, if you want to get the service related exception here at the client ends, add a tag in service. Because, at this point you might want to step into it.

Client Code

So, lets add the final code that collects the filter specified by the user, and call the service. When the data is retrieved, you can simply just assign object array to .DataSource property to show on Grid. Following the output of the client.

 Collapse
private void button1_Click(object sender, EventArgs e)
{
    //Get the combo choice, if there is any.
    string strGenre = cbxGenre.SelectedIndex > -1 ? cbxGenre.SelectedItem.ToString() : string.Empty;

    //Declare the books array; though the actual return type is List, it actually gets casted into
    //Book[] array.
    Book[] lstBooks = null;

    //Discard other filters, if user has entered a book id
    if (!string.IsNullOrEmpty(txtID.Text))
    {
        lstBooks = bookService.GetBookByID(txtID.Text);
    }
    else
    {
        //Lets get books by filter.
        lstBooks = bookService.Filter(Author: txtAuthor.Text, Title: TxtTitle.Text, Genre: strGenre);
    }

    //Set datasource, custom object.
    dataGridView1.DataSource = lstBooks;

}

Did you notice bookService.Filter(Author: txtAuthor.Text, Title: TxtTitle.Text, Genre: strGenre); line in the code above?

Thats what the named arguments are. Named arguments free you from the need to remember or to look up the order of parameters in the parameter lists of called methods. The parameter for each argument can be specified by parameter name. Named arguments can follow positional arguments.

As an example, if at some point, for this client app, user only provides the Author to look for, you can provide only the author to this method. Like:bookService.Filter(Author: "Paulo Coelho");

Note that you will have to update the Service’s .Filter() method and provide the default arguments; for instance, like following:

 Collapse
public List<book> Filter(string Author = "N/A", string Genre = "N/A", string Title = "N/A")

fig12.jpg
FIG12:Output of client user interface (UI)

Points of Interest

Couple of things that I noticed is that WCF service is way different than an ASP.NET service. The file extensions are different as well. .asmx for ASP.NET and .svc for WCF. Also, after all that you have done above, and deployed your application and now you are wondering, WHY your service is taking time on the first load. Well, Why my service is slow on first access? might just help you.

Simple Web Service using WCF (Windows Communication Framework)


Introduction

This article shows you how easy it is to setup a web service using WCF (Windows Communication Framework). Using the source I’ve provided as a template, you can quickly create your own web services. This article does not deal with a client consuming the web service (you will have to wait until part 2).

Background

I’ve been playing around with WCF for a while, since the early CTP’s. I found it difficult to find good samples/examples. Either they didn’t work or I was either too lazy or too stupid to get them working. All I wanted was something that worked with very little effort (or understanding) on my part. I just wanted something I could install and get running!!!

Of course at some point everyone will have to understand the ABC’s (but that can wait for another day). When you start to learn a new technology, especially a Beta or CPT – you just want it to work, figuring out how it works can wait for another day…..

So I put together a simple WCF Web service, that you can just download and get running in a few minutes (for lazy developers – like myself!)

Getting Started

You are going to need Visual Studio 2005 (it might work with other versions of Visual Studio, but I’ve not tested in and I’m not going to!!), and .NET 3.0 (I would get the entire package from here instead).

Then just download the source from above.

Using the code

Download the example code and open up the solution in Visual Studio 2005.

The are two projects, the Web service and the Implementation of the class. [Fig 1]

Fig 1 – showing the 2 projects

I have chosen to use the dev web server that is built into Visual Studio, it’s just easier, less setup and mucking around. But there is no reason not to use IIS (if you know how to). When your code goes into production you will be using IIS, but for now I’m going to leave it alone.

There are two parts to the web service, the .svc file and the web.config.

WCFService.svc

Collapse

Web.Config

Collapse

The Service from the ServiceHost attribute in the WCFService.svc file should match one of the service names in the web.config. The service name and endpoint contract should both match the implementation and contracts from the WCF Project Template.

The WCF Project Template is made up of 3 parts, the contract [data contract or message], the implementation and the interface [ServiceContract] (yes, the ABC’s had to come in somewhere).

The Service Contract

The WCFContract.cs contains the interface for this service.

Collapse
[ServiceContract]
interface IEchoContract
{
[OperationContract]
EchoMessage Echo(EchoMessage Message);
}
The Data Contract

The Message which gets sent around is contained in the WCFContract.cs

Collapse
[DataContract]
public class EchoMessage
{
private string _OutMessage;
private string _ReturnMessage;

[DataMember]
public string OutMessage
{
get { return _OutMessage; }
set { _OutMessage = value; }
}

[DataMember]
public string ReturnMessage
{
get { return _ReturnMessage; }
set { _ReturnMessage = value; }
}
}
The Implementation

The implementation of the web service is in WCFImplementation.cs

Collapse
class EchoImplementation : IEchoContract
{
public EchoMessage Echo(EchoMessage Message)
{
EchoMessage _returningMessage = new EchoMessage();

_returningMessage.ReturnMessage = Message.OutMessage;

return _returningMessage;
}
}
For this example, I used the EchoMessage to pass the data between the client and the web service, but this could be any class that has [DataContract] as an attribute.