Data Access has been discontinued. Please refer to this page for more information.

This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.

By default, the ServiceStack layers generated with Service Wizard allow you to retrieve the data only for the persistent properties of a given entity. This means that, the navigational properties are neither exposed in the DTO classes, nor any queries are issued for related objects.

This article will show you how to extend the generated service for a given entity, in order to retrieve its objects with all of their navigational properties.

When your ServiceStack layer exposes multiple related entities, make sure to avoid circular references between the corresponding DTO classes.

Suppose you have a model based on the Northwind sample database, and your ServiceStack layer exposes service methods for the following entities: Order, OrderDetail and Customer. To extend the service of the Order entity, to retrieve the OrderDetail objects, and the Customer object related to each order, you can execute the following steps:

  1. In the DTOs project, add a class file called OrderDTO.partial.cs(.vb). In it file you will extend OrderDTO in a partial class. For example:

    using System;
    using System.Collections.Generic;
    namespace EntitiesModelServicesDTOs.CoreDTOs
    {
        public partial class OrderDTO
        {
            public CustomerDTO Customer { get; set; }
            public IList<OrderDetailDTO> OrderDetails { get; set; }
        }
    }
    
    Namespace CoreDTOs
        Partial Public Class OrderDTO
            Public Property Customer() As CustomerDTO
            Public Property OrderDetails() As List(Of OrderDetailDTO)
        End Class
    End Namespace
    
  2. In the DTOs project, add a class file called OrderServiceMessages.partial.cs(.vb). In it you will add request and response service messages that will be used in the new service method. For example:

    using System;
    using ServiceStack;
    using EntitiesModelServicesDTOs.CoreDTOs;
    using System.Collections.Generic;
    namespace EntitiesModelServicesDTOs.OrderServiceMessages
    {
        public partial class GetOrdersWithNavigation : IReturn<GetOrdersWithNavigationResponse>
        {
        }
        public partial class GetOrdersWithNavigationResponse
        {
            public IList<OrderDTO> Orders { get; set; }
        }
    }
    
    Imports ServiceStack
    Imports EntitiesModelServicesDTOs.CoreDTOs
    Namespace OrderServiceMessages
        Partial Public Class GetOrdersWithNavigation
            Implements IReturn(Of IList(Of OrderDTO))
        End Class
        Partial Public Class GetOrdersWithNavigationResponse
            Public Property Orders As IList(Of OrderDTO)
        End Class
    End Namespace
    
  3. In the project which holds the code base of the ServiceStack layer, add a new class file called OrderRepository.partial.cs(.vb). In it you will extend the generated repository related to the Order entity. The code in this step will override the GetAll() method inherited from the base repository class, in order to apply the fetch strategy, which specifies the navigational properties that should be loaded. For example:

    using ServiceStack.Model;
    using System.Collections.Generic;
    namespace ServiceStack.Demo.Repositories
    {
        public partial class OrderRepository
        {
            public IEnumerable<Order> GetAllWithNavigation()
            {
                this.fetchStrategy.LoadWith<Order>(o => o.OrderDetails);
                this.fetchStrategy.LoadWith<Order>(o => o.Customer);
                this.context.FetchStrategy = fetchStrategy;
                return base.GetAll();
            }
        }
    }
    
    Imports ServiceStack.Model
    Namespace Repositories
        Partial Public Class OrderRepository
            Public Function GetAllWithNavigation() As IEnumerable(Of Order)
                Me.fetchStrategy.LoadWith(Of Order)(Function(o) o.OrderDetails)
                Me.fetchStrategy.LoadWith(Of Order)(Function(o) o.Customer)
                Me.context.FetchStrategy = fetchStrategy
                Return MyBase.GetAll()
            End Function
        End Class
    End Namespace
    
  4. In the project which holds the code base of the ServiceStack layer, add a new class file called OrderService.partial.cs(.vb). In it you will extend the service for the Order entity and its implementation. Depending on whether your code is on C# or on VB, you can choose from the following options:

    • For C# - In the OrderService.partial.cs file, add a partial interface, which extends the generated IOrderServiceImplementation with the signature of the new service method:

        using System;
        using System.Linq;
        using System.Collections.Generic;
        using ServiceStack.Model;
        using EntitiesModelServicesDTOs.CoreDTOs;
        using EntitiesModelServicesDTOs.OrderServiceMessages;
        namespace ServiceStack.Demo
        {
            public partial interface IOrderServiceImplementation
            {
                GetOrdersWithNavigationResponse Get(GetOrdersWithNavigation request);
            }
        }
      
    • For VB - Open the OrderService.vb file and in the body of the ICategoryServiceImplementation interface, add the signature of the new service method:

        Public Interface IOrderServiceImplementation
            Property ServiceReference() As Service
            Function [Get](request As QueryOrders) As QueryResponse(Of OrderDTO)
            Function [Get](request As GetOrderById) As GetOrderByIdResponse
            Function Post(request As AddOrder) As HttpResult
            Sub Put(request As UpdateOrder)
            Sub Delete(request As DeleteOrder)
            '
            'The definition of the new service method.
            Function [Get](request As GetOrdersWithNavigation) As GetOrdersWithNavigationResponse
        End Interface
      

      On VB, if you re-generate the service layer, you will have to repeat this step.

  5. In the OrderService.partial.cs(.vb), extend the OrderServiceImplementation class with the actual implementation of the new service method:

    public partial class OrderServiceImplementation
    {
        public GetOrdersWithNavigationResponse Get(GetOrdersWithNavigation request)
        {
            List<ServiceStack.Model.Order> orders = this.repository
                                                        .GetAllWithNavigation()
                                                        .ToList();
            GetOrdersWithNavigationResponse responseOrders = new GetOrdersWithNavigationResponse();
            List<OrderDTO> orderDtos = new List<OrderDTO>();
            foreach (ServiceStack.Model.Order order in orders)
            {
                List<OrderDetailDTO> details = new List<OrderDetailDTO>();
                foreach (ServiceStack.Model.OrderDetail detail in order.OrderDetails)
                {
                    OrderDetailDTO detailDTO = detail.ConvertTo<OrderDetailDTO>();
                    details.Add(detailDTO);
                }
                OrderDTO orderDTO = order.ConvertTo<OrderDTO>();
                orderDTO.OrderDetails = details;
                orderDtos.Add(orderDTO);
            }
            responseOrders.Orders = orderDtos;
            return responseOrders;
        }
    }
    
    Imports EntitiesModelServicesDTOs.OrderServiceMessages
    Imports EntitiesModelServicesDTOs.CoreDTOs
    Partial Public Class OrderServiceImplementation
        Public Function [Get](ByVal request As GetOrdersWithNavigation) As GetOrdersWithNavigationResponse _
            Implements IOrderServiceImplementation.Get
            Dim orders As List(Of ServiceStack.Model.Order) = Me._repository _ 
                                                                .GetAllWithNavigation() _ 
                                                                .ToList()
            Dim responseOrders As New GetOrdersWithNavigationResponse
            Dim orderDtos As New List(Of OrderDTO)()
            For Each order As ServiceStack.Model.Order In orders
                Dim details As New List(Of OrderDetailDTO)()
                For Each detail As ServiceStack.Model.OrderDetail In order.OrderDetails
                    Dim detailDTO As OrderDetailDTO = detail.ConvertTo(Of OrderDetailDTO)()
                    details.Add(detailDTO)
                Next detail
                Dim _orderDTO As OrderDTO = order.ConvertTo(Of OrderDTO)()
                _orderDTO.OrderDetails = details
                orderDtos.Add(_orderDTO)
            Next order
            responseOrders.Orders = orderDtos
            Return responseOrders
        End Function
    End Class
    
  6. In the OrderService.partial.cs(.vb) file, extend the OrderService class with the call to the new service method:

    public partial class OrderService
    {
        public GetOrdersWithNavigationResponse Get(GetOrdersWithNavigation request)
        {
            return this.orderSvcImp.Get(request);
        }
    }
    
    Partial Public Class OrderService
        Public Function [Get](ByVal request As GetOrdersWithNavigation) As GetOrdersWithNavigationResponse
            Return Me._orderSvcImp.Get(request)
        End Function
    End Class
    
  7. In the web application that holds you ServiceStack layer, add a new class file called AppHost.partial.cs(.vb). In it you will extend the ServiceStack service host, in order to register a route for the new service method. This requires you to implement the RegisterCustomRoutes method. For example:

    using System;
    using EntitiesModelServicesDTOs.OrderServiceMessages;
    namespace ServiceStack.Demo
    {
        public partial class AppHost
        {
            partial void RegisterCustomRoutes(ref bool shouldRegisterDefaultRoutes)
            {
                shouldRegisterDefaultRoutes = true;
                this.Routes.Add<GetOrdersWithNavigation>(OrderService.OrdersBasePath + 
                                                           "/WithNavigation", ApplyTo.Get);
            }
        }
    }
    
    Imports EntitiesModelServicesDTOs.OrderServiceMessages
    Partial Public Class AppHost
        Private Sub RegisterCustomRoutes(ByRef shouldRegisterDefaultRoutes As Boolean)
            shouldRegisterDefaultRoutes = True
            Me.Routes.Add(Of GetOrdersWithNavigation)(OrderService.OrdersBasePath & _ 
                                                        "/WithNavigation", ApplyTo.Get)
        End Sub
    End Class
    
  8. Build your solution and start the web application for a test.

  9. The new service method can be tested on a URL similar to the following:

    http://localhost:<port_number>/Orders/WithNavigation