Sonntag, 18. April 2010

Changes of WCF RIA Services for Visual Studio 2010

With the new version of the WCF RIA Services for Visual Studio 2010, that comes last Friday, there are several changes.

Assemblies and Namespaces

Assembly Rename & Refactoring

Previous Assembly Name

New Assembly Name

System.Windows.Ria

System.ServiceModel.DomainServices.Client + System.ServiceModel.DomainServices.Client.Web

System.Windows.Controls.Ria

System.Windows.Controls.DomainServices

System.Web.Ria

System.ServiceModel.DomainServices.Server + System.ServiceModel.DomainServices.Hosting

System.Web.DomainServices

System.ServiceModel.DomainServices.Server

System.Web.DomainServices.EntityFramework

System.ServicesModel.DomainServices.EntityFramework

System.Web.DomainServices.LinqToSql

Microsoft.ServiceModel.DomainServices.LinqToSql

System.Web.DomainServices.Proxies

Microsoft.ServiceModel.DomainServices.Hosting.Local

System.Windows.Controls.Ria.Design

System.Windows.Controls.DomainServices.Design

System.Windows.Controls.Ria.Expression.Design

System.Windows.Controls.DomainServices.Expression.Design

System.Windows.Controls.Ria.VisualStudio.Design

System.Windows.Controls.DomainServices.VisualStudio.Design

Namespace Rename & Refactoring

Previous Namespace Name

New Namespace Name

System.Web.DomainServices

System.ServiceModel.DomainServices.Server

System.Web.DomainServices.Providers

System.ServiceModel.DomainServices.EntityFramework (for LinqToEntities classes)

Microsoft.ServiceModel.DomainServices.LinqToSql (for LinqToSql classes)

System.Web.Ria

System.ServiceModel.DomainServices.Hosting

System.Web.Ria.ApplicationServices

System.ServiceModel.DomainServices.Server.ApplicationServices

System.Web.Ria.Data

Namespace removed.

DomainIdentifierAttribute and ExternalReferenceAttribute moved to System.ServiceModel.DomainServices.

CompositionAttribute moved to System.ComponentModel.DataAnnotations.

OperationError renamed to ValidationResultInfo and now available in both System.ServiceModel.DomainServices.Client and System.ServiceModel.DomainServices.Server.

System.Web.Ria.Services

System.ServiceModel.DomainServices.Hosting

System.Windows.Controls.Ria

System.Windows.Controls

System.Windows.Data

System.Windows.Controls

System.Windows.Ria

System.ServiceModel.DomainServices.Client

System.Windows.Ria.ApplicationServices

System.ServiceModel.DomainServices.Client.ApplicationServices

System.Windows.Ria.Services

System.ServiceModel.DomainServices.Client

Changed how the Silverlight application is notified of validation errors

In the previous release, validation rules on data were enforced on the client by raising an exception when the validation rule was not met. In the RC release, validation rules are enforced by raising events through the INotifyDataErrorInfo interface, which is new in Silverlight 4. With this approach, The INotifyDataErrorInfo.ErrorsChanged event is raised when an invalid value is assigned to a property. Any where in your code that checks for a ValidationException will now likely need to change as an event is raised instead of the exception.

An overloaded version of the ValidateProperty method was added that accepts a ValidationContext parameter. The generated code was changed so this ValidateProperty method is called between the Changing and Changed events. If you want to retain exception-based validation, you can override the ValidateProperty method and raise an exception for invalid values, as shown below.

 

   1: public partial class City
   2: {
   3:     protected override void ValidateProperty(ValidationContext validationContext,
   4:     object value)
   5:     {
   6:         ValidationContext context = new ValidationContext(this, null, null) { MemberName = propertyName };
   7:         // Validate in a way that will throw an exception if invalid
   8:         System.ComponentModel.DataAnnotations.Validator.ValidateProperty(value,context);
   9:  
  10:     }
  11:  
  12: }

When you create a custom validation class or attribute, you must now pass to the Silverlight application the name or names of the members that failed validation. You pass the names back with the ValidationResult, as shown below.

 

   1: public static class GenderValidator
   2: {
   3:     public static ValidationResult IsGenderValid(string gender, ValidationContext context)
   4:     {
   5:         if (gender == "M" || gender == "m" || gender == "F" || gender == "f")
   6:         {
   7:  
   8:             return ValidationResult.Success;
   9:  
  10:         }
  11:         else
  12:         {
  13:  
  14:             return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
  15:         }
  16:  
  17:     }
  18:  
  19: }

Removal of Resolve methods from DomainService

In the previous release, you could provide a method for customizing how concurrency conflicts are resolved. For the RC release, this feature and all related members have been removed. Providing a common method signature for resolving conflicts in different types of DALs could not be supported in this release.

Changed server communication from SOAP with binary encoding to REST with binary encoding

In the previous release, communication between the client and server was implemented using SOAP with binary encoding. This implementation did not allow clients to cache the response because all requests were performed using POST. In the RC release, the communication has been changed to REST with binary encoding. You can now specify whether the request is performed using GET or POST. By default, queries will use GET, and invoke operations will use POST. You specify whether GET or POST is used by setting the HasSideEffects property.

To inform clients of a DomainService that they can cache a response, you must apply the OutputCache attribute to the operation.

You must rebuild existing client and server projects to accommodate this change, and add a reference to the System.ServiceModel.Web.Extensions.dll assembly in the client project. If you implemented a customized client, you will need to either change to the new protocol or implement and EndpointFactory similar to the one used in the previous release.

Changed default Endpoint for all domain services

In the RC release, by default, only the Binary endpoint is enabled for domain services. To use the Binary endpoint no additional configuration is needed. If you want to use another endpoint (such as JSON, SOAP, or a custom host) you must register an endpoint factory in the Web.config file as shown below:

 

   1: <system.serviceModel>
   2:   <domainservices>
   3:     <endpoints>
   4:       <add name="json" type="Microsoft.ServiceModel.DomainService.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainService.Hosting" />
   5:     </endpoints>
   6:   </domainservices>
   7:   <system.serviceModel>

Removal of ChangeSet parameter from DomainService methods

In the previous release, the AuthorizeChangeSet, ExecuteChangeSet, PersistChangeSet, and ValidateChangeSet methods on the DomainService class all contained a parameter for a ChangeSet object. The ChangeSet parameter has been removed from the methods. The parameter is not needed because the ChangeSet object is now retrieved through the ChangeSet property.

Removal of QueryCompletedResult.ResultCount Property

The ResultCount property on the QueryCompletedResult class was removed. You can retrieve the same value through the Entity.Count property.

DomainDataSource no longer blocks loads when another load is pending

In the previous release, the CanLoad property of the DomainDataSource was false when IsLoadingData is true. This implementation prevented executing a new load operation when another load was in progress. This behavior has been changed for the next release. Now, if a new load is invoked when another load is pending, the previous load is canceled and the new load supersedes it. To retain the old behavior of blocking a new load operation, check the IsLoadingData property before calling the Load method.

IgnoreOperation renamed to Ignore

IgnoreOperationAttribute has been renamed to IgnoreAttribute:

[IgnoreOpration] -> [Ignore]

DomainServiceDescriptionProvider and MetadataProvider combined into a single class

The DomainServiceDescriptionProvider class and the MetadataProvider class have been combined into the DomainServiceDescriptionProvider class. Anyone who has created a class that derives from DomainServiceDescriptionProvider or MetadataProvider will have to adapt the derived class for this change. As a result of this change, the following classes were also removed:

  • MetadataProviderAttribute
  • LinqToEntitiesTypeDescriptionProvider
  • LinqToSqlTypeDescriptionProvider

If you applied the LinqToEntitiesMetadataProvider or LinqToSqlMetadataProvider attribute, you must now use either the LinqToEntitiesDomainServiceDescriptionProvider or LinqToSqlDomainServiceDescriptionProvider attribute.

Load method on DomainContext now has strongly-typed callback parameter

Previously, one of the overloaded Load methods on the DomainContext accepted a parameter of type Delegate for the callback method. Now, that parameter is strongly-typed and accepts a parameter of the type Action<LoadOperation> or Action<LoadOperation<EntityType>>.

Invoke signatures changed on DomainClient and DomainService

In the previous release, the Invoke method contained distinct parameters for invoke operation arguments. Now, the Invoke methods accept a parameter object that contains those arguments. You create a new instance of the InvokeArgs class and pass it as a parameter when calling BeginInvoke or BeginInvokeCore on DomainClient. You create a new instance of the InvokeDescription class and pass it as a parameter when calling Invoke on the DomainService.

Removed EnableClientAccessAttribute.ServiceName property

The EnableClientAccessAttribute.ServiceName property has been removed. Instead, use the ServiceContractAttribute.Name property.

SubmitChanges on DomainDataSource no longer automatically reloads data

In the RC release, the DomainDataSource no longer automatically reloads the data when the SubmitChanges method successfully completes. You can reload the data after submitting changes by calling the Load method from an event handler for the SubmittedChanges event.

‘new’ keyword no longer permitted on entity properties

In the previous release, the new keyword was permitted on entity properties to allow polymorhphic property access in the server code. In the RC release, the new keyword is no longer permitted. An InvalidOperationException is raised if new is applied to an entity property.

Count<T>( ) method no longer automatically called by DomainService.Query( )

In the previous release, the Count<T> method was automatically called by the DomainService.Query method so the TotalEntitiesCount property on DomainClientResult could be set. In the RC release, the Count<T> method is no longer automatically called, and therefore the TotalEntitiesCount property is not set. This change was made to improve performance. To explicitly request that the Count method is called, you can set the IncludeTotalCount property on the EntityQuery to true.

Removal of DomainOperationEntry.IsAuthorized and addition of DomainService.IsAuthorized

The IsAuthorized method was moved from DomainOperationEntry to DomainService. The method signature was changed to:

public AuthorizationResult IsAuthorized(DomainOperationEntry domainOperationEntry, object entity)

The entity parameter can be null so a custom class that derives from AuthorizationAttribute must tolerate a null value for AuthorizationContext.Instance.

Generated code changed for domain services that derive from LinqToEntitiesDomainService

The code that is generated when you use the DomainService Wizard to create a domain service that exposes Entity Framework classes has changed. In the previous release, the generated code assumed a single entity set. In the RC release, you can set the correct entity set for an entity in your code. The AttachAsModified extension method was also changed so it no longer assumes an instance of EntityObject. There were no changes to the generated code for the default query method. The following table shows the previous code generation and the new code generation. If you created your domain service manually, you must make this changes in your code.

Changes to DomainDataSource

The DomainDataSource class includes several changes that were were made to leverage Silverlight 4 features - DependencyObject data binding and Commanding. The following changes were made for the RC release:

  1. DomainDataSource.SubmitChanges() No Longer Causes a Reload

The SubmitChanges method on DomainDataSource has been changed so that it will not automatically invoke a reload when it completes successfully. Equivalent behavior can be achieved by invoking the Load method from the SubmittedChanges event

  1. Descriptors changed to DependencyObjects

The FilterDescriptor, GroupDescriptor, Parameter, and SortDescriptor have been changed to DependencyObjects. This makes all their properties available for data binding. For instance, FilterDescriptor.Value can now be bound directly instead of requiring the use of a ControlParameter.

Was

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo">
   2:   <dds:ControlParameter ControlName="textBox1" ParameterName="Text"
   3:       RefreshEventName="TextChanged" />
   4: </dds:FilterDescriptor>

Now

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo"
   2:     Value="{Binding ElementName=textBox1, Path=Text}" />

FilterDescriptor.Value, GroupDescriptor.PropertyPath, and SortDescriptor.PropertyPath are no longer Parameter types. Instead each has been made an Object or String as appropriate. To access the properties in code, you now use descriptor.Value instead of descriptor.Value.Value.

Additionally, the FilterDescriptorCollection, GroupDescriptorCollection, ParameterCollection, and SortDescriptorCollection have all been made into DepedencyObjectCollections to facilitate the new binding behavior. This has rendered the following types obsolete, and they have been removed from the framework:

· ControlParameter

· ObservableItemCollection

· ItemChangedEventArgs

· ParameterTypeConverter

  1. FilterDescriptors made read-only

The FilterDescriptors property on DomainDataSource is now always initialized to a non-null value and is no longer settable.

Was

   1: <dds:DomainDataSource.FilterDescriptors>
   2:   <dds:FilterDescriptorCollection>
   3:     <dds:FilterDescriptor ...="" />
   4:     <dds:FilterDescriptor ...="" />
   5:   </dds:FilterDescriptorCollection>
   6: </dds:DomainDataSource.FilterDescriptors>
   7:  
   8:  
   9:  

Now

   1: <dds:DomainDataSource.FilterDescriptors>
   2:   <dds:FilterDescriptor ...="" />
   3:   <dds:FilterDescriptor ...="" />
   4: </dds:DomainDataSource.FilterDescriptors>
   5:  

LogicalOperator moved from FilterDescriptorCollection to DomainDataSource

The LogicalOperator property on the FilterDescriptorCollection has been relocated to the DomainDataSource. The property is now named FilterOperator.

Was

   1: <dds:DomainDataSource ...="">
   2:   <dds:DomainDataSource.FilterDescriptors>
   3:     <dds:FilterDescriptorCollection LogicalOperator="Or">
   4:       <dds:FilterDescriptor ...="" />
   5:     </dds:FilterDescriptorCollection>
   6:   </dds:DomainDataSource.FilterDescriptors>
   7: </dds:DomainDataSource>

Now

   1: <dds:DomainDataSource FilterOperator="Or" ...="">
   2:   <dds:DomainDataSource.FilterDescriptors>
   3:     <dds:FilterDescriptor ...="" />
   4:   </dds:DomainDataSource.FilterDescriptors>
   5: </dds:DomainDataSource>
  1. ModifiedFilterParameters and ModifiedQueryParameters removed

The ModifiedFilterParameters and ModifiedQueryParameters properties have been removed from LoadingDataEventArgs and LoadedDataEventArgs.

  1. FilterDescriptor.IgnoreValue default value changed to FilterDescriptor.DefaultIgnoredValue

The default behavior of the IgnoredValue property on the FilterDescriptor has changed to prevent unintended matching. Previously, the default IgnoredValue was an empty string. Now, it defaults to FilterDescriptor.DefaultIgnoredValue.

If you expect an empty string to be ignored by the filter, you are now required to explicitly set the IgnoredValue.

Was

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo">
   2:   <dds:ControlParameter ControlName="textBox1" ParameterName="Text"
   3:       RefreshEventName="TextChanged" />
   4: </dds:FilterDescriptor>

Now

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo"
   2:     IgnoredValue=""
   3:     Value="{Binding ElementName=textBox1, Path=Text}" />
   4:  
  1. Descriptor validation moved to DomainDataSource.Load

A majority of the validation for the FilterDescriptor, GroupDescriptor, Parameter, and SortDescriptor types has been moved to the Load method on the DomainDataSource. If a descriptor is not defined when the Load method is invoked, an error will be raised in the LoadedData event.

When the DomainDataSource is auto-loading, a few immediate validation checks are performed. The PropertyPaths must all be valid. Also, if FilterDescriptor.Value or Parameter.Value cannot be converted to the underlying property type, the auto-load will be postponed until the conversion is successful.

1 Kommentar:

  1. Hi
    What do you think about this
    http://forums.silverlight.net/forums/p/168648/398720.aspx#398720
    I can't find a solution for filter
    sandus
    ssandu@msn.com
    Thank's

    AntwortenLöschen