Answered WCF Data Service & derived entity

  • Monday, September 03, 2012 10:10 PM
     
     

    Is there a way to get derived types to show up in the service and be queryable the same way the base classes are, without passing through service operation?

    Thanks

All Replies

  • Tuesday, September 04, 2012 7:19 AM
    Moderator
     
     

    Not sure what should be the behavior you're asking for. Below is just a guess:

    Let's assume a service with namespace MyService has a type Person and a type Employee which derives from Person. And then an entity set People of type Person. If you query for ~/People you would get all instances of Person and all instances of Employee. If you query for ~/People/MyService.Employee you would get only the instances of Employee.

    Thanks,


    Vitek Karas [MSFT]

  • Tuesday, September 04, 2012 11:17 PM
     
      Has Code

    Thansk for your answer. Unfortunally People return all entity (People & Employee, Base & Derived) and Employee doesn't work. The only workaround that I found is to have a Service Operation like that

    [WebGet]
    public IQueryable<Employee> Employees()
    {
       return CurrentDataSource.People.OfType<Employee>();
    }

  • Wednesday, September 05, 2012 12:48 AM
     
     

    Are you sure you've constructed the query like Vitek said?

    ~/People/The.Fully.Qualified.TypeName.Employee should return the subset of Person instances that are of type Employee.

    The syntax is [EntitySet] + "/" + [Fully Qualified Derived TypeName]


    -Ian

  • Wednesday, September 05, 2012 7:34 AM
    Moderator
     
     

    One more note, this "type cast" feature requires OData V3, so make sure that you're using WCF Data Services 5.0 or higher (available for example on NuGet).

    Thanks,


    Vitek Karas [MSFT]

  • Thursday, September 06, 2012 10:58 AM
     
      Has Code

    I'm using Vs2012, Wcf Data Service 5.0 (OData V3).

    Calling http://localhost/MyDataService.svc/People/

    I get

      <?xml version="1.0" encoding="utf-8" ?> 
    - <feed xml:base="http://localhost/MyDataService.svc/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <id>http://localhost/MyDataService.svc/People/</id> 
      <title type="text">People</title> 
      <updated>2012-09-06T10:53:09Z</updated> 
      <link rel="self" title="People" href="People" /> 
    - <entry>
      <id>http://localhost/MyDataService.svc/People(1)</id> 
      <category term="MyModel.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
      <link rel="edit" title="Person" href="People(1)" /> 
      <title /> 
      <updated>2012-09-06T10:53:09Z</updated> 
    - <author>
      <name /> 
      </author>
    - <content type="application/xml">
    - <m:properties>
      <d:Id m:type="Edm.Int32">1</d:Id> 
      <d:Name>ANDY1</d:Name> 
      <d:Work>WORK1</d:Work> 
      </m:properties>
      </content>
      </entry>
    - <entry>
      <id>http://localhost/MyDataService.svc/People(2)</id> 
      <category term="MyModel.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
      <link rel="edit" title="Person" href="People(2)" /> 
      <title /> 
      <updated>2012-09-06T10:53:09Z</updated> 
    - <author>
      <name /> 
      </author>
    - <content type="application/xml">
    - <m:properties>
      <d:Id m:type="Edm.Int32">2</d:Id> 
      <d:Name>ANDY2</d:Name> 
      <d:Work>WORK2</d:Work> 
      </m:properties>
      </content>
      </entry>
    - <entry>
      <id>http://localhost/MyDataService.svc/People(3)</id> 
      <category term="MyModel.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
      <link rel="edit" title="Person" href="People(3)" /> 
      <title /> 
      <updated>2012-09-06T10:53:09Z</updated> 
    - <author>
      <name /> 
      </author>
    - <content type="application/xml">
    - <m:properties>
      <d:Id m:type="Edm.Int32">3</d:Id> 
      <d:Name>ANDY3</d:Name> 
      <d:Work>WORK3</d:Work> 
      </m:properties>
      </content>
      </entry>
    - <entry>
      <id>http://localhost/MyDataService.svc/People(4)</id> 
      <category term="MyModel.Person" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
      <link rel="edit" title="Person" href="People(4)" /> 
      <title /> 
      <updated>2012-09-06T10:53:09Z</updated> 
    - <author>
      <name /> 
      </author>
    - <content type="application/xml">
    - <m:properties>
      <d:Id m:type="Edm.Int32">4</d:Id> 
      <d:Name>ANDY4</d:Name> 
      </m:properties>
      </content>
      </entry>
      </feed>

    I'm calling http://localhost/MyDataService.svc/People/MyModel.Employee http://localhost/MyDataService.svc/People/Employees http://localhost/MyDataService.svc/People/MyModel.Employees ...but no way: where am I wrong? Thx.

  • Thursday, September 06, 2012 4:07 PM
    Moderator
     
     

    That looks correct. So couple of troubleshooting tips:

    - See if you can figure out the exact reason why it fails. This might help: http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx

    - Make sure that you enable V3 features on the server - in your InitializeService you should set the MaxProtocolVersion to V3.

    If you still can't figure it out, please follow the debugging tips above and post the actual error you get along with callstack.

    Thanks,


    Vitek Karas [MSFT]

  • Monday, September 10, 2012 1:54 PM
     
      Has Code

    Yes I'using V3 and all suggestion to debug...

        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
        public class MyDataService : DataService<MyModelContainer>
        {
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
                config.UseVerboseErrors = true;
                config.SetEntitySetAccessRule("*", EntitySetRights.All);
            }
        }
    

    But no way. No error with callstack. Just a stupid

    Server Error in '/' Application.

    The resource cannot be found.

    Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.           

    Requested URL: /MyDataService.svc/People/MyModel.Employee


    Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929

    ...I cannot figure out what I am wrong. Thanks.


  • Monday, September 10, 2012 2:23 PM
    Moderator
     
     Answered

    Actually one more idea:

    Are you by any chance trying this on the Visual Studio Web Development Server? It won't work there (this HTTP server has known limitations, one of which is the inability to correctly parse URLs with dots in them in all cases).

    The fix is very simple. Install IIS Express and change your project to use it. Or deploy the project to a real IIS.

    Thanks,


    Vitek Karas [MSFT]

  • Monday, September 10, 2012 7:53 PM
     
     

    If I deploy to a real IIS, it works perfectly!!!

    If I run from vs2012 using internal Visual Studio Development Server option, I get the described above behaviour.

    If I run from vs2012 using use lcoal IIS Web Server option I get immediately the following error. Why???


    Server Error in '/' Application.
    --------------------------------------------------------------------------------


     The resource cannot be found.
    Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

    Requested URL: /MyDataService.svc/


    --------------------------------------------------------------------------------
    Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929

  • Tuesday, September 11, 2012 7:38 AM
    Moderator
     
     

    I don't know... there's no difference between local IIS and what you call real IIS, they are both the same. Unless you're using IISExpress as the local option.

    Maybe ask that question on the VS forums or IIS...

    Thanks,


    Vitek Karas [MSFT]

  • Tuesday, September 11, 2012 9:39 AM
     
     

    Thanks a lot for you support!

    Last two question:

    - Do you have any suggestion for that? http://social.msdn.microsoft.com/Forums/is/adodotnetdataservices/thread/34e77056-6000-46ef-bc94-a69d9fc7db40

    - I need to pass to an operation service a string parameter: the source string can have ' \n \r " etc. Is there some function that clean or encode for me the string? HttpUtility.Encode doesn't work for this issue....

  • Tuesday, September 11, 2012 4:11 PM
    Moderator
     
     Answered

    Re the string: Try using Uri.EscapeDataString - that is the one which should be used in such situations.

    I'll take a look at the other question, but I'm no expert on the WCF Service itself...

    Thanks,


    Vitek Karas [MSFT]