Mike Bateman
Mike Bateman

Reputation: 380

ASP.Net WebAPI IIQueryable covert to POCO Objects

I have been using the WebAPI in ASP.Net to allow access to our Entity Framework Objects. The problem I am having is converting the objects to a custom POCO for our end customers to use. I need to convert the Entity Framework Object to a custom POCO.

For example in our SQL Database we have Tbl_Person with the following properties

PersonID FirstName SureName DateOFBirth AnnualSalary

This table maps to an Entity Framework class Person with the same properties. But I want to change the properties so that when a end customer accesses it they get a POCO like:

PersonID Name Age SalaryRange

I also want to keep the current features such as JSON & XMLoutput and allow for OData queries. I have been trying to 'Collect' the Odata Query and applyto my database context but this does not seem to be work correctly Please see code example below:

Imports System.Net
Imports System.Web.Http
Imports System.Data.Entity

Public Class PeopleData
    Inherits DbContext

    Public Property People() As DbSet(Of Person)

End Class

Public Class Person
    Public Property PersonID() As Integer
    Public Property FirstName() As String
    Public Property SureName() As String
    Public Property DateOFBirth() As Date
    Public Property AnnualSalary() As Integer
End Class

Public Class PeopleController
    Inherits System.Web.Http.ApiController

    Private db As New PeopleData

    Function GetPeople(query As OData.Query.ODataQueryOptions(Of Person)) As IQueryable(Of apiPerson)

        Dim pep = query.ApplyTo(db.People)
        Dim resPep As New List(Of apiPerson)
        For Each p In pep
            resPep.Add(New apiPerson(p))
        Next
        Return resPep.AsQueryable
    End Function

End Class

Public Class apiPerson

    Public Sub New(ByVal p As Person)
        PersonID = p.PersonID
        Name = p.FirstName & " " & p.SureName
        Age = Date.Now.Year - p.DateOFBirth.Year
        If p.AnnualSalary > 15000 Then
            SalaryRange = "High"
        Else
            SalaryRange = "Low"
        End If
    End Sub
    Public Property PersonID() As Integer
    Public Property Name() As String
    Public Property Age() As Integer
    Public Property SalaryRange() As String

End Class

I have two problems:

1) The API help pages don't populate and only produce this error: 'Sample not available.' I like the dynamic help pages & that they pick up code comments, this is a really quick and easy way to maintain documentation. How can I get them to work with the ApiPerson?

2) If I try /api/people?$filter=Age eq 29 I get an error Type 'MvcApiPeople.Person' does not have a property 'Age'. I understand that the LINQ Query is been passed to the 'Person' and that property does not exist but how can I 'Translate' queries to map to different properties in the actual Database Object?

Upvotes: 0

Views: 538

Answers (3)

Mike Bateman
Mike Bateman

Reputation: 380

After playing around with many different solutions I decided the simplest way to control the information that is made available on an API and still allow iQueryable is to control the data at database level or at class level with Data Contract annotations.

I actually created views in my database to render the data exactly how I want it to appear for end customers. I felt this had the best benefits for performance and speed of implementation.

Thank you to all the guys who offered suggestions.

Upvotes: 0

gurra777
gurra777

Reputation: 351

Regarding your question 1:

I think your problem is that the apiPerson-class is missing a parameterless constructor.

Also, I found a blog post with some information on how to customize sample generation when the default generation mechanism doesn't work:

http://blogs.msdn.com/b/yaohuang1/archive/2012/10/13/asp-net-web-api-help-page-part-2-providing-custom-samples-on-the-help-page.aspx.

Upvotes: 0

RaghuRam Nadiminti
RaghuRam Nadiminti

Reputation: 6793

Your action declaration should be

Function GetPeople(query As OData.Query.ODataQueryOptions(Of apiPerson)) As IQueryable(Of apiPerson)

i.e query parameter should be of type ODataQueryOptions (Of apiPerson) not ODataQueryOptions (Of Person).

Upvotes: 1

Related Questions