My oData service is generatind the metadata above. And my breeze client couldnt proccess.
Breeze error: "Metadata query failed for /odata/v1/$metadata; Unable to process returned metadata: Cannot read property 'end' of null"
Url from metadata: /odata/v1/$metadata#Users
This problem occurs only with Indentity entities! If i change it for another entity of my model it works perfectly!
Can anyone help me!?
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0">
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="FatoresWebV2.Models">
<EntityType Name="User">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Status" Type="Edm.Boolean" Nullable="false"/>
<Property Name="Email" Type="Edm.String"/>
<Property Name="EmailConfirmed" Type="Edm.Boolean" Nullable="false"/>
<Property Name="PasswordHash" Type="Edm.String"/>
<Property Name="SecurityStamp" Type="Edm.String"/>
<Property Name="PhoneNumber" Type="Edm.String"/>
<Property Name="PhoneNumberConfirmed" Type="Edm.Boolean" Nullable="false"/>
<Property Name="TwoFactorEnabled" Type="Edm.Boolean" Nullable="false"/>
<Property Name="LockoutEndDateUtc" Type="Edm.DateTime"/>
<Property Name="LockoutEnabled" Type="Edm.Boolean" Nullable="false"/>
<Property Name="AccessFailedCount" Type="Edm.Int32" Nullable="false"/>
<Property Name="Id" Type="Edm.String" Nullable="false"/>
<Property Name="UserName" Type="Edm.String"/>
<NavigationProperty Name="Roles" Relationship="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Roles_Microsoft_AspNet_Identity_EntityFramework_IdentityUserRole_RolesPartner" ToRole="Roles" FromRole="RolesPartner"/>
<NavigationProperty Name="Claims" Relationship="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Claims_Microsoft_AspNet_Identity_EntityFramework_IdentityUserClaim_ClaimsPartner" ToRole="Claims" FromRole="ClaimsPartner"/>
<NavigationProperty Name="Logins" Relationship="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Logins_Microsoft_AspNet_Identity_EntityFramework_IdentityUserLogin_LoginsPartner" ToRole="Logins" FromRole="LoginsPartner"/>
</EntityType>
</Schema>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="Microsoft.AspNet.Identity.EntityFramework">
<EntityType Name="IdentityUserClaim">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false"/>
<Property Name="UserId" Type="Edm.String"/>
<Property Name="ClaimType" Type="Edm.String"/>
<Property Name="ClaimValue" Type="Edm.String"/>
</EntityType>
<EntityType Name="IdentityUserLogin">
<Property Name="LoginProvider" Type="Edm.String"/>
<Property Name="ProviderKey" Type="Edm.String"/>
<Property Name="UserId" Type="Edm.String"/>
</EntityType>
<EntityType Name="IdentityUserRole">
<Property Name="UserId" Type="Edm.String"/>
<Property Name="RoleId" Type="Edm.String"/>
</EntityType>
<Association Name="FatoresWebV2_Models_User_Roles_Microsoft_AspNet_Identity_EntityFramework_IdentityUserRole_RolesPartner">
<End Type="Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole" Role="Roles" Multiplicity="*"/>
<End Type="FatoresWebV2.Models.User" Role="RolesPartner" Multiplicity="0..1"/>
</Association>
<Association Name="FatoresWebV2_Models_User_Claims_Microsoft_AspNet_Identity_EntityFramework_IdentityUserClaim_ClaimsPartner">
<End Type="Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim" Role="Claims" Multiplicity="*"/>
<End Type="FatoresWebV2.Models.User" Role="ClaimsPartner" Multiplicity="0..1"/>
</Association>
<Association Name="FatoresWebV2_Models_User_Logins_Microsoft_AspNet_Identity_EntityFramework_IdentityUserLogin_LoginsPartner">
<End Type="Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin" Role="Logins" Multiplicity="*"/>
<End Type="FatoresWebV2.Models.User" Role="LoginsPartner" Multiplicity="0..1"/>
</Association>
</Schema>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="Default">
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="Users" EntityType="FatoresWebV2.Models.User"/>
<EntitySet Name="IdentityUserClaims" EntityType="Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim"/>
<EntitySet Name="IdentityUserLogins" EntityType="Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin"/>
<EntitySet Name="IdentityUserRoles" EntityType="Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole"/>
<AssociationSet Name="FatoresWebV2_Models_User_Roles_Microsoft_AspNet_Identity_EntityFramework_IdentityUserRole_RolesPartnerSet" Association="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Roles_Microsoft_AspNet_Identity_EntityFramework_IdentityUserRole_RolesPartner">
<End Role="RolesPartner" EntitySet="Users"/>
<End Role="Roles" EntitySet="IdentityUserRoles"/>
</AssociationSet>
<AssociationSet Name="FatoresWebV2_Models_User_Claims_Microsoft_AspNet_Identity_EntityFramework_IdentityUserClaim_ClaimsPartnerSet" Association="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Claims_Microsoft_AspNet_Identity_EntityFramework_IdentityUserClaim_ClaimsPartner">
<End Role="ClaimsPartner" EntitySet="Users"/>
<End Role="Claims" EntitySet="IdentityUserClaims"/>
</AssociationSet>
<AssociationSet Name="FatoresWebV2_Models_User_Logins_Microsoft_AspNet_Identity_EntityFramework_IdentityUserLogin_LoginsPartnerSet" Association="Microsoft.AspNet.Identity.EntityFramework.FatoresWebV2_Models_User_Logins_Microsoft_AspNet_Identity_EntityFramework_IdentityUserLogin_LoginsPartner">
<End Role="LoginsPartner" EntitySet="Users"/>
<End Role="Logins" EntitySet="IdentityUserLogins"/>
</AssociationSet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Related
I am exploring OData.
I have been following Working with OData - Integrating an Existing ASP.NET Core 3.x API by Referbruv!
My EdmModel follows his and is as follows:
internal static IEdmModel GetEdmModel() {
// create OData builder instance
var builder = new ODataConventionModelBuilder();
// CLIENTS
// map the entities set which are the types returned from the endpoint onto the OData pipeline
// the string parameter is the name of the controller
// which supplies the data of type Client entity model in this case
builder.EntitySet<ClientIndexDto>("ODataClient").EntityType.HasKey(x => x.id);
builder.EntitySet<ClientDetailsDto>("ODataClientDetails").EntityType.HasKey(x => x.id);
// configure a function onto the builder, AllClients
// which is same as the name provided in the ODataRoute
builder.Function("AllClients")
.ReturnsCollectionFromEntitySet<ClientIndexDto>("ODataClient");
builder.Function("ClientById")
.ReturnsCollectionFromEntitySet<ClientDetailsDto>("ODataClientDetails")
.Parameter<int>("id");
return builder.GetEdmModel();
}
The section:
builder.Function("ClientById")
.ReturnsCollectionFromEntitySet<ClientDetailsDto>("ODataClientDetails")
.Parameter<int>("id");
Deals with getting a client by Id.
For completeness I have in My StartUp.cs file the following for OData:
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.Select().Filter().OrderBy().Expand().Count().MaxTop(10);
endpoints.MapODataRoute("odata", "odata", GetEdmModel());
});
The $metadata returned is as follows:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="JobsLedger.MODELS.API.App.Client" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="ClientIndexDto">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" Nullable="false" />
<Property Name="ClientNo" Type="Edm.String" />
<Property Name="Active" Type="Edm.Boolean" Nullable="false" />
<Property Name="ClientFirstName" Type="Edm.String" />
<Property Name="ClientLastName" Type="Edm.String" />
<Property Name="Company" Type="Edm.Boolean" Nullable="false" />
<Property Name="CompanyName" Type="Edm.String" />
<Property Name="MobilePhone" Type="Edm.String" />
<Property Name="IsWarrantyCompany" Type="Edm.Boolean" Nullable="false" />
<Property Name="JobsCount" Type="Edm.String" />
</EntityType>
<EntityType Name="ClientDetailsDto">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" Nullable="false" />
<Property Name="ClientNo" Type="Edm.String" />
<Property Name="Company" Type="Edm.Boolean" Nullable="false" />
<Property Name="IsWarrantyCompany" Type="Edm.Boolean" Nullable="false" />
<Property Name="CompanyName" Type="Edm.String" />
<Property Name="ClientFirstName" Type="Edm.String" />
<Property Name="ClientLastName" Type="Edm.String" />
<Property Name="MobilePhone" Type="Edm.String" />
<Property Name="DeActivated" Type="Edm.String" />
<Property Name="CreatedOn" Type="Edm.String" />
<Property Name="CreatedBy" Type="Edm.String" />
<Property Name="ModifiedOn" Type="Edm.String" />
<Property Name="ModifiedBy" Type="Edm.String" />
<Property Name="SuburbId" Type="Edm.Int32" Nullable="false" />
<NavigationProperty Name="Address" Type="JobsLedger.MODELS.Common.Address.AddressDto" />
<NavigationProperty Name="ClientJobs" Type="Collection(JobsLedger.MODELS.API.App.Job.ClientJobDto)" />
<NavigationProperty Name="ClientNotes" Type="Collection(JobsLedger.MODELS.Common.Notes.ClientNoteDto)" />
</EntityType>
</Schema>
<Schema Namespace="JobsLedger.MODELS.Common.Address" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="AddressDto">
<Key>
<PropertyRef Name="Address1" />
</Key>
<Property Name="Address1" Type="Edm.String" Nullable="false" />
<Property Name="Address2" Type="Edm.String" />
<Property Name="SuburbId" Type="Edm.Int32" Nullable="false" />
<Property Name="SuburbName" Type="Edm.String" />
<Property Name="StateShortName" Type="Edm.String" />
<Property Name="Postcode" Type="Edm.String" />
</EntityType>
</Schema>
<Schema Namespace="JobsLedger.MODELS.API.App.Job" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="ClientJobDto">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="JobNo" Type="Edm.String" />
<Property Name="AgentJobNo" Type="Edm.String" />
<Property Name="Type" Type="Edm.String" />
<Property Name="Status" Type="Edm.String" />
<Property Name="WarrantyCompany" Type="Edm.String" />
<Property Name="NumberOfVisits" Type="Edm.String" />
<Property Name="CreatedOn" Type="Edm.String" />
<Property Name="CreatedBy" Type="Edm.String" />
<Property Name="ModifiedOn" Type="Edm.String" />
<Property Name="ModifiedBy" Type="Edm.String" />
<NavigationProperty Name="JobNotes" Type="Collection(JobsLedger.MODELS.Common.Notes.JobNoteDto)" />
<NavigationProperty Name="JobVisits" Type="Collection(JobsLedger.MODELS.API.App.Job.JobVisitDto)" />
</EntityType>
<EntityType Name="JobVisitDto">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="DateCreated" Type="Edm.String" />
<Property Name="VisitDate" Type="Edm.String" />
<Property Name="StartTime" Type="Edm.String" />
<Property Name="EndTime" Type="Edm.String" />
</EntityType>
</Schema>
<Schema Namespace="JobsLedger.MODELS.Common.Notes" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="JobNoteDto">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="JobId" Type="Edm.Int32" Nullable="false" />
<Property Name="Details" Type="Edm.String" />
<Property Name="NoteType" Type="Edm.String" />
<Property Name="CreatedOnDate" Type="Edm.String" />
<Property Name="CreatedOnTime" Type="Edm.String" />
<Property Name="CreatedBy" Type="Edm.String" />
<Property Name="ModifiedOnDate" Type="Edm.String" />
<Property Name="ModifiedOnTime" Type="Edm.String" />
<Property Name="ModifiedBy" Type="Edm.String" />
</EntityType>
<EntityType Name="ClientNoteDto">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" Nullable="false" />
<Property Name="Details" Type="Edm.String" />
<Property Name="NoteType" Type="Edm.String" />
<Property Name="CreatedOnDate" Type="Edm.String" />
<Property Name="CreatedOnTime" Type="Edm.String" />
<Property Name="CreatedBy" Type="Edm.String" />
<Property Name="ModifiedOnDate" Type="Edm.String" />
<Property Name="ModifiedOnTime" Type="Edm.String" />
<Property Name="ModifiedBy" Type="Edm.String" />
</EntityType>
</Schema>
<Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<Function Name="AllClients">
<ReturnType Type="Collection(JobsLedger.MODELS.API.App.Client.ClientIndexDto)" />
</Function>
<Function Name="ClientById">
<Parameter Name="id" Type="Edm.Int32" Nullable="false" />
<ReturnType Type="Collection(JobsLedger.MODELS.API.App.Client.ClientDetailsDto)" />
</Function>
<EntityContainer Name="Container">
<EntitySet Name="ODataClient" EntityType="JobsLedger.MODELS.API.App.Client.ClientIndexDto" />
<EntitySet Name="ODataClientDetails" EntityType="JobsLedger.MODELS.API.App.Client.ClientDetailsDto" />
<FunctionImport Name="AllClients" Function="Default.AllClients" EntitySet="ODataClient" IncludeInServiceDocument="true" />
<FunctionImport Name="ClientById" Function="Default.ClientById" EntitySet="ODataClientDetails" IncludeInServiceDocument="true" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
My Controller is as follows:
using JobsLedger.API.Controllers.API.App.Interfaces;
using JobsLedger.API.ControllerServices.API.App.ClientService.Interfaces;
using JobsLedger.DATA;
using JobsLedger.DATA.Repositories.Interfaces;
using JobsLedger.MODELS.API.App.Client;
using Microsoft.AspNet.OData;
using Microsoft.AspNet.OData.Routing;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
namespace JobsLedger.API.Controllers.API.App {
[Route("api/[controller]")]
[ApiController]
[Authorize(Roles = "TenantAdmin,Admin,Employee")]
public class ODataClientController : ODataController, IClientController {
private readonly IClientServices _clientServices;
public ODataClientController( IClientServices clientServices) {
_clientServices = clientServices;
}
[HttpGet]
[EnableQuery()]
[ODataRoute("AllClients()")]
public IActionResult Get()
{
return Ok(_clientServices.GetAllClientsAsDto());
}
[HttpGet]
[EnableQuery]
[ODataRoute("ClientById(id={id})")]
public IActionResult Get(int id) {
return Ok(_clientServices.GetClient(id));
}
I want to get a client with an ID of "5" so I use the following get command in Postman:
https://localhost:44301/odata/ClientById(id=5)?
This is as the tutorial indicates - with brackets around the "id=5"
It gets to the endpoint but the id is set to "0".
Given my EdmModel, the #MetaData, and the controller action for a single Id why, when I send a GET command with an (Id=5) I get an Id=0? What do I need to do to fix this?
In the article comments, Referbruv also mentions issue with routing in .net core 3.1. So, you can try it in 3.0 and if it works there, it is the issue with 3.1.
If you can do it with id= then based on the attr-routing this should work.
[ODataRoute("ClientById({id})")]
I'm using CsdlReader in C# to parse a csdl. The whole XML file is as follows:
<Schema
xmlns=\"http://schemas.microsoft.com/ado/2008/09/edm\"
xmlns:edm_annotation=\"http://schemas.microsoft.com/ado/2009/02/edm/annotation\"
xmlns:bi=\"http://schemas.microsoft.com/sqlbi/2010/10/edm/extensions\" bi:Version=\"1.0\" Namespace=\"Sandbox\">
<EntityContainer Name=\"Sandbox\">
<EntitySet Name=\"CountryRegions\" EntityType=\"Sandbox.CountryRegions\">
<bi:EntitySet />
</EntitySet>
<EntitySet Name=\"Editions\" EntityType=\"Sandbox.Editions\">
<bi:EntitySet />
</EntitySet>
<EntitySet Name=\"Medals\" EntityType=\"Sandbox.Medals\">
<bi:EntitySet />
</EntitySet>
<EntitySet Name=\"Medalists\" EntityType=\"Sandbox.Medalists\">
<bi:EntitySet />
</EntitySet>
<EntitySet Name=\"MedalClasses\" EntityType=\"Sandbox.MedalClasses\">
<bi:EntitySet Hidden=\"true\" />
</EntitySet>
<AssociationSet Name=\"Editions_CountryRegions_CountryRegions_Country_Region\" Association=\"Sandbox.Editions_CountryRegions_CountryRegions_Country_Region\">
<End EntitySet=\"Editions\" />
<End EntitySet=\"CountryRegions\" />
<bi:AssociationSet State=\"Inactive\" />
</AssociationSet>
<AssociationSet Name=\"Medals_CountryRegions_CountryRegions_IOC_Code\" Association=\"Sandbox.Medals_CountryRegions_CountryRegions_IOC_Code\">
<End EntitySet=\"Medals\" />
<End EntitySet=\"CountryRegions\" />
<bi:AssociationSet />
</AssociationSet>
<AssociationSet Name=\"Medals_Editions_Editions_Year\" Association=\"Sandbox.Medals_Editions_Editions_Year\">
<End EntitySet=\"Medals\" />
<End EntitySet=\"Editions\" />
<bi:AssociationSet />
</AssociationSet>
<AssociationSet Name=\"Medals_MedalClasses_MedalClasses_Class\" Association=\"Sandbox.Medals_MedalClasses_MedalClasses_Class\">
<End EntitySet=\"Medals\" />
<End EntitySet=\"MedalClasses\" />
<bi:AssociationSet />
</AssociationSet>
<AssociationSet Name=\"Medalists_Medals_Medals_Medal_ID\" Association=\"Sandbox.Medalists_Medals_Medals_Medal_ID\">
<End EntitySet=\"Medalists\" />
<End EntitySet=\"Medals\" />
<bi:AssociationSet />
</AssociationSet>
<bi:EntityContainer Caption=\"IN_Olympics\" Culture=\"en-US\">
<bi:CompareOptions IgnoreCase=\"true\" />
</bi:EntityContainer>
</EntityContainer>
<EntityType Name=\"CountryRegions\">
<Key>
<PropertyRef Name=\"IOC_Code\" />
</Key>
<Property Name=\"RowNumber\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Hidden=\"true\" Contents=\"RowNumber\" Stability=\"RowNumber\" />
</Property>
<Property Name=\"Country_Region\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\" Nullable=\"false\">
<bi:Property Caption=\"Country/Region\" ReferenceName=\"Country/Region\" Contents=\"Country\" />
</Property>
<Property Name=\"IOC_Code\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\" Nullable=\"false\">
<bi:Property Caption=\"IOC Code\" Hidden=\"true\" ReferenceName=\"IOC Code\" GroupingBehavior=\"GroupOnEntityKey\" />
</Property>
<Property Name=\"ISO_Code\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"ISO Code\" Hidden=\"true\" ReferenceName=\"ISO Code\" />
</Property>
<Property Name=\"Residency\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"Flag\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Contents=\"ImageUrl\" />
</Property>
<Property Name=\"Continent\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Contents=\"Continent\" />
</Property>
<Property Name=\"Heavyweight\" Type=\"Boolean\">
<bi:Property FormatString=\""TRUE";"TRUE";"FALSE"\" />
</Property>
<Property Name=\"medal_rank\" Type=\"Int64\">
<bi:Measure Caption=\"medal rank\" ReferenceName=\"medal rank\" />
</Property>
<bi:EntityType>
<bi:DisplayKey>
<bi:MemberRef Name=\"Country_Region\" />
</bi:DisplayKey>
<bi:DefaultDetails>
<bi:MemberRef Name=\"Flag\" />
<bi:MemberRef Name=\"Country_Region\" />
</bi:DefaultDetails>
<bi:DefaultImage>
<bi:MemberRef Name=\"Flag\" />
</bi:DefaultImage>
</bi:EntityType>
</EntityType>
<EntityType Name=\"Editions\">
<Key>
<PropertyRef Name=\"Year\" />
</Key>
<Property Name=\"RowNumber\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Hidden=\"true\" Contents=\"RowNumber\" Stability=\"RowNumber\" />
</Property>
<Property Name=\"Host_City\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Host City\" ReferenceName=\"Host City\" Contents=\"City\" />
</Property>
<Property Name=\"Year\" Type=\"Int64\" Nullable=\"false\">
<bi:Property DefaultAggregateFunction=\"None\" GroupingBehavior=\"GroupOnEntityKey\" />
</Property>
<Property Name=\"Host_Country_Region\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Host Country/Region\" ReferenceName=\"Host Country/Region\" Contents=\"Country\" />
</Property>
<Property Name=\"Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"Host_Continent\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Host Continent\" ReferenceName=\"Host Continent\" Contents=\"Continent\" />
</Property>
<Property Name=\"Olympic_Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Olympic Name\" ReferenceName=\"Olympic Name\" />
</Property>
<Property Name=\"Olympic_Full_Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Olympic Full Name\" ReferenceName=\"Olympic Full Name\" />
</Property>
<Property Name=\"Sum_of_Year\" Type=\"Int64\">
<bi:Measure Caption=\"Sum of Year\" ReferenceName=\"Sum of Year\" IsSimpleMeasure=\"true\" />
</Property>
<NavigationProperty Name=\"CountryRegions_Country_Region\" Relationship=\"Sandbox.Editions_CountryRegions_CountryRegions_Country_Region\" FromRole=\"Editions_Host_Country_Region\" ToRole=\"CountryRegions_Country_Region\">
<bi:NavigationProperty ReferenceName=\"CountryRegions_Country/Region\" />
</NavigationProperty>
<bi:EntityType>
<bi:DisplayKey>
<bi:MemberRef Name=\"Name\" />
</bi:DisplayKey>
</bi:EntityType>
</EntityType>
<EntityType Name=\"Medals\">
<Key>
<PropertyRef Name=\"Medal_ID\" />
</Key>
<Property Name=\"RowNumber\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Hidden=\"true\" Contents=\"RowNumber\" Stability=\"RowNumber\" />
</Property>
<Property Name=\"Medal_ID\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Caption=\"Medal ID\" Hidden=\"true\" ReferenceName=\"Medal ID\" GroupingBehavior=\"GroupOnEntityKey\" />
</Property>
<Property Name=\"Year\" Type=\"Double\">
<bi:Property Hidden=\"true\" />
</Property>
<Property Name=\"Sport\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"Discipline\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"NOC\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Hidden=\"true\" />
</Property>
<Property Name=\"Event\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"Event_Gender_raw\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Event Gender raw\" ReferenceName=\"Event Gender raw\" />
</Property>
<Property Name=\"Class\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property>
<bi:OrderBy>
<bi:PropertyRef Name=\"Class_Rank\" />
</bi:OrderBy>
</bi:Property>
</Property>
<Property Name=\"Description\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property />
</Property>
<Property Name=\"Class_Rank\" Type=\"Int64\">
<bi:Property Caption=\"Class Rank\" Hidden=\"true\" ReferenceName=\"Class Rank\" />
</Property>
<Property Name=\"Event_Gender\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Event Gender\" ReferenceName=\"Event Gender\" />
</Property>
<Property Name=\"Olympic_Year\" Type=\"Int64\">
<bi:Property Caption=\"Olympic Year\" ReferenceName=\"Olympic Year\" DefaultAggregateFunction=\"None\" />
</Property>
<Property Name=\"Country_Region\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Country/Region\" ReferenceName=\"Country/Region\" Contents=\"Country\" />
</Property>
<Property Name=\"medal_growth__vs_previous_Olympics_\" Type=\"Double\">
<bi:Measure Caption=\"medal growth (vs previous Olympics)\" ReferenceName=\"medal growth (vs previous Olympics)\" FormatString=\"0.0 %;-0.0 %;0.0 %\" />
</Property>
<Property Name=\"Cumulative_Medal_Count\" Type=\"Int64\">
<bi:Measure Caption=\"Cumulative Medal Count\" ReferenceName=\"Cumulative Medal Count\" FormatString=\"#,0\" />
</Property>
<Property Name=\"Cumulative_Event_Count\" Type=\"Int64\">
<bi:Measure Caption=\"Cumulative Event Count\" ReferenceName=\"Cumulative Event Count\" />
</Property>
<Property Name=\"Years_Since_First_Olympic_Win\" Type=\"Int64\">
<bi:Measure Caption=\"Years Since First Olympic Win\" ReferenceName=\"Years Since First Olympic Win\" />
</Property>
<Property Name=\"Percent_of_Total_Medals_in_Sport\" Type=\"Double\">
<bi:Measure Caption=\"Percent of Total Medals in Sport\" ReferenceName=\"Percent of Total Medals in Sport\" FormatString=\"0.00 %;-0.00 %;0.00 %\" />
</Property>
<Property Name=\"Medal_Weight\" Type=\"Double\">
<bi:Measure Caption=\"Medal Weight\" ReferenceName=\"Medal Weight\" />
</Property>
<Property Name=\"Medal_Count\" Type=\"Int64\">
<bi:Measure Caption=\"Medal Count\" ReferenceName=\"Medal Count\" FormatString=\"#,0\" />
</Property>
<NavigationProperty Name=\"CountryRegions_IOC_Code\" Relationship=\"Sandbox.Medals_CountryRegions_CountryRegions_IOC_Code\" FromRole=\"Medals_NOC\" ToRole=\"CountryRegions_IOC_Code\">
<bi:NavigationProperty ReferenceName=\"CountryRegions_IOC Code\" />
</NavigationProperty>
<NavigationProperty Name=\"Editions_Year\" Relationship=\"Sandbox.Medals_Editions_Editions_Year\" FromRole=\"Medals_Year\" ToRole=\"Editions_Year\">
<bi:NavigationProperty />
</NavigationProperty>
<NavigationProperty Name=\"MedalClasses_Class\" Relationship=\"Sandbox.Medals_MedalClasses_MedalClasses_Class\" FromRole=\"Medals_Class\" ToRole=\"MedalClasses_Class\">
<bi:NavigationProperty />
</NavigationProperty>
<bi:EntityType>
<bi:DisplayKey>
<bi:MemberRef Name=\"Description\" />
</bi:DisplayKey>
<bi:DefaultDetails>
<bi:MemberRef Name=\"Discipline\" />
<bi:MemberRef Name=\"Event\" />
<bi:MemberRef Name=\"Event_Gender\" />
<bi:MemberRef Name=\"Year\" />
<bi:MemberRef Name=\"Class\" />
<bi:MemberRef Name=\"Olympic_Year\" />
<bi:MemberRef Name=\"Country_Region\" />
</bi:DefaultDetails>
</bi:EntityType>
</EntityType>
<EntityType Name=\"Medalists\">
<Key>
<PropertyRef Name=\"Medalist_ID\" />
</Key>
<Property Name=\"RowNumber\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Hidden=\"true\" Contents=\"RowNumber\" Stability=\"RowNumber\" />
</Property>
<Property Name=\"Medalist_ID\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Caption=\"Medalist ID\" Hidden=\"true\" ReferenceName=\"Medalist ID\" />
</Property>
<Property Name=\"Medal_ID\" Type=\"Int64\">
<bi:Property Caption=\"Medal ID\" Hidden=\"true\" ReferenceName=\"Medal ID\" />
</Property>
<Property Name=\"Athlete_Name_Sort_Order\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Athlete Name Sort Order\" Hidden=\"true\" ReferenceName=\"Athlete Name Sort Order\" />
</Property>
<Property Name=\"Athlete_Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Athlete Name\" ReferenceName=\"Athlete Name\" />
</Property>
<Property Name=\"Medal_Class\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Medal Class\" ReferenceName=\"Medal Class\" />
</Property>
<Property Name=\"Athlete_Full_Last_Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Athlete Full Last Name\" Hidden=\"true\" ReferenceName=\"Athlete Full Last Name\" />
</Property>
<Property Name=\"Athlete_Alias\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Athlete Alias\" ReferenceName=\"Athlete Alias\" />
</Property>
<Property Name=\"Athlete_Last_Name\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\">
<bi:Property Caption=\"Athlete Last Name\" ReferenceName=\"Athlete Last Name\" />
</Property>
<Property Name=\"Sum_of_Medalist_ID\" Type=\"Int64\">
<bi:Measure Caption=\"Sum of Medalist ID\" ReferenceName=\"Sum of Medalist ID\" IsSimpleMeasure=\"true\" />
</Property>
<Property Name=\"Count_of_Athlete_Name\" Type=\"Int64\">
<bi:Measure Caption=\"Count of Athlete Name\" ReferenceName=\"Count of Athlete Name\" IsSimpleMeasure=\"true\" />
</Property>
<NavigationProperty Name=\"Medals_Medal_ID\" Relationship=\"Sandbox.Medalists_Medals_Medals_Medal_ID\" FromRole=\"Medalists_Medal_ID\" ToRole=\"Medals_Medal_ID\">
<bi:NavigationProperty ReferenceName=\"Medals_Medal ID\" />
</NavigationProperty>
<bi:EntityType>
<bi:DefaultDetails>
<bi:MemberRef Name=\"Athlete_Name\" />
</bi:DefaultDetails>
</bi:EntityType>
</EntityType>
<EntityType Name=\"MedalClasses\">
<Key>
<PropertyRef Name=\"v__XL_RowNumber\" />
</Key>
<Property Name=\"Class\" Type=\"String\" MaxLength=\"Max\" Unicode=\"true\" FixedLength=\"false\" Nullable=\"false\">
<bi:Property />
</Property>
<Property Name=\"Class_Rank\" Type=\"Int64\">
<bi:Property Caption=\"Class Rank\" ReferenceName=\"Class Rank\" />
</Property>
<Property Name=\"v__XL_RowNumber\" Type=\"Int64\" Nullable=\"false\">
<bi:Property Caption=\"__XL_RowNumber\" Hidden=\"true\" ReferenceName=\"__XL_RowNumber\" Contents=\"RowNumber\" Stability=\"RowNumber\" />
</Property>
<bi:EntityType />
</EntityType>
<Association Name=\"Editions_CountryRegions_CountryRegions_Country_Region\">
<End Role=\"Editions_Host_Country_Region\" Type=\"Sandbox.Editions\" Multiplicity=\"*\" />
<End Role=\"CountryRegions_Country_Region\" Type=\"Sandbox.CountryRegions\" Multiplicity=\"0..1\" />
</Association>
<Association Name=\"Medals_CountryRegions_CountryRegions_IOC_Code\">
<End Role=\"Medals_NOC\" Type=\"Sandbox.Medals\" Multiplicity=\"*\" />
<End Role=\"CountryRegions_IOC_Code\" Type=\"Sandbox.CountryRegions\" Multiplicity=\"0..1\" />
</Association>
<Association Name=\"Medals_Editions_Editions_Year\">
<End Role=\"Medals_Year\" Type=\"Sandbox.Medals\" Multiplicity=\"*\" />
<End Role=\"Editions_Year\" Type=\"Sandbox.Editions\" Multiplicity=\"0..1\" />
</Association>
<Association Name=\"Medals_MedalClasses_MedalClasses_Class\">
<End Role=\"Medals_Class\" Type=\"Sandbox.Medals\" Multiplicity=\"*\" />
<End Role=\"MedalClasses_Class\" Type=\"Sandbox.MedalClasses\" Multiplicity=\"0..1\" />
</Association>
<Association Name=\"Medalists_Medals_Medals_Medal_ID\">
<End Role=\"Medalists_Medal_ID\" Type=\"Sandbox.Medalists\" Multiplicity=\"*\" />
<End Role=\"Medals_Medal_ID\" Type=\"Sandbox.Medals\" Multiplicity=\"0..1\" />
</Association>
</Schema>
And this is my code:
CsdlReader.TryParse(schemaReaders, out edmModel, out edmErrors)
As you can see. Role is an attribute of End. However, it seems that I am unable to parse that XML. And I have errors like this in edmErrors:
{MissingAttribute : Required schema attribute 'Role' is not present on
element 'End'. : (0, 0)}
The message tells me that Role is missing, but I do have that in my csdl.
End elements in AssociationSet of Sandbox entity container indeed miss Role attributes:
<AssociationSet Name=\"Editions_CountryRegions_CountryRegions_Country_Region\" Association=\"Sandbox.Editions_CountryRegions_CountryRegions_Country_Region\">
<End EntitySet=\"Editions\" />
<End EntitySet=\"CountryRegions\" />
<bi:AssociationSet State=\"Inactive\" />
</AssociationSet>
This is the root cause of parsing errors.
It is down to the OData version. Older versions generate AssociationSet without Role, a newer version of CsdlReader expects Role to be there. Current is 4.0 (see http://www.odata.org/documentation/ ).
You can see the version of your CSDL by looking at the properties of the assembly. If you obtained your XML using GetSchemaDataSet then you can request the right version in the RestrictionList parameter. This only shows it in XMLA but the params are the same. (https://learn.microsoft.com/en-us/sql/analysis-services/schema-rowsets/xml/discover-csdl-metadata-rowset )
I'm trying to add a bound function to my Web API 2.2 OData v4 controller, but it returns 404 with the error message:
{
"error":{
"code":"","message":"No HTTP resource was found that matches the request URI 'http://localhost:2390/Hierarchies('300924834')/FullHierarchy'.","innererror":{
"message":"No routing convention was found to select an action for the OData path with template '~/entityset/key/unresolved'.","type":"","stacktrace":""
}
}
}
This is my method on the HierarchiesController:
[HttpGet]
public IHttpActionResult FullHierarchy([FromODataUri]string key)
{
return Ok(new Hierarchy());
}
I tried to add the attribute [ODataRoute("Hierarchies({key}/FullHierarchy)")]on my method but then I got the following error on the line GlobalConfiguration.Configure(WebApiConfig.Register);when first running the application:
The path template 'Hierarchies({key}/FullHierarchy)' on the action 'FullHierarchy' in controller 'Hierarchies' is not a valid OData path template. Bad Request - Error in query syntax.
This is my configuration in WebApiConfig:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = ""; // tried with and without this line.
var hierachyType = builder.EntitySet<Hierarchy>("Hierarchies").EntityType;
hierachyType.Function("FullHierarchy").Returns<Hierarchy>();
Note that bound functions to collections don't work as well, but unbound functions do work.
This is how my $metadata looks like:
<?xml version="1.0" encoding="UTF-8"?>
<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="Entities.Models">
<EntityType Name="Hierarchy">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Name" Type="Edm.String" />
<Property Name="Id" Type="Edm.String" Nullable="false" />
<NavigationProperty Name="Policy" Type="Entities.Models.Policy" />
<NavigationProperty Name="Nodes" Type="Collection(Entities.Models.HierarchyNode)" />
</EntityType>
<EntityType Name="Node" OpenType="true">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Name" Type="Edm.String" />
<Property Name="Id" Type="Edm.String" Nullable="false" />
</EntityType>
<EntityType Name="Site" BaseType="Entities.Models.Node" OpenType="true">
<Property Name="Address" Type="Edm.String" />
</EntityType>
<EntityType Name="Policy">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.String" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<NavigationProperty Name="Rules" Type="Collection(Entities.Rules.Rule)" />
</EntityType>
<EntityType Name="HierarchyNode">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.String" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<NavigationProperty Name="Nodes" Type="Collection(Entities.Models.HierarchyNode)" />
</EntityType>
<EntityType Name="Building" BaseType="Entities.Models.Node" OpenType="true">
<Property Name="StaffCount" Type="Edm.Int32" Nullable="false" />
</EntityType>
<EntityType Name="Source" BaseType="Entities.Models.Node" OpenType="true">
<Property Name="GroupByOperation" Type="Edm.String" />
<Property Name="Factor" Type="Edm.Int32" Nullable="false" />
</EntityType>
</Schema>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Entities.Rules">
<EntityType Name="Rule" Abstract="true">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.String" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="NodeType" Type="Edm.String" />
</EntityType>
<EntityType Name="ParentChildRule" BaseType="Entities.Rules.Rule">
<Property Name="AllowedParentsTypes" Type="Edm.String" />
<Property Name="ForbiddenParentsTypes" Type="Edm.String" />
</EntityType>
<EntityType Name="PredicateRule_1OfTNode" BaseType="Entities.Rules.Rule">
<Property Name="Predicate" Type="System.Linq.Expressions.Expression_1OfFunc_2OfTNode_String" />
</EntityType>
<EntityType Name="PropertyRule" BaseType="Entities.Rules.Rule">
<Property Name="RequiredProperties" Type="Edm.String" />
</EntityType>
</Schema>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="System.Linq.Expressions">
<ComplexType Name="Expression_1OfFunc_2OfTNode_String">
<Property Name="Parameters" Type="Collection(System.Linq.Expressions.ParameterExpression)" />
</ComplexType>
<ComplexType Name="ParameterExpression" />
</Schema>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm">
<Function Name="FullHierarchy" IsBound="true">
<Parameter Name="bindingParameter" Type="Entities.Models.Hierarchy" />
<ReturnType Type="Entities.Models.Hierarchy" />
</Function>
<EntityContainer Name="Container">
<EntitySet Name="Hierarchies" EntityType="Entities.Models.Hierarchy" />
<EntitySet Name="Nodes" EntityType="Entities.Models.Node" />
<EntitySet Name="Sites" EntityType="Entities.Models.Site" />
<EntitySet Name="Rules" EntityType="Entities.Rules.Rule" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
There are several things:
The schema needs to have a namespace. I.e. builder.Namespace = ""; needs to be removed or replaced with a non-empty string.
The function needs to be invoked by it's fully qualified name. I.e. The request URL needs to be http://localhost:2390/Hierarchies('300924834')/<namespace>.FullHierarchy in which <namespace> should be the default namespace or the one you specify in item #1.
As a function bound to a single entity, writing the controller method like this is adequate:
[HttpGet]
public IHttpActionResult FullHierarchy()
{
return Ok(new Hierarchy());
}
I don't know the exact reason. I'd guess the convention model builder helps you with such routing.
It works for me, and following are my test function details:
WebApiConfig:
builder.EntityType<Product>().Function("SomeFunction").Returns<string>();
In the ProductsController:
[HttpGet]
public IHttpActionResult SomeFunction()
{
return Ok("Some");
}
The request:
GET http://localhost:54017/Products(1)/Default.SomeFunction
I'm working on a small project that has a rather simple web api. We decided to go with the EntitySetController class for our controllers. So far that all words great when testing the web api using Fiddler2, I can get to the odata api and make get requests on the controller.
Next part was creating a simple client to test the api in code, so I created a console application and I added a service reference, and pointed it to my api url. I got the expected container and the 4 entity classes show up under the container. The problem is that 2 of the entity classes don't show up using the original namespace, and 2 of the entities do.
This is the response to $metadata
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<Schema Namespace="IRSI.Utilities.Model" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="Concept">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
</EntityType>
<EntityType Name="Store">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="StoreNumber" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="ConceptId" Type="Edm.Int32" Nullable="false" />
</EntityType>
</Schema>
<Schema Namespace="IRSI.Utilities.Electricity.Model" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="ElectricityInvoice">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="InvoiceNumber" Type="Edm.String" />
<Property Name="InvoiceDate" Type="Edm.DateTime" Nullable="false" />
<Property Name="Amount" Type="Edm.Decimal" Nullable="false" />
<Property Name="PreviousReadDate" Type="Edm.DateTime" Nullable="false" />
<Property Name="CurrentReadDate" Type="Edm.DateTime" Nullable="false" />
<Property Name="UsageDays" Type="Edm.Int32" Nullable="false" />
<Property Name="UsagekVA" Type="Edm.Decimal" Nullable="false" />
<Property Name="FixedCharge" Type="Edm.Decimal" Nullable="false" />
<Property Name="UsagekWh" Type="Edm.Int32" Nullable="false" />
<Property Name="RatekWh" Type="Edm.Decimal" Nullable="false" />
<Property Name="AdditionalUsagekWh" Type="Edm.Int32" Nullable="false" />
<Property Name="RateAdditionalUsagekWh" Type="Edm.Decimal" Nullable="false" />
<Property Name="CombustiblePurchase" Type="Edm.Decimal" Nullable="false" />
<Property Name="CombustibleRate" Type="Edm.Decimal" Nullable="false" />
<Property Name="EnergyPurchased" Type="Edm.Decimal" Nullable="false" />
<Property Name="EnergyRate" Type="Edm.Decimal" Nullable="false" />
<Property Name="OtherCharges" Type="Edm.Decimal" Nullable="false" />
<Property Name="StoreId" Type="Edm.Int32" Nullable="false" />
</EntityType>
</Schema>
<Schema Namespace="IRSI.Utilities.Water.Model" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="WaterInvoice">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="InvoiceDate" Type="Edm.DateTime" Nullable="false" />
<Property Name="InvoiceNumber" Type="Edm.String" />
<Property Name="Amount" Type="Edm.Decimal" Nullable="false" />
<Property Name="PreviousRead" Type="Edm.DateTime" Nullable="false" />
<Property Name="CurrentRead" Type="Edm.DateTime" Nullable="false" />
<Property Name="UsageDays" Type="Edm.Int32" Nullable="false" />
<Property Name="Usage" Type="Edm.Decimal" Nullable="false" />
<Property Name="WaterCharge" Type="Edm.Decimal" Nullable="false" />
<Property Name="StormDrainCharge" Type="Edm.Decimal" Nullable="false" />
<Property Name="CCARCharge" Type="Edm.Decimal" Nullable="false" />
<Property Name="SpecialCharge" Type="Edm.Decimal" Nullable="false" />
<Property Name="StoreId" Type="Edm.Int32" Nullable="false" />
</EntityType>
</Schema>
<Schema Namespace="Default" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="UtilitiesContext" m:IsDefaultEntityContainer="true">
<EntitySet Name="Concepts" EntityType="IRSI.Utilities.Model.Concept" />
<EntitySet Name="Stores" EntityType="IRSI.Utilities.Model.Store" />
<EntitySet Name="ElectricityInvoices" EntityType="IRSI.Utilities.Electricity.Model.ElectricityInvoice" />
<EntitySet Name="WaterInvoices" EntityType="IRSI.Utilities.Water.Model.WaterInvoice" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
The proxies generated end up in:
IRSI.Utilities.Electricity.Model.ElecricityInvoice;
IRSI.Utilities.Water.Model.WaterInvoice;
IRSI.Utilities.Data.Client.UtilitiesService.Concept;
IRSI.Utilities.Data.Client.UtilitiesService.Store;
where IRSI.Utilities.Data.Client is the namespace of the console application
and the container is:
IRSI.Utilities.Data.Client.UtilitiesService.UtilitiesContext;
in the Web Api i'm setting up the routes like this:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.ContainerName = "UtilitiesContext";
builder.EntitySet<Concept>("Concepts");
builder.EntitySet<Store>("Stores");
builder.EntitySet<ElectricityInvoice>("ElectricityInvoices");
builder.EntitySet<WaterInvoice>("WaterInvoices");
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel());
}
Am I missing something that is telling the client to generate the proxies differently. Ideally it should be the original namespace like the namespace in the schemas. Next best is fully use one schema, like all entities under the service namespace but not a mix of the 2.
Thanks, Junicus
You may want to try this method: http://blogs.msdn.com/b/odatateam/archive/2014/03/11/how-to-use-odata-client-code-generator-to-generate-client-side-proxy-class.aspx.
One of my Entity Framework Models contains a MS-SQL View. The View is called User and contains various properties for users.
When I right click on the model and select Update Model from Database, I get the following error:
"An exception of type 'System.InvalidOperationException' occurred while attempting to update from the database. The exception message is: 'A model generation extension made changes to the model generated from the database that were not valid'.
This occurs in any model we have that uses a View in Entity Framework 4.0. It's getting very tedious to delete and recreate the model every time some part of the database structure changes. Is there anyway to make "Update Model from Database" work when my model contains a View?
If it makes a difference, this is a readonly View.
EDIT: I forgot to mention, this is a cross-database View. That seems to be where the problem occurs. A regular view (within the same database) works fine.
Here's a my sample EDMX file. I'm not sure if it will be useful or not.
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<edmx:Runtime>
<edmx:StorageModels>
<Schema Namespace="SignupsModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="SignupsModelStoreContainer">
<EntitySet Name="Users" EntityType="SignupsModel.Store.Users" store:Type="Views" Schema="dbo">
</EntitySet>
</EntityContainer>
<EntityType Name="Users">
<Key>
<PropertyRef Name="userID" />
</Key>
<Property Name="userID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="userName" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="campusID" Type="varchar" Nullable="false" MaxLength="7" />
<Property Name="firstName" Type="varchar" Nullable="false" MaxLength="30" />
<Property Name="middleInitial" Type="varchar" Nullable="false" MaxLength="1" />
<Property Name="lastName" Type="varchar" Nullable="false" MaxLength="30" />
</EntityType>
</Schema>
</edmx:StorageModels>
<edmx:ConceptualModels>
<Schema Namespace="SignupsModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityContainer Name="Entities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Users" EntityType="SignupsModel.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="userID" />
</Key>
<Property Name="userID" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Name="userName" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
<Property Name="campusID" Type="String" Nullable="false" MaxLength="7" Unicode="false" FixedLength="false" />
<Property Name="firstName" Type="String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />
<Property Name="middleInitial" Type="String" Nullable="false" MaxLength="1" Unicode="false" FixedLength="false" />
<Property Name="lastName" Type="String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
<EntityContainerMapping StorageEntityContainer="SignupsModelStoreContainer" CdmEntityContainer="Entities">
<EntitySetMapping Name="Users"><EntityTypeMapping TypeName="SignupsModel.User"><MappingFragment StoreEntitySet="Users">
<ScalarProperty Name="userID" ColumnName="userID" />
<ScalarProperty Name="userName" ColumnName="userName" />
<ScalarProperty Name="campusID" ColumnName="campusID" />
<ScalarProperty Name="firstName" ColumnName="firstName" />
<ScalarProperty Name="middleInitial" ColumnName="middleInitial" />
<ScalarProperty Name="lastName" ColumnName="lastName" />
</MappingFragment></EntityTypeMapping></EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
I think I tracked down the issue. A while back, I guess I installed a Visual Studio addon called "Edmx Views Processor". I thought I had uninstalled it. Removing the addon seems to solve the issue.
The extension in question is located here:
http://visualstudiogallery.msdn.microsoft.com/en-us/d9b76b5d-d45c-4e79-8d28-31444be582de