WCF Data Services: MaxProtocolVersion set at v2 despite Service set at v3. Ends up Throwing error on OfType()
Asked Answered
N

2

7

I'm having a problem that when I attempt to do a linq query against my odata service with the OfType() method, I get an error saying that the request isn't valid for a Version 2 service. I have created the WCF Data Service and have set the MaxProtocolVersion to v3.

public class TestDirectorySearch : DataService<TestDirectoryEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        config.SetEntitySetPageSize("*", 50);

        config.UseVerboseErrors = true;
        config.DataServiceBehavior.MaxProtocolVersion = System.Data.Services.Common.DataServiceProtocolVersion.V3;
    }
}

My edmx has the following line:

<edmx:DataServices m:DataServiceVersion="1.0" 
    m:MaxDataServiceVersion="3.0" 
    xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">

When I attempt to do the following query I get an error saying that the "The method 'OfType' is not supported when MaxProtocolVersion is less than '3.0'."

from test in context.Tests.OfType<OrderableTest>()
    where test.TestRevisionId.Equals(mmt.RevisionId)
    select new
    {
            Reflex = test.ReflexTest
            , ShipTemp = (test.SpecimenTemperature == null) ? null : test.SpecimenTemperature.DisplayDescription
    }).FirstOrDefault();

If I check the MaxProtocolVersion of my context, it is set at v2. At what point is this failing? What can I do to set this correctly?

Exact error:

{"The method 'OfType' is not supported when MaxProtocolVersion is less than '3.0'."}

Requested stack trace:

at System.Data.Services.Client.ResourceBinder.AnalyzeOfType(MethodCallExpression mce, DataServiceProtocolVersion maxProtocolVersion)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitMethodCall(MethodCallExpression m)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ResourceBinder.AnalyzeProjection(MethodCallExpression mce, SequenceMethod sequenceMethod, Expression& e)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitMethodCall(MethodCallExpression m)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ResourceBinder.Bind(Expression e, DataServiceContext context)
at System.Data.Services.Client.DataServiceQueryProvider.Translate(Expression e)
at System.Data.Services.Client.DataServiceQuery`1.Translate()
at System.Data.Services.Client.DataServiceQuery`1.Execute()
at System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at System.Data.Services.Client.DataServiceQueryProvider.ReturnSingleton[TElement](Expression expression)
at System.Data.Services.Client.DataServiceQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
at TDMixBLL.TestDirectoryServiceHandler.PopulateOrderableTestInfo(MonitoredMixTest mmt) in C:\Dev\TDMix\ANSR - TDMix\TDMix2\TDMixBLL\TDMixBLL\TestDirectoryServiceHandler.cs:line 161
at TDMixBLL.TestDirectoryServiceHandler.PopulateTestInfo(MonitoredMixTest test) in C:\Dev\TDMix\ANSR - TDMix\TDMix2\TDMixBLL\TDMixBLL\TestDirectoryServiceHandler.cs:line 124
at TDMixBLL.TestDirectoryServiceHandler.GetTest(Int64 testRevisionId) in C:\Dev\TDMix\ANSR - TDMix\TDMix2\TDMixBLL\TDMixBLL\TestDirectoryServiceHandler.cs:line 112
at TDMixBLL.TestDirectoryServiceHandler.PopulateTests(List`1 testsToPopulate) in C:\Dev\TDMix\ANSR - TDMix\TDMix2\TDMixBLL\TDMixBLL\TestDirectoryServiceHandler.cs:line 66
at TDMix2.Tests.TestRetrievalTests.TestPopulate() in C:\Dev\TDMix\ANSR - TDMix\TDMix2\TDMix2.Tests\TestRetrievalTests.cs:line 38
Nightwear answered 7/6, 2012 at 14:59 Comment(2)
Can you please post the exact error you're getting - with stack trace? Thanks.Scincoid
@VitekKarasMSFT I have added the requested stack trace. Thank you.Nightwear
S
8

This is an error on the client. The DataServiceContext has to be constructed with V3 in order to support V3 features (like OfType). DataServiceContext has a new constructor overload which takes the MaxProtocolVersion parameter. Make sure that you use it and pass in V3.

Scincoid answered 8/6, 2012 at 9:6 Comment(8)
Thanks for the response, sorry about the length in my reply as I was moving through a sprint and couldn't return to this problem. I only have one constructor for DataServiceContext. I noticed when I add a reference to the service that a reference to System.Data.Service.Client keeps getting added. It is possible this is why I am not getting the new constructor. What can I do to stop this reference from being added?Nightwear
Yes - the assembly has to be called Microsoft.Data.Services.Client in order for you to get the V3 features. You can either manually replace the assembly references, or even better install the WCF Data Services 5.0 setup (not just the NuGet) which should update the VS components inside Add Service Reference to work with V3 features as expected.Scincoid
I figured that's what it was. I keep finding posts about the MSI about to be released, but I'm not finding the MSI itself. Any hints on that one for me?Nightwear
I found the MSI at microsoft.com/en-us/download/details.aspx?id=29306. However, a link msdn.microsoft.com/en-us/data/ee720179 here would also be nice.Nightwear
I don't see the new overloaded constructor in my client. I'm referencing Microsoft.Data.Services.Client and my WCFService is wrapping an EF Code First Model. On the client if I check the read only property MaxProtocolVersion I can see its V2 still, but my constructor only accepts Uri as a parameter. I'm using the latest 5.0.2 build from NuGet in VS2010. Any ideas ?Claqueur
I don't know what's wrong - please check the version of the assembly you're referencing. Also take a look at it in the object browser if it really doesn't have the constructor overload.Scincoid
@Claqueur I had the same problem. I ended up needing to install the msi linked above. You can try and just create a dataservicecontext, but that means you don't have your strongly typed mappings. YOu could also edit your Reference.cs's main constructor to pass in the V3. If you ever update your service reference, that will disappear, however.Nightwear
Another option is to add another constructor in your own partial class extension. Don't forget the 3 lines in the middle. public MyEntities(string uri): base(new Uri(uri), DataServiceProtocolVersion.V3) { this.ResolveName = new global::System.Func<global::System.Type, string>(this.ResolveNameFromType); this.ResolveType = new global::System.Func<string, global::System.Type>(this.ResolveTypeFromName); this.OnContextCreated(); }Nightwear
N
4

In addition to installing the MSI as above, you can find your way into the Nuget constructur you're looking for by extending the partial class

namespace Project.ServiceReference
{
    public partial class MyEntities : global::System.Data.Services.Client.DataServiceContext
    {
        public TestDirectoryEntities(string uri)
            : base(new Uri(uri), DataServiceProtocolVersion.V3)
        {
            this.ResolveName = new global::System.Func<global::System.Type, string>(this.ResolveNameFromType);
            this.ResolveType = new global::System.Func<string, global::System.Type>(this.ResolveTypeFromName);
            this.OnContextCreated();
        }
    }
}

The 3 lines are copied directly from the Reference.cs.

Nightwear answered 4/2, 2013 at 22:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.