smoksnes
smoksnes

Reputation: 10851

Error when consuming OData service - There is a type mismatch between the client and the service

I'm trying to consume a OData V4-service. The service has this relevant metadata:

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Some.Name.Space">
            <EntityType Name="StatisticalProgram">
                <Key>
                    <PropertyRef Name="Id"/>
                </Key>
                <Property Name="Name" Type="Edm.String"/>
                <Property Name="ShortName" Type="Edm.String"/>
                <Property Name="Deployed" Type="Edm.Boolean" Nullable="false"/>
                <Property Name="CreatedBy" Type="Edm.String"/>
                <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false"/>
                <Property Name="UpdateBy" Type="Edm.String"/>
                <Property Name="UpdatedDate" Type="Edm.DateTimeOffset"/>
                <Property Name="Id" Type="Edm.Guid" Nullable="false"/>
            </EntityType>
       // Other....

Which I'm trying to map to this model:

[DataServiceKey("Id")]
public class StatisticalProgram
{
    public string Name { get; set; }
    public Guid Id { get; set; }
    public string ShortName { get; set; }
}

I'm using Fiddler to sniff the request, and both the request and the response looks ok, but I get this error:

There is a type mismatch between the client and the service. Type '[Namespace].StatisticalProgram' is not an entity type, but the type in the response payload represents an entity type. Please ensure that types defined on the client match the data model of the service, or update the service reference on the client.

Everything works great if I use another source, like odata.org.

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="ODataDemo">
            <EntityType Name="Product">
                <Key>
                    <PropertyRef Name="ID"/>
                </Key>
                <Property Name="ID" Type="Edm.Int32" Nullable="false"/>
                <Property Name="Name" Type="Edm.String"/>
                <Property Name="Description" Type="Edm.String"/>
                <Property Name="ReleaseDate" Type="Edm.DateTimeOffset" Nullable="false"/>
                <Property Name="DiscontinuedDate" Type="Edm.DateTimeOffset"/>
                <Property Name="Rating" Type="Edm.Int16" Nullable="false"/>
                <Property Name="Price" Type="Edm.Double" Nullable="false"/>
                <NavigationProperty Name="Categories" Type="Collection(ODataDemo.Category)" Partner="Products"/>
                <NavigationProperty Name="Supplier" Type="ODataDemo.Supplier" Partner="Products"/>
                <NavigationProperty Name="ProductDetail" Type="ODataDemo.ProductDetail" Partner="Product"/>
            </EntityType>
            // Other

And map to this model:

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

My client class for consuming it looks like this:

public class MyClient<T> where T : class 
{
    private readonly Uri _uri;
    private readonly string _entitySetName;

    public MyClient(Uri uri, string entitySetName)
    {
        _uri = uri;
        _entitySetName = entitySetName;
    }

    public IQueryable<T> Entities()
    {
        var context = new DataServiceContext(_uri, ODataProtocolVersion.V4);
        context.Format.LoadServiceModel = GenerateModel;

        DataServiceQuery<T> query = context.CreateQuery<T>(_entitySetName);
        return query;
    }

    private IEdmModel GenerateModel()
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<T>(_entitySetName);
        return builder.GetEdmModel();
    }
}

And I use it like this for Product (works great):

var uri = new Uri("http://services.odata.org/V4/OData/OData.svc");
var myClient = new MyClient<Product>(uri, "Products");
var result = myClient.Entities().ToList();

Or like this for StatisticalProgram (doesn't work):

var uri = new Uri("http://mylocaluri.com");
var myClient = new MyClient<StatisticalProgram>(uri, "StatisticalPrograms");
var result = myClient.Entities().ToList();

I'm using

using System.Web.OData.Builder;
using Microsoft.OData.Client;
using Microsoft.OData.Edm;

So, to sum up. It works great if I use odata.org, but not my local OData source. I figure that it might be related to the ID-property, since it's a guid. Can that mess up the mapping? The local OData source works great if you only use it with Postman or a browser. So there seems to be some problems with the mapping.

Upvotes: 1

Views: 980

Answers (1)

smoksnes
smoksnes

Reputation: 10851

It turned out that I used the wrong attribute for defining the Id-column.

It should be:

[global::Microsoft.OData.Client.Key("Id")]

So now my model looks like this and everything works fine!

[Microsoft.OData.Client.Key("Id")]
public class StatisticalProgram
{
    public string Name { get; set; }
    public Guid Id { get; set; }
    public string ShortName { get; set; }
}

Upvotes: 1

Related Questions