[微軟官方代碼]Getting Started - WCF RIA Services

[對應資源下載] : 代碼文件下載   數據庫下載   文檔下載


The sample provides a step by step guide to building your first RIA services application. The application we will be building here is an HR Application for an Enterprise.

Installation

1. Manually uninstall the following via Add/Remove programs in Control Panel:

  1. Microsoft Silverlight (any version prior to Silverlight 3 RTW)
  2. Microsoft Silverlight SDK
  3. Microsoft Silverlight Tools for Visual Studio 2008

2. Install Visual Studio 2010 RC.

3. Install the following:

  1. Silverlight 4 RC
  2. Silverlight 4 RC SDK

4. Install WCF RIA Services RC.

Creating a new WCF RIA Services application

1. Start Visual Studio

2. On the File menu, click Newà Project. TheNew Project dialog is displayed.

3. In the Project types pane, expand Visual Basic or C#, then selectSilverlight.

4. In the My Templates pane, select Silverlight Business Application.

5. Change the project name to ‘HRApp’. Click OK.

There are a couple of things to notice once the project is created:

  1. The solution created for you consists of two projects: a Silverlight client project called HRApp and an ASP.NET Web Application server project called HRApp.Web.
  2. The default application created for you has navigation, login/logout, new user registration enabled by default. Run the project and experiment with the default, out of the box application. When running the application for the first time, allow Visual Studio to Modify Web.config file to enable debugging.

NOTE – The default User Registration implementation requires SQL Server Express be installed on the machine.

Setting up the application

1. In the client project, open MainPage.xaml.

2. Notice that the default XAML code (shown below) gets the application name from a resource.

複製代碼
XAML
Edit|Remove
<!-- XAML --><TextBlock x:Name="ApplicationNameTextBlock"   Style="{StaticResource ApplicationNameStyle}"   Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>

3. In the client project, open the Assets folder, and in that folder open the Resources folder.

4. Open the ApplicationStrings.resx file, and change the ApplicationName resource to “HR Application”.

5. Save and close the ApplicationStrings.resx file.

6. In Solution Explorer, right click the HRApp project, select Add, and then select New Item.The Add New Item dialog box is displayed.

7. In the Categories pane, selectSilverlight and in Templates pane, select Silverlight Page. Name the new item ‘EmployeeList.xaml’ and clickAdd.

8. Open EmployeeList.xaml and add the following XAML code between the <Grid> tags

複製代碼
XAML
Edit|Remove
<!-- XAML --><ScrollViewer BorderThickness="0"  VerticalScrollBarVisibility="Auto" Padding="12,0,12,0" Margin="-12">    <StackPanel Margin="0,12,0,12" Orientation="Vertical" >      <TextBlock Text="Employee List" Style="{StaticResource HeaderTextStyle}"/>    </StackPanel></ScrollViewer>

9. Save the EmployeeList.xaml file.

10. In Solution Explorer, click EmployeeList.xaml and drag it to theViews folder.

11. If you are using Visual Basic, add the following Imports statement toEmployeeList.xaml.vb.

複製代碼
Visual Basic
Edit|Remove
Imports System.Windows.Controls

12. Open MainPage.xaml and add a new link button to top of the page by adding the XAML code between the two existing link buttons.

複製代碼
XAML
Edit|Remove
<!-- XAML --><HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/EmployeeList" TargetName="ContentFrame" Content="Employee List"/> <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>

13. Run the application and you will notice a new link button (‘Employee List’) has been added.

Adding Business Logic to a .NET RIA Services application

If you have the AdventureWorks database already installed feel free to use it; otherwise you can install one from CodePlex:http://msftdbprodsamples.codeplex.com/releases/view/4004

Add a Data Source

1. In Solution Explorer, right-click the HRApp.Web project, select Add, and then select New Item. The Add New Item dialog box is displayed.

2. In the Categories pane, selectData, and in the Templates pane, select ADO.NET Entity Data Model. Name the data model ‘AdventureWorks.edmx’ and clickAdd.

3. In the Entity Data Model Wizard, choose to generate the Model from an existing database and clickNext.

4. Select the connection to the AdventureWorks database and then set the name of the entity connection settings toAdventureWorks_DataEntities.

5. Select Next.

6. Expand the Tables node and choose the Employee table to be used by the Entity Data model. Set the model namespace to ‘AdventureWorks_DataModel’.

7. Click Finish. The entity data model appears in the designer.

8. On the Build menu, selectBuild Solution.

Add a Domain Service Object and Query for Data

1. In Solution Explorer, right-click the HRApp.Web project, select Add, and then select New Item. The Add New Item dialog box is displayed.

2. In the Categories pane, selectWeb, and in the Templates pane, select Domain Service Class. Name the new item ‘OrganizationService’.

3. Click Add

4. In the Add New Domain Service Class dialog, selectEmployee from the Entities list, select Enable editing, and selectGenerate associated classes for metadata. Also, ensure that the Enable client access checkbox is checked.

5. Click OK.

6. In the OrganizationService.cs/vb file, you will see that a query method and the Create/Update/Delete (CUD) data methods have been added. The CUD data methods were added becauseEnable editing was selected.

7. Customize the select function by updating theGetEmployees() method to return the data sorted by EmployeeID.

Replace this generated code:

複製代碼
C#Visual Basic
Edit|Remove
// C# 
public IQueryable<Employee> GetEmployees() 
{ 
return this.ObjectContext.Employees; 
} 
'VB 
Public Function GetEmployees() As IQueryable(Of Employee) 
Return Me.ObjectContext.Employees 
End Function
With the following code:
複製代碼
Visual BasicC#
Edit|Remove
'VBPublic Function GetEmployees() As IQueryable(Of Employee)    Return Me.ObjectContext.Employees.OrderBy(Function(e) e.EmployeeID)End Function
// C#public IQueryable<Employee> GetEmployees(){    return this.ObjectContext.Employees.OrderBy(e => e.EmployeeID);}

8. On the Build menu, selectBuild Solution.
Building the solution generates the Domain Context and entities in the client project.

9. In the client project, open EmployeeList.xaml.

10. Open the Toolbox. The Toolbox is available from theView menu.

11. Drag a DataGrid from the toolbox onto the XAML view forEmployeeList.xaml. Add the DataGrid inside of the StackPanel, just after the TextBlock.
Dragging a DataGrid into the XAML editor adds a reference to theSystem.Windows.Controls.Data assembly and maps the System.Windows.Controls namespace to a prefix. The prefix can be any value. In this walkthrough, the examples are shown with the prefix set todata.

複製代碼
XAML
Edit|Remove
<!-- XAML --><data:DataGrid ></data:DataGrid>

The prefix is set in the Page element.

xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

12. Name the DataGrid ‘dataGrid1’ , make it read-only, and set its minimum height by adding the following XAML..

複製代碼
XAML
Edit|Remove
<!-- XAML --><data:DataGrid Name="dataGrid1" MinHeight="100" IsReadOnly="True"></data:DataGrid>

13. Save EmployeeList.xaml and build the solution.

14. Open EmployeeList.xaml.cs/vb.

15. Add the following using/Imports statements:
複製代碼
Visual BasicC#
Edit|Remove
'VBImports System.ServiceModel.DomainServices.Client
// C#using HRApp.Web;using System.ServiceModel.DomainServices.Client;

16. In the code generated for the client project, theOrganizationContext is generated based on OrganizationService. Instantiate theOrganizationContext class and load employee data by adding the following code (in bold) toEmployeeList.xaml.cs/vb:

複製代碼
Visual BasicC#
Edit|Remove
'VBImports System.Windows.ControlsImports System.ServiceModel.DomainServices.ClientPartial Public Class EmployeeList    Inherits Page    Dim _OrganizationContext As New OrganizationContext    Public Sub New()        InitializeComponent()        Me.dataGrid1.ItemsSource = _OrganizationContext.Employees       _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery())End Sub    'Occurs when the user navigates to this page.    Protected Overrides Sub OnNavigatedTo(ByVal e As       System.Windows.Navigation.NavigationEventArgs)    End SubEnd Class
// C#namespace HRApp{    public partial class EmployeeList : Page    {      OrganizationContext _OrganizationContext = new OrganizationContext();      public EmployeeList()      {         InitializeComponent();  this.dataGrid1.ItemsSource = _OrganizationContext.Employees;  _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery());      }                // Occurs when the user navigates to this page.      protected override void OnNavigatedTo(NavigationEventArgs e)      {      }    }}

17. Run the application. Click the Employee List link when the application is loaded to see theDataGrid.

Add a Custom Query

1. In the HRApp.Web project, open OrganizationService.cs/vb.

2. Add a new method called GetSalariedEmployees by adding the following code to the body of the class.

複製代碼
Visual BasicC#
Edit|Remove
'VBPublic Function GetSalariedEmployees() As IQueryable(Of Employee)    Return Me.ObjectContext.Employees.Where(Function(e) e.SalariedFlag = True).OrderBy(Function(e) e.EmployeeID)End Function
// C#public IQueryable<Employee> GetSalariedEmployees(){    return this.ObjectContext.Employees.Where(e => e.SalariedFlag == true).OrderBy(e => e.EmployeeID);}

3. On the Build menu, selectBuild Solution.

4. In the client project, open EmployeeList.xaml.cs/vb. A new query function is available in IntelliSense called OrganizationContext.GetSalariedEmployeesQuery.

5. In the constructor, replace the call toGetEmployeesQuery() with a call to GetSalariedEmployeesQuery() .

複製代碼
Visual BasicC#
Edit|Remove
'VB_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery())
// C#_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery());

6. Run the application and click the Employee List link. Notice that employees 1, 2, and 4 no longer appear in the list because they are not salaried.

Add a Domain Data Source

1. In the client project, open EmployeeList.xaml.

2. Drag the DomainDataSource from the toolbox ontoEmployeeList.xaml, just before the DataGrid.

3. Change the namespace prefix for System.Windows.Controls frommy to riaControls.

複製代碼
XAML
Edit|Remove
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"

4. For C# solutions, add the following namespace declaration to the XAML file:

複製代碼
XAML
Edit|Remove
<!— XAML for C# solutions -->xmlns:ds="clr-namespace:HRApp.Web"

For VB solutions, add the following namespace declaration to the XAML file:

複製代碼
XAML
Edit|Remove
<!-- XAML for VB solutions-->xmlns:ds="clr-namespace:HRApp"

5. Name the DomainDataSource ‘employeeDataSource’ and set the DomainContext , LoadSize, AutoLoad, and query method by adding the following XAML code:

複製代碼
XAML
Edit|Remove
<!-- XAML -->    <riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True"></riaControls:DomainDataSource>

6. Set the DomainContext for the DomainDataSource with the following XAML code.

複製代碼
XAML
Edit|Remove
<!-- XAML --><riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True" >    <riaControls:DomainDataSource.DomainContext>      <ds:OrganizationContext/>     </riaControls:DomainDataSource.DomainContext></riaControls:DomainDataSource>

7. Replace this DataGrid XAML:

複製代碼
XAML
Edit|Remove
<!-- XAML --><data:DataGrid Name="dataGrid1" MinHeight="100" IsReadOnly="True"></data:DataGrid>

with the following XAML:

複製代碼
XAML
Edit|Remove
<!-- XAML --><data:DataGrid Name="dataGrid1" MinHeight="100" IsReadOnly="True" Height="Auto" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />

8. Open EmployeeList.xaml.cs/vb.

9. In the constructor, remove or comment out the code to instantiate theOrganizationContext instance, the call to GetSalariedEmployeesQuery(), and the code to set the DataGrid'sItemsSource.

You no longer need to explicitly load data, since the DomainDataSource will do this automatically.

複製代碼
Visual BasicC#
Edit|Remove
'VBPartial Public Class EmployeeList    Inherits Page    'Dim _OrganizationContext As New OrganizationContext    Public Sub New()        InitializeComponent()            '_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeeQuery())        'Me.dataGrid1.ItemsSource = _OrganizationContext.Employees    End Sub
// C#//OrganizationContext _OrganizationContext = new OrganizationContext();public EmployeeList()        {            InitializeComponent();                      // this.dataGrid1.ItemsSource= _OrganizationContext.Employees;//_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeeQuery());                   }

10. Run the application and click the Employee List link. The application works as before.

Add Sorting/Filtering/Paging to the DataSource

1. Specify how data is sorted in the DataGrid by adding SortDescriptors to the DomainDataSource. Add the following XAML (in bold) to theDomainDataSource to sort the VacationHours column in Ascending order.

複製代碼
XAML
Edit|Remove
<!-- XAML --><riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True" >  <riaControls:DomainDataSource.DomainContext>    <ds:OrganizationContext/>   </riaControls:DomainDataSource.DomainContext>  <riaControls:DomainDataSource.SortDescriptors>    <riaControls:SortDescriptor PropertyPath="VacationHours" Direction="Ascending" />  </riaControls:DomainDataSource.SortDescriptors></riaControls:DomainDataSource>

2. Run the application and click the Employee List link. The data will be sorted by Vacation Hours and you can change the sort direction by clicking on the column header.

3. Add the XAML code in bold below to EmployeeList.xaml. That will add support for filtering.

複製代碼
XAML
Edit|Remove
<!-- XAML --><navigation:Page x:Class="HRApp.EmployeeList"      xmlns:ds="clr-namespace:HRApp.Web"      xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"       xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      mc:Ignorable="d"      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"      d:DesignWidth="640" d:DesignHeight="480"      Title="EmployeeList Page"><Grid x:Name="LayoutRoot" Background="White"><ScrollViewer BorderThickness="0"  VerticalScrollBarVisibility="Auto" Padding="12,0,12,0" Margin="-12">  <StackPanel Margin="0,12,0,12" Orientation="Vertical" >    <TextBlock Text="Employee List" Style="{StaticResource HeaderTextStyle}"/>      <StackPanel Orientation="Horizontal"                   HorizontalAlignment="Right"                   Margin="0,-16,0,0">         <TextBlock VerticalAlignment="Center"                     Text="Min Vacation Hours Filter" />         <TextBox x:Name="vacationHoursText" Width="75"                   FontSize="11" Margin="4" Text="0"/>      </StackPanel>      <riaControls:DomainDataSource             Name="employeeDataSource"             LoadSize="20"             QueryName="GetSalariedEmployees"             AutoLoad="True">        <riaControls:DomainDataSource.DomainContext>          <ds:OrganizationContext/>         </riaControls:DomainDataSource.DomainContext>        <riaControls:DomainDataSource.SortDescriptors>          <riaControls:SortDescriptor PropertyPath="VacationHours"                                   Direction="Ascending" />        </riaControls:DomainDataSource.SortDescriptors>       <riaControls:DomainDataSource.FilterDescriptors>         <riaControls:FilterDescriptor               PropertyPath="VacationHours"               Operator="IsGreaterThanOrEqualTo"              IgnoredValue=""              Value="{Binding ElementName=vacationHoursText, Path=Text}"  >         </riaControls:FilterDescriptor>       </riaControls:DomainDataSource.FilterDescriptors>      </riaControls:DomainDataSource>      <data:DataGrid MinHeight="100"                IsReadOnly="True"                ItemsSource="{Binding Data, ElementName=employeeDataSource}"               Name="dataGrid1" />  </StackPanel></ScrollViewer>        </Grid></navigation:Page>

4. Run the Application and filter the Employee List using the “Min Vacation Hours Filter” Text Box

5. Drag a DataPager from the toolbox on toEmployeeList.xaml. Add the DataPager just below theDataGrid.

6. Set the page size to 5 and set the source by adding the following XAML to theDataPager:

複製代碼
XAML
Edit|Remove
<!-- XAML --><br><br><data:DataPager PageSize="5" Source="{Binding Data, ElementName=employeeDataSource}" Margin="0,-1,0,0"></data:DataPager><br>

7. Run the application and click the employee list link. You will see only 5 rows of filtered data per page and pager controls below theDataGrid.

Master Detail

Adding a DataForm

We will be using the DataForm Control from the SL 3 Toolkit for the Detail View. The Silverlight Business Application Project Template carries the System.Windows.Controls.Data.DataForm.Toolkit.dll binary in the ‘Libs’ Folder, hence our Project already has access to the DataForm Control.

1. In the client project, open EmployeeList.xaml.

2. Add the following namespace declaration toEmployeeList.xaml.

複製代碼
XAML
Edit|Remove
<!-- XAML --> 
 
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit" 

3. After the DataPager control, add the XAML code below. The code adds the DataForm to the EmployeeList Page and sets the DataForm attributes and specifies the columns to be displayed.

<dataForm:DataForm x:Name="dataForm1" Header="Employee Information" AutoGenerateFields="False" AutoEdit="False" AutoCommit="False" CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}" Margin="0,12,0,0">

<dataForm:DataForm.EditTemplate>

<DataTemplate>

<StackPanel>

<dataForm:DataField Label="Employee ID">

<TextBox IsReadOnly="True"

Text="{Binding EmployeeID, Mode=OneWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Login ID">

<TextBox Text="{Binding LoginID, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Hire Date">

<TextBox Text="{Binding HireDate, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Marital Status">

<TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Gender">

<TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

<dataForm:DataField Label="Vacation Hours">

<TextBox Text="{Binding VacationHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

<dataForm:DataField Label="Sick Leave Hours">

<TextBox Text="{Binding SickLeaveHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

<dataForm:DataField Label="Active">

<CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

</StackPanel>

</DataTemplate>

</dataForm:DataForm.EditTemplate>

</dataForm:DataForm>

4. Run the application and click the employee list link. The DataForm displays details of the item selected in theDataGrid.

Updating the Database

Updating a record

Checking the Enable editing option in the New Domain Service Class wizard caused CUD methods to be generated automatically in the domain service layer (OrganizationService class). In order to use these methods to update the database, you will add editing buttons to the user interface of the employee list.

1. In the client project, open EmployeeList.xaml.

Add a ‘Submit’ button just after the DataForm tags by adding the following XAML code.

複製代碼
XAML
Edit|Remove
<!-- XAML --> 
 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0"> 
  <Button x:Name="submitButton" Width="75" Height="23"   
          Content="Submit" Margin="4,0,0,0" Click="submitButton_Click"/> 
                 
</StackPanel> 

3. Handle the button click event in EmployeeList.xaml.cs/vb by adding the following code:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Private Sub submitButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 
    employeeDataSource.SubmitChanges() 
End Sub 
// C# 
 
private void submitButton_Click(object sender, RoutedEventArgs e) 
{ 
    employeeDataSource.SubmitChanges(); 
} 

4. Run the application and click theEmployee List link. You can now modify any editable field by clicking on the pencil icon on the DataForm to put the form in edit mode. Make changes to the Employee data and clickOK when done with the edits. Click the Submit button to save the data.Changes are saved to the database on the server only when you click the ‘Submit’ button.

Adding Custom Methods to a Domain Service

1. In the HRApp.Web server project, open OrganizationService.cs/vb and add a custom method called ‘ApproveSabbatical’.

複製代碼
Visual BasicC#
Edit|Remove
'VB 
    Public Sub ApproveSabbatical(ByVal current As Employee) 
        Me.ObjectContext.Employees.AttachAsModified(current) 
        current.CurrentFlag = False 
    End Sub 
// C# 
        public void ApproveSabbatical(Employee current) 
        { 
              // Start custom workflow here 
            this.ObjectContext.Employees.AttachAsModified(current); 
            current.CurrentFlag = false;         
        } 

2. On the Build menu, selectBuild Solution.

3. In the client project, open EmployeeList.xaml.

4. Add an ‘Approve Sabbatical’ button by adding the following XAML code (in bold):

複製代碼
XAML
Edit|Remove
<!-- XAML --> 
 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0"> 
                <Button x:Name="submitButton" Width="75" Height="23"  Content="Save"  Margin="4,0,0,0" Click="submitButton_Click"/> 
                <Button x:Name="approveSabbatical" Width="115" Height="23"  Content="Approve Sabbatical"  Margin="4,0,0,0" Click="approveSabbatical_Click"/> 
            </StackPanel> 

5. Open EmployeeList.xaml.cs/vb.

6. Handle the button click event and call theApproveSabbatical method by adding the following code:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Private Sub approveSabbatical_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 
    Dim luckyEmployee As Employee 
    luckyEmployee = dataGrid1.SelectedItem 
    luckyEmployee.ApproveSabbatical() 
    employeeDataSource.SubmitChanges() 
End Sub 
// C# 
 
private void approveSabbatical_Click(object sender, RoutedEventArgs e) 
{ 
    Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); 
    luckyEmployee.ApproveSabbatical(); 
    employeeDataSource.SubmitChanges(); 
} 

7. Run the application and click theemployee list link. Click the ApproveSabbatical button and note that theCurrentFlag for the selected employee clears.

Validation

Basic Validation

The DataForm control has the ability to show validation errors that come from the Data Access Layer (DAL). For example, enter a non-integer value in the Vacation Hours field in the detail view and a validation error is displayed.

Checking the Generate associated classes for metadata option in theNew Domain Service Class wizard caused a file named OrganizationService.metadata.cs/vb to be generated automatically in theHRApp.Web project. You will add validation attributes to this file that will be enforced across application tiers.

1. In the HRApp.web project, openOrganizationService.metadata.cs/vb.

2. Add the following attributes to Gender and Vacation Hours:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
<Required()> _ 
Public Gender As String 
 
<Range(0, 70)> _ 
Public VacationHours As Short 
// C# 
 
[Required] 
public string Gender { get; set; } 
 
[Range(0, 70)] 
public short VacationHours { get; set; } 

3. On the Build menu, select Build Solution.

4. Run the application.

5. Click on the Employee List link. Select an employee and click the pencil icon in the upper right hand corner of the data form to enable editing. Enter a value into the Vacation Hours field that is not within the valid range (0-70). You will see a validation error. Also note that the Gender field is required and cannot be left empty.

Custom Validation

1. In Solution Explorer, right-click the HRApp.Web project, select Add, and then select New Item. The Add New Item dialog box is displayed.

2. In the Categories pane, selectCode, and in the Templates pane, select Code File. Name the new item ‘OrganizationService.shared.cs’ or ‘OrganizationService.shared.vb’ and clickAdd.

3. Add the following block of code to the file:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Imports System 
Imports System.ComponentModel.DataAnnotations 
 
Public Module GenderValidator 
    Public Function IsGenderValid(ByVal gender As String, ByVal context As ValidationContext) As ValidationResult 
        If gender = "M" OrElse gender = "m" OrElse gender = "F" OrElse gender = "f" Then 
            Return ValidationResult.Success 
        Else 
            Return New ValidationResult("The Gender field only has two valid values 'M'/'F'", New String() {"Gender"}) 
        End If 
    End Function 
End Module 
// C# 
using System; 
using System.ComponentModel.DataAnnotations; 
 
namespace HRApp.Web 
{ 
    public static class GenderValidator 
    { 
        public static ValidationResult IsGenderValid(string gender, ValidationContext context) 
        { 
            if (gender == "M" || gender == "m" || gender == "F" || gender == "f") 
            { 
                return ValidationResult.Success; 
            } 
            else 
            { 
                return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] {"Gender"});             
        } 
        } 
    } 
} 

Note: Since the file ends with ‘.shared.cs/vb’, the same code will be available to be consumed on the client as well as the server. We will be using this to run the same validation rule at both locations. (After you rebuild the solution, look in the hidden Generated_Code folder on the client, and you will see the OrganizationService.shared.cs/vb file present there as well and being compiled as part of the server project.)

4. Open OrganizationService.metadata.cs/vb.

5. Add a new custom validation attribute to the gender property by adding the following code (in bold).

複製代碼
Visual BasicC#
Edit|Remove
'VB 
<Required()> _ 
<CustomValidation(GetType(GenderValidator), "IsGenderValid")> _ 
Public Gender As String 
// C# 
[CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")] 
[Required] 
public string Gender { get; set; } 

6. On the Build menu, selectBuild Solution.

7. Run the application.

8. Click on the Employee List link. Enter a value for theGender field that is not ’M’ or ’F’.

Add a new record

You will now create a user interface to allow the addition of new employee records to the database. The validation rules that you added in the previous sections will automatically be applied in the new user interface.

1. In Solution Explorer, right-click the HRApp project, select Add, and then select New Item. TheAdd New Item dialog box is displayed.

2. In the Categories pane, selectSilverlight, and in the Templates pane, select Silverlight Child Window. Name the new item ‘EmployeeRegistrationWindow.xaml’ and clickAdd.

3. Open EmployeeRegistrationWindow.xaml.cs/vb and add the following using/Imports statement:

複製代碼
JavaScriptC#
Edit|Remove
'VB 
Imports System.Windows.Controls 
Imports System.Windows 
// C# 
using HRApp.Web; 

4. Add the following property in the code:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Public Property NewEmployee As Employee 
// C# 
public Employee NewEmployee { get; set; } 

5. Open EmployeeRegistrationWindow.xaml.

6. Hide the ChildWindow Close button by adding the XAML in bold below.

<controls:ChildWindow x:Class="HRApp.EmployeeRegistrationWindow"

Width="400" Height="300"

Title="EmployeeRegistrationWindow"HasCloseButton="False">

7. As we did for the Details view, here too we will be using the DataForm Control from the SL 3 Toolkit. The Silverlight Business Application Project Template carries the System.Windows.Controls.Data.DataForm.Toolkit binary in the ‘Libs’ Folder, hence our Project already has access to the DataForm Control.

Add the following namespace declaration to EmployeeRegistrationWindow.xaml:

複製代碼
XAML
Edit|Remove
<!-- XAML --> 
 
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit" 

8. Add the DataForm from to theEmployeeRegistrationWindow.xaml just above the ‘Cancel’ button using the XAML Code below.

<dataForm:DataForm x:Name="addEmployeeDataForm" AutoGenerateFields="False" AutoCommit="True" AutoEdit="True" CommandButtonsVisibility="None">

<dataForm:DataForm.EditTemplate>

<DataTemplate>

<StackPanel>

<dataForm:DataField Label="Login ID">

<TextBox Text="{Binding LoginID, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="National ID">

<TextBox Text="{Binding NationalIDNumber, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Title">

<TextBox Text="{Binding Title, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Marital Status">

<TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />

</dataForm:DataField>

<dataForm:DataField Label="Gender">

<TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

<dataForm:DataField Label="Salaried">

<CheckBox IsChecked="{Binding SalariedFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

<dataForm:DataField Label="Active">

<CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />

</dataForm:DataField>

</StackPanel>

</DataTemplate>

</dataForm:DataForm.EditTemplate>

</dataForm:DataForm>

9. Open EmployeeRegistrationWindow.xaml.cs/vband add the following code (in bold):

複製代碼
JavaScriptC#
Edit|Remove
'VB 
Partial Public Class EmployeeRegistrationWindow 
    Inherits ChildWindow 
 
    Public Sub New() 
        InitializeComponent() 
        NewEmployee = New Employee 
        addEmployeeDataForm.CurrentItem = NewEmployee 
        addEmployeeDataForm.BeginEdit() 
    End Sub 
 
    Public Property NewEmployee As Employee 
 
    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click 
        Me.addEmployeeDataForm.CommitEdit() 
        Me.DialogResult = True 
    End Sub 
 
    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click 
        NewEmployee = Nothing 
        addEmployeeDataForm.CancelEdit() 
        Me.DialogResult = False 
    End Sub 
 
End Class 
// C# 
 
public partial class EmployeeRegistrationWindow : ChildWindow 
    { 
        public Employee NewEmployee { get; set; } 
 
        public EmployeeRegistrationWindow() 
        { 
            InitializeComponent(); 
            NewEmployee = new Employee(); 
           addEmployeeDataForm.CurrentItem = NewEmployee; 
           addEmployeeDataForm.BeginEdit();     
        } 
 
        private void OKButton_Click(object sender, RoutedEventArgs e) 
        { 
            addEmployeeDataForm.CommitEdit();     
            this.DialogResult = true; 
        } 
 
        private void CancelButton_Click(object sender, RoutedEventArgs e) 
        { 
            NewEmployee = null; 
           addEmployeeDataForm.CancelEdit(); 
            this.DialogResult = false; 
        } 
    } 

10. Open EmployeeList.xaml.

11. Add a button called ‘addNewEmployee’ between theDataPager and the DataForm by adding the following XAML code.

複製代碼
XAML
Edit|Remove
<!-- XAML --> 
 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0"> 
    <Button x:Name="addNewEmployee" Width="90" Height="23"  Content="Add Employee"  Margin="4,0,0,0" Click="addNewEmployee_Click"/> 
</StackPanel> 

12. Open EmployeeList.xaml.cs/vb.

13. Handle the button click event to show theEmployeeRegistrationWindow by adding the following code:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Private Sub addNewEmployee_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 
    Dim addEmp As New EmployeeRegistrationWindow() 
    AddHandler addEmp.Closed, AddressOf addEmp_Closed 
    addEmp.Show() 
End Sub 
// C# 
 
private void addNewEmployee_Click(object sender, RoutedEventArgs e) 
{ 
    EmployeeRegistrationWindow addEmp = new EmployeeRegistrationWindow(); 
    addEmp.Closed += new EventHandler(addEmp_Closed); 
    addEmp.Show(); 
} 

14. Add the following method to handle theclosed event for the EmployeeRegistrationWindow:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Private Sub addEmp_Closed(ByVal sender As Object, ByVal e As System.EventArgs) 
    Dim emp As EmployeeRegistrationWindow = sender 
    If Not emp.NewEmployee Is Nothing Then 
        Dim _OrganizationContext As OrganizationContext = employeeDataSource.DomainContext 
        _OrganizationContext.Employees.Add(emp.NewEmployee) 
        employeeDataSource.SubmitChanges() 
    End If 
End Sub 
// C# 
 
void addEmp_Closed(object sender, EventArgs e) 
 
{ 
    EmployeeRegistrationWindow emp = (EmployeeRegistrationWindow)sender; 
    if (emp.NewEmployee != null) 
    { 
        OrganizationContext _OrganizationContext = (OrganizationContext)(employeeDataSource.DomainContext); 
        _OrganizationContext.Employees.Add(emp.NewEmployee); 
 employeeDataSource.SubmitChanges(); 
    } 
} 

15. In the HRApp.web project, openOrganizationService.cs/vb.

16. Add the following code (in bold) to theInsertEmployee method:

複製代碼
Visual BasicC#
Edit|Remove
'VB 
Public Sub InsertEmployee(ByVal employee As Employee) 
    'Modify the employee data to meet the database constraints. 
    employee.HireDate = DateTime.Now 
    employee.ModifiedDate = DateTime.Now 
    employee.VacationHours = 0 
    employee.SickLeaveHours = 0 
    employee.rowguid = Guid.NewGuid() 
    employee.ContactID = 1001 
    employee.BirthDate = New DateTime(1967, 3, 18) 
 
    If ((employee.EntityState = EntityState.Detached) = False) Then 
        Me.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added) 
    Else 
        Me.ObjectContext.Employees.AddObject(employee) 
    End If 
 
End Sub 
// C# 
 
      public void InsertEmployee(Employee employee) 
        { 
     // Modify the employee data to meet the database constraints. 
            employee.HireDate = DateTime.Now; 
            employee.ModifiedDate = DateTime.Now; 
            employee.VacationHours = 0; 
            employee.SickLeaveHours = 0; 
            employee.rowguid = Guid.NewGuid(); 
            employee.ContactID = 1001; 
            employee.BirthDate = new DateTime(1967, 3, 18); 
 
             if ((employee.EntityState != EntityState.Detached)) 
             { 
                this.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added); 
             } 
             else 
             { 
                this.ObjectContext.Employees.AddObject(employee); 
             } 
} 

17. Run the application.

18. Click the employee list link. You can now add new employees to the database by clicking the ‘Add Employee’ button. To ensure that the new employee appears in the list, mark the employee as Salaried. Earlier you modified the application to only load salaried employees.

Authentication

Authentication

1. Open OrganizationService.cs/vb

2. Add the RequiresAuthentication attribute on theApproveSabbatical method by adding the following code (in bold).

This ensures that only authenticated users can now call the ApproveSabbatical method on the server. If an anonymous user clicks on theApproveSabbatical button, the CurrentFlag for the selected employee will not be cleared.

複製代碼
Visual BasicC#
Edit|Remove
'VB 
<RequiresAuthentication()> _ 
Public Sub ApproveSabbatical(ByVal current As Employee) 
    Me.ObjectContext.Employees.AttachAsModified(current) 
    current.CurrentFlag = False 
End Sub 
// C# 
[RequiresAuthentication()] 
public void ApproveSabbatical(Employee current) 
{ 
    // Start custom workflow here 
    this.ObjectContext.Employees.AttachAsModified(current); 
    current.CurrentFlag = false; 
} 

3. In the client project, open EmployeeList.xaml.cs/vb.

4. Add the following using/Imports statements:

複製代碼
Visual BasicC#
Edit|Remove
'VB  
Imports System.ServiceModel.DomainServices.Client.ApplicationServices 
// C# 
using System.ServiceModel.DomainServices.Client.ApplicationServices; 
using HRApp.LoginUI; 

5. Modify the approveSabbatical_Click method with the following code: This will allow anonymous users to get authenticated and then approve a sabbatical. If the users do not have an existing user account they can create one using the Registration Dialog.

複製代碼
Visual BasicC#
Edit|Remove
'VB 
    Private Sub approveSabbatical_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) 
        If WebContext.Current.User IsNot Nothing AndAlso WebContext.Current.User.IsAuthenticated Then 
            Dim luckyEmployee As Employee = dataGrid1.SelectedItem 
            luckyEmployee.ApproveSabbatical() 
            employeeDataSource.SubmitChanges() 
        Else 
            AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted 
            Dim newWindow As New LoginRegistrationWindow 
            newWindow.Show() 
        End If 
    End Sub 
 
    Private Sub Current_LoginCompleted(ByVal sender As Object, ByVal e As AuthenticationEventArgs) 
        Dim luckyEmployee As Employee = dataGrid1.SelectedItem 
        luckyEmployee.ApproveSabbatical() 
        employeeDataSource.SubmitChanges() 
        RemoveHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted 
    End Sub 
//C# 
private void approveSabbatical_Click(object sender, RoutedEventArgs e)    
{ 
    if (WebContext.Current.User.IsAuthenticated) 
    { 
        Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); 
        luckyEmployee.ApproveSabbatical(); 
        employeeDataSource.SubmitChanges(); 
    } 
    else 
    { 
        WebContext.Current.Authentication.LoggedIn += Authentication_LoggedIn; 
        new LoginRegistrationWindow().Show(); 
    } 
} 
 
private void Authentication_LoggedIn(object sender, AuthenticationEventArgs e) 
{ 
    Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); 
    luckyEmployee.ApproveSabbatical(); 
    employeeDataSource.SubmitChanges(); 
     
    WebContext.Current.Authentication.LoggedIn -= Authentication_LoggedIn; 
} 

6. Run the application and click the employee list link.

7. Select an employee record and click the ‘Approve Sabbatical’ button. You are redirected to the login page.

8. Enter your credentials to login, or clickregister.

After login is completed, you are redirected to the Employee List page and the employee’s sabbatical is approved.

Completed Projects

The completed projects for both VB and C# can be found at:-

http://go.microsoft.com/fwlink/?LinkId=145481

WCF RIA Services

Microsoft WCF RIA Services simplifies the traditional n-tier application pattern by bringing together the ASP.NET and Silverlight platforms using WCF. The RIA Services provides a prescriptive pattern to write application logic that runs on the mid-tier and controls access to data for queries, changes and custom operations. It also provides end-to-end support for common tasks such as data validation, authentication and roles by integrating with Silverlight components on the client and ASP.NET on the mid-tier. It includes rich tooling for integrating client and mid-tier projects and for building rich UI through the simplicity of drag-drop support.

For the latest information please click here .

RIA Services Home Page with links to the download site, MSDN docs, talks ... can be found here.

For help porting applications to the latest bits - Breaking Changes from Beta(PDC 09) to RTW

The document above also insludes guidance on updating VS 2008/.NET 3.5 RIA Services applications to VS 2010/.NET 4

Please use the forums to provide feedback or post questions.

Sample download instructions

Please note that once you have downloaded a Sample.zip from below to your machine, you need to right click on the .zip, go to the Property Page and explicitly UnBlock the content. Only then should you extract the .zip file.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章