wcf ria services complex type parameters

by dsoltesz 8. October 2011 00:07 >

I always seem to forget how to get complex types to work as parameters in wcf ria services sp1.  You first have to make sure you expose your complex type as an IEnumerable

public IQueryable<MyComplexType> ExposeComplexType()
        {
            //stub to expose complex type to client
            throw new NotSupportedException();
        }

Then in order to use the complex type as a parameter, you have to mark your domain service method with the Invoke attribute

 

 [Invoke]
        public IEnumerable<SomeEntity> QueryMyEntity(MyComplexType param)
        { return myObjects;}

Tags: , ,

.NET | wcf ria services

Deleting a parent entity and related child entities with RIA Services

by dsoltesz 22. September 2011 00:31 >

I created an extension that will allow you to traverse child entities easily so that you can remove each one from the parent.  Code is below.

 

public static class EntityExtensions { #region Static Methods (public) public static IEnumerable TraverseChildEntities ( this Entity parent, EntityContainer container ) { IEnumerable entityCollectionProperties = from p in parent.GetType( ).GetProperties( ) where p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition( ) == typeof ( EntityCollection<> ) select p; //// For every entity list, bind to the entity removed event foreach ( PropertyInfo property in entityCollectionProperties ) { var collectionType = property.PropertyType.GetGenericArguments()[0]; EntitySet set; if (!container.TryGetEntitySet(collectionType,out set)) { continue; } var entityCollection = ( IEnumerable )property.GetValue( parent, null ); foreach ( Entity entity in entityCollection ) { foreach ( Entity childEntity in entity.TraverseChildEntities(container ) ) { yield return childEntity; } yield return entity; } } } #endregion }

 With this extension in place now when I want to delete a parent entity and related child entities I can do somethig like this.

 

foreach (var child in new List(Parent.TraverseChildEntities(DomainContext.EntityContainer))) { DomainContext.EntityContainer.GetEntitySet(child.GetType()).Remove(child); } DomainContext.Parents.Remove(parent);

Tags: , ,

c# | silverlight | wcf ria services

Silverlight tabcontrol with scrollable tabItems

by dsoltesz 20. July 2010 18:31 >

I ran into an issue where I had more tab items than could fit within the desired width of my tab control.  Instead of all the tab items appearing on a single line, they would wrap and create a multiline affect which I did not want.  I wanted the user to be able to scroll through the tab items if needed.  I did some checking to see if someone had built or customized the silverlight toolkit to support this but I did not find anything, so I decided to create a custom tabcontrol with scrollable items.  Below is a picture of the default tab control and my custom scrollable tabcontrol.  Note: I have only modified the "Top" layout for the tabcontrol so if someone wants to use one of the other layouts, they will have to update accordingly.

 

Here is the code for the custom scrollable tab control.

file: ScrollableTab.xaml.cs


 [StyleTypedProperty(Property = "TabLeftButtonTopStyle", StyleTargetType = typeof(RepeatButton)),
     StyleTypedProperty(Property = "TabRightButtonTopStyle", StyleTargetType = typeof(RepeatButton)),
     TemplatePart(Name = "TabLeftButtonTop", Type = typeof(RepeatButton)),
	 TemplatePart(Name = "TabRightButtonTop", Type = typeof(RepeatButton)),
     TemplatePart(Name = "TabScrollViewerTop", Type = typeof(ScrollViewer)),
     TemplatePart(Name = "TabPanelTop", Type = typeof(TabPanel))]
    public class SlidingTabControl : System.Windows.Controls.TabControl
    {
		private RepeatButton tabLeftButton;
		private RepeatButton tabRightButton;
        private ScrollViewer tabScrollViewer;
        private TabPanel tabPanelTop;
        private double currentHorizontalOffset = 0;
        private double maxHorizontalOffset = 0;

        /// 
        /// Tab Top Left Button style
        /// 
        public static readonly DependencyProperty TabLeftButtonTopStyleProperty = DependencyProperty.Register(
            "TabLeftButtonTopStyle",
            typeof(Style),
            typeof(SlidingTabControl),
            new PropertyMetadata(null));

        /// 
        /// Tab Top Left Button style
        /// 
        public static readonly DependencyProperty TabRightButtonTopStyleProperty = DependencyProperty.Register(
            "TabRightButtonTopStyle",
            typeof(Style),
            typeof(SlidingTabControl),
            new PropertyMetadata(null));

        /// 
        /// Initializes a new instance of the  class.
        /// 
        public SlidingTabControl()
        {
            this.DefaultStyleKey = typeof(SlidingTabControl);
            this.SelectionChanged += new SelectionChangedEventHandler(SlidingTabControl_SelectionChanged);
        }

        /// 
        /// Gets or sets the Tab Top Left Button style.
        /// 
        /// The left button style style.
        [Description("Gets or sets the tab top left button style")]
        [Category("ScrollButton")]
        public Style TabLeftButtonTopStyle
        {
            get { return (Style)GetValue(TabLeftButtonTopStyleProperty); }
            set { SetValue(TabLeftButtonTopStyleProperty, value); }
        }

        /// 
        /// Gets or sets the Tab Top Right Button style.
        /// 
        /// The left button style style.
        [Description("Gets or sets the tab top right button style")]
        [Category("ScrollButton")]
        public Style TabRightButtonTopStyle
        {
            get { return (Style)GetValue(TabRightButtonTopStyleProperty); }
            set { SetValue(TabRightButtonTopStyleProperty, value); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            //remove old handlers
            if (null != this.tabLeftButton)
            {
                this.tabLeftButton.Click -= this.tabLeftButton_Click;
            }
            if (null != this.tabRightButton)
            {
                this.tabRightButton.Click -= this.tabRightButton_Click;
            }

            //add new handlers
            this.tabLeftButton = GetTemplateChild("TabLeftButtonTop") as RepeatButton;
            this.tabRightButton = GetTemplateChild("TabRightButtonTop") as RepeatButton;
            this.tabScrollViewer = GetTemplateChild("TabScrollViewerTop") as ScrollViewer;
            this.tabPanelTop = GetTemplateChild("TabPanelTop") as TabPanel;
            if (null != this.tabLeftButton)
            {
                this.tabLeftButton.Click += new RoutedEventHandler(tabLeftButton_Click);
            }
            if (null != this.tabRightButton)
            {
                this.tabRightButton.Click += new RoutedEventHandler(tabRightButton_Click);
            }

        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            var size = base.ArrangeOverride(finalSize);

            if (this.tabPanelTop != null && this.tabScrollViewer != null)
            {
                if (this.tabPanelTop.ActualWidth > this.tabScrollViewer.ActualWidth)
                {
                    maxHorizontalOffset = this.tabPanelTop.ActualWidth - this.tabScrollViewer.ActualWidth + 30;
                }
                SetScrollButtonVisibility();
            }

            return size;
        }
        private void SlidingTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SlidingTabControl tabControl = sender as SlidingTabControl;
            tabControl.Dispatcher.BeginInvoke(new Action(() => UpdateZIndex(sender as SlidingTabControl)));
        }
        private void tabRightButton_Click(object sender, RoutedEventArgs e)
        {
            if (null != this.tabScrollViewer && null != this.tabPanelTop)
            {
                currentHorizontalOffset = this.tabScrollViewer.HorizontalOffset + 25;
                if (currentHorizontalOffset > maxHorizontalOffset)
                    currentHorizontalOffset = maxHorizontalOffset;
                this.tabScrollViewer.ScrollToHorizontalOffset(currentHorizontalOffset);
                SetScrollButtonVisibility();
            }
        }
        private void tabLeftButton_Click(object sender, RoutedEventArgs e)
        {
            if (null != this.tabScrollViewer)
            {
                
                currentHorizontalOffset = this.tabScrollViewer.HorizontalOffset - 25;
                if (currentHorizontalOffset < 0)
                    currentHorizontalOffset = 0;
                
                this.tabScrollViewer.ScrollToHorizontalOffset(currentHorizontalOffset);
                SetScrollButtonVisibility();
            }
            
        }
        private void SetScrollButtonVisibility()
        {
            if (null != this.tabScrollViewer)
            {
                if (null != this.tabLeftButton)
                {
                    if (this.currentHorizontalOffset > 0)
                        this.tabLeftButton.Visibility = Visibility.Visible;
                    else
                        this.tabLeftButton.Visibility = Visibility.Collapsed;

                }
                if (null != this.tabRightButton)
                {
                    if (currentHorizontalOffset >= maxHorizontalOffset)
                    {
                        this.tabRightButton.Visibility = System.Windows.Visibility.Collapsed;
                    }
                    else
                    {
                        this.tabRightButton.Visibility = System.Windows.Visibility.Visible;
                    }
                }
            }
        }
        private void UpdateZIndex(SlidingTabControl tc)
        {
            if (tc != null)
            {
                foreach (TabItem tabItem in tc.Items)
                {
                    tabItem.SetValue(Canvas.ZIndexProperty, (tabItem == tc.SelectedItem ? tc.Items.Count : (tc.Items.Count - 1) - tc.Items.IndexOf(tabItem)));
                }
            }

        }

        
    }

 

file generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TabControl"
    xmlns:System_Windows_Controls_Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls"
    >

 

    <Style TargetType="local:SlidingTabControl">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                    <GradientStop Color="#FFFEFEFE" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFA3AEB9" Offset="0"/>
                    <GradientStop Color="#FF8399A9" Offset="0.375"/>
                    <GradientStop Color="#FF718597" Offset="0.375"/>
                    <GradientStop Color="#FF617584" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="5"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:SlidingTabControl">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualTop">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualBottom">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualLeft">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualRight">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid x:Name="TemplateTop" Visibility="Collapsed">
                         <Grid.ColumnDefinitions>
                          <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
       </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
       <RepeatButton Content="&lt;" x:Name="TabLeftButtonTop" Style="{TemplateBinding TabLeftButtonTopStyle}"/>
                            <ScrollViewer x:Name="TabScrollViewerTop" Grid.Column="1" IsTabStop="False" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden" >
                         <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelTop" Margin="20,2,2,-1" Canvas.ZIndex="1"/>
       </ScrollViewer>
       <RepeatButton Content="&gt;" x:Name="TabRightButtonTop" Style="{TemplateBinding TabRightButtonTopStyle}" Grid.Column="2"/>
                         <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0,0,3,3" MinWidth="10" MinHeight="10" Grid.Row="1" Grid.ColumnSpan="3">
                          <ContentPresenter x:Name="ContentTop" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                         </Border>
                         <Border x:Name="DisabledVisualTop" Background="#8CFFFFFF" CornerRadius="0,0,3,3" IsHitTestVisible="False" Opacity="0" Grid.Row="1" Grid.RowSpan="2" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateBottom" Visibility="Collapsed">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelBottom" Margin="2,-1,2,2" Grid.Row="1" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3,3,0,0" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentBottom" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualBottom" Background="#8CFFFFFF" CornerRadius="3,3,0,0" IsHitTestVisible="False" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateLeft" Visibility="Collapsed">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelLeft" Margin="2,2,-1,2" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" CornerRadius="0,3,3,0" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentLeft" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualLeft" Background="#8CFFFFFF" Grid.Column="1" CornerRadius="0,3,3,0" IsHitTestVisible="False" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateRight" Visibility="Collapsed">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelRight" Grid.Column="1" Margin="-1,2,2,2" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3,0,0,3" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentRight" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualRight" Background="#8CFFFFFF" CornerRadius="3,0,0,3" IsHitTestVisible="False" Margin="0" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

  
</ResourceDictionary>

 

Download code

SlidingTabControlDemo.zip (2.10 mb)

Tags: ,

c# | wcf ria services

Unable to debug Silverlight application

by dsoltesz 19. May 2010 16:29 >

I was recently working on a silveright application when I suddenly noticed that my breakpoints were not being hit.  It took me a little while to figure out what was going on. 

To enable silverlight debugging make sure.

1.  <compilation debug="true" targetFramework="4.0"/>

2. Go to your .Web project file in solution explorer, right click and select Property -> click the Web tab -> at the bottom you'll see the Debuggers section, make sure ASP.NET and Silverlight are checked.

Hope this saves some of you some time.

 

Tags: ,

wcf ria services

WCF Ria Services - Authentication - Add custom property and method to authenticated user

by dsoltesz 25. February 2010 23:24 >

In my silverlight application I'm using wcf ria services to handle my authentication.  I wanted to add a custom property and method to my User object and have it be available to my silverlight client.

RiaContext.Current.User.MyNewProperty 

RiaContext.Current.User.MyNewMethod. 

The default silverlight business application template will create a AuthenticationService.cs file for you.

[EnableClientAccess]

public class AuthenticationService : AuthenticationBase<User>

{

}

public class User : UserBase

{     

  // NOTE: Profile properties can be added for use in Silverlight application.

  // To enable profiles, edit the appropriate section of web.config file.

 

}

First I added my property to my user class and added an attribute to exclude it from profile usage

public class User : UserBase

{

  [ProfileUsage(IsExcluded = true)]

  public IEnumerable<string> Permissions { get; private set; }

}

I didn't want this property to be saved as part of the users profile back to a database so you can set this property attribute if you don't want to setup a profile provider in your web.config. Next I tried adding my custom method to my user class but when I went to access the property in my silverlight client, the method was not showing up.  Since we are using wcf ria services, if you want methods to show up on the client then you have to explictly say so by creating a *.shared.cs class.

So to get everything working:

First you will want to move your User class out ouf the AuthenticationService.cs file and into its own User.cs file.

Next, delare your User class as a partial class.  This is so we can add our custom method via a shared file. 

Create another file called User.Shared.cs and declare this as a partial class as well along with your custom method.

Now when everything gets compiled and generated, your custom property and custom method will be available on your silverlight client user object. 

Here is what each file should look like.

AuthenticationService.cs 

[EnableClientAccess]

public class AuthenticationService : AuthenticationBase<User>

{

 

}

User.cs

public partial class User : UserBase

    {

        public User()

        {

            List<string> permissions = new List<string>();

            permissions.Add("test");

            permissions.Add("test2");

 

            Permissions = permissions; 

        }

 

        // NOTE: Profile properties can be added for use in Silverlight application.

        // To enable profiles, edit the appropriate section of web.config file.

        [ProfileUsage(IsExcluded = true)]

        public IEnumerable<string> Permissions { get; private set; }

    }

 

User.Shared.cs

public partial class User

    {

        public bool HasPermission(string permission)

        { 

            if ((this.Permissions == null))

            {

                return false;

            }

            return System.Linq.Enumerable.Contains(Permissions, permission);

        }

    }

 

Build your app and in your silverlight client you will have your new property and method

RiaContext.Current.User.Permissions

RiaContext.Current.User.HasPermissions

Tags: , , ,

.NET | c# | silverlight | wcf ria services

WCF Ria Services - Active Directory Roles

by dsoltesz 26. January 2010 21:02 >

I ran into a issue using wcf ria services with windows authentication and getting the currently logged in users roles.  I followed the steps to enable windows authentication.

1. Change App.xaml to use Windows Authentication (By default the Silverlight Business Application template has Forms Authentication)

<Application.ApplicationLifetimeObjects>
        <app:RiaContext>
            <app:RiaContext.Authentication>
                <!--<appsvc:FormsAuthentication/>-->
                <appsvc:WindowsAuthentication/>
            </app:RiaContext.Authentication>
        </app:RiaContext>
</Application.ApplicationLifetimeObjects>

2. Change Web.config to use Windows Authentication

<!--The <authentication> section enables configuration
    of the security authentication mode used by
    ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>

3. Load current user.  In your app.xaml.cs

 // This will automatically authenticate a user when using windows authentication
 RiaContext.Current.Authentication.LoadUser(this.Application_UserLoaded, null);

After the user loaded I then wanted to access the users AD roles. 

/// <summary>
///     Invoked when the <see cref="LoadUserOperation"/> completes. Use this
///     event handler to switch from the "loading UI" you created in
///     <see cref="InitializeRootVisual"/> to the "application UI"
/// </summary>
    private void Application_UserLoaded(LoadUserOperation operation)
        {
           foreach (var r in RiaContext.Current.User.Roles)
            {
                //do something
            }
        }

 However, RiaContext.Current.User.Roles.Count was always zero

I had missed a key step in my configuration that tells your app which role provider to use.

4.  Setup windows role provider in web.config

<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider"/>

After adding this setting to my web.config, all of my AD roles now appeared in RiaContext.Current.User.Roles

 

 

Tags: , , ,

c# | wcf ria services

about the author

My name is Dan Soltesz, and I"m a consultant specializing in Microsoft technologies

  • Silverlight 2.0,3.0,4.0,5.0
  • Windows Phone 7,8
  • Windows 8
  • WPF
  • MVC / SPA
  • ASP.NET 2.0,3.0,3.5,4.0
  • WCF, WCF Ria Services
  • Entity Framework / EF Code First
  • C#
  • MVVM, Repository Pattern

to name a few.  On this site you will find links to sites/blogs that I read and my own attempt at writing some blogs that may help others as well as a few miscellaneous items.  If there is something that you need to know about me and cannot find on this site, please feel free to contact me.

page list

sponsors

month list

recentcomments

Comment RSS