[Tutorial & Sample] How to use OData Client Code Generator to generate client-side proxy class


Edited on July 09, 2014 by updating “Add OData Client Proxy File” for V2.0.0 and adding “Appendix” part. Please refer to “OData Client Code Generator 2.0.0 release” for V2.0.0 release notes

Edited on Apr 29, 2014 by adding “Upgrade the Project Dependencies to the Most Recent Version” part.

In this tutorial, you will generate an OData client proxy class for an OData V4 service by “OData Client Code Generator”.

Install OData Client Code Generator

Start Visual Studio, from the TOOLS menu, select Extensions and Updates

In the left panel, expand Online -> Visual Studio Gallery. Search “OData Client Code Generator” in search box and Download the VSIX.

download

After the VSIX is downloaded, the installer page will show. Click Install.

Install

Following dialog will show when installation finish. Click Close.

Install Finished

You need to restart Visual studio in order for the changes to take effect.

Create Your Application

Create your project. OData Client Code Generator works with any projects, but here, we take “Console Application” project for example

ConsoleApp

Add OData Client Proxy File

In Solution Explorer, right click you project name. Click Add->New Item.

AddItem

In the left panel, expand Installed->Visual C# Items->Code. Choose “OData Client”, and rename your client file, such as “NorthwindProxy.tt”, and Click Add.

RenameItem

This step will add two files to your project

1. NorthwindProxy.tt contains all the configurations you need to set:

  • MetadataDocumentUri

Service document URI or service metadata URI or a file path of metadata local copy.

  • NamespacePrefix
    • The value will be used as the namespace of your client proxy when metadata contains only one schema.
    • The value will be added before namespaces of schemas when metadata contains several schemas.
    • The namespace in metadata will be used if the value is empty string.
  • EnableNamingAlias

   This value will be used to enable naming alias. By default, it is to enable camel case on client side. But user can customize the naming alias logic.

2. NorthwindProxy.ttinclude is the T4 template for generating proxy file from metadata document.

Save the tt file, The generated cs file will show in Solution Explorer under the tt file.

Consume the generated code

Now, we have generated the client proxy for the service file. You can refer to it in your client code. Example.

Upgrade the Project Dependencies to the Most Recent Version

After all the steps above, you will find that the OData core and client libraries version 6.0.0 have been added into the references of this project.

If you want to upgrade the OData core and client libraries to the most recent version, you can use the NuGet Package Manager to do it.

In the solution explorer, right click the project and click “Manage NuGet Packages”.

In the left panel, expand Update -> nuget.org. Select “OData Client for .NET” and click “Update”.

After a few seconds, the “License Acceptance” dialog shows up. On this dialog, click “I Accept”.



It will update these assemblies for this project. Then “Close” the dialog when it is done.

Check the OData core and client libraries assemblies, and it will show that you have upgraded them to the most recent version.


 

Appendix

 The OData Code Generator V1.0.0 generates two files different from the V2.0.0 when adding new OData Client item template

1. NorthwindProxy.odata.config contains all the configurations you need to set:

  • MetadataDocumentUri

Service document URI or service metadata URI or a file path of metadata local copy.

  • NamespacePrefix
    • The value will be used as the namespace of your client proxy when metadata contains only one schema.
    • The value will be added before namespaces of schemas when metadata contains several schemas.
    • The namespace in metadata will be used if the value is empty string.

2. NorthwindProxy.tt is the T4 template for generating proxy file from metadata document.

Save your configuration file.

Config

Re-trigger the code generation by right click at NorthwindProxy.tt, and select “Run Custom Tool”. The generated cs file will show in Solution Explorer under the tt file.

cs Generated

cs file

Comments (37)

  1. Maxim says:

    It is support early version of OData (V3, V2,…)?

  2. KapitonovM says:

    I have exception during “Run Custom Tool” on my OData service

    "Running transformation: System.InvalidOperationException: The element 'edmx:Edmx' was unexpected for the root element. The root element should be Edmx."

  3. DotNetWise says:

    Still no news about supporting OData V4 / enums?

    6 months ago you said an alpha version will be released soon, but since then no news about it.

  4. jhalbrecht says:

    'Create your project. OData Client Code Generator works with any projects, but here, we take “Console Application” project for example'

    After install the OData Client doesn't show for my Windows 8.1 Metro application. (It does show for other project types)

  5. Layla Liu says:

    @Maxim   11 Mar 2014 9:21 PM  

    It doesn't support V3/V2 service. To generate client code for V3/V2 service, please use ASR

  6. Layla Liu says:

    @KapitonovM 11 Mar 2014 9:24 PM

    Could you please confirm that whether your first element of the metadata document is like "<edmx:Edmx xmlns="docs.oasis-open.org/…/edm" xmlns:edmx="docs.oasis-open.org/…/edmx" Version="4.0">"?

  7. Layla Liu says:

    @DotNetWise 12 Mar 2014 1:55 AM

    OData V4 support Enum now, Please use the latest version

  8. KapitonovM says:

    @Layla Liu Thu, Mar 13 2014 1:54 PM

    You already answered.

    – "It doesn't support V3/V2 service. To generate client code for V3/V2 service, please use ASR"

    My server have V3

    Thx.

  9. Pablo Cibraro says:

    I am getting the same error as KapitonovM. The EDMX version is 1.0, altough I have a DataService element with the version 4.0. Any idea of we can fix this issue ? Thanks

  10. KapitonovM says:

    Hi, only for your information:

    I cannot use "OData Client for .NET" 6.1.0 package what "OData Client Code Generator" depends on it

    together with "Microsoft ASP.NET Web API 2.2 for OData v4.0" in one project because assembly versioning conflict.

  11. Uffe says:

    How do we use this with a server requiring windows authentication? It seems like it doesn't supports showing a login dialog. Could you please fix it?

  12. Uffe says:

    So? How do we supply credentials with this T4 thingy???

  13. layla liu says:

    @Uffe,

    Currently, we don't support any authentication when generating Client proxy. You can download the metadata on your local file system and provide the local file path to work around.

  14. Harry says:

    I get the following error:

    Error 2 Running transformation: System.Net.WebException: Unable to connect to the remote server —> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:21959

    This is in the same project as the service is hosted.

  15. Shravan Peddapally says:

    I got an exception

    Running transformation: System.Net.WebException: The remote server returned an error: (404) Not Found.

    on selecting "Run Custom Tool". Can any one help me in resolving this??

  16. Goroth says:

    The template generates an invalid type called "Nullable_1OfDateTime" when it should have been "nullable datetime".  It is generating an error "The complex type 'System.Nullable_1OfDateTime' has no settable properties."

  17. layla liu says:

    @Shravan Peddapally

    Please try to access your service by IE.

    Or you can download the metadata to a local file and provide the local file path to work around.

  18. layla liu says:

    @Goroth

    Could you provide me the piece of metadata about DateTime. In V4 EdmLib, OData support edm:DateTimeOffset instead of edm.DateTime.

  19. layla liu says:

    @Harry

    Could you please try to access your service by IE.

    Or please download the metadata manually to a local file and provide the local file path to work around.

  20. tyrius says:

    Are there any plans to support functions that return collections using the Edm.EntityType abstract type?  I have three different entity sets and I want to expose a function that will return objects from each entity set in a single collection.

    docs.oasis-open.org/…/odata-v4.0-os-part3-csdl.html

    tools.oasis-open.org/…/ODATA-374

  21. Abdelwahab says:

    Is inserting object graphs supported?  

    I tried inserting related entities " Addto…   ,  AddLink,   Set Link "   ,  and the server seems to recieve only the parent entity

  22. layla liu says:

    @Abdelwahab,

    AddObject does not follow the object graph and add related objects. AddLink and SetLink only create or change relationships between entity instances. So you need to add those related entities separately.

  23. Amalah &#39;MSDN&#39; says:

    Hi,

    @Layla Liu

    excellent tutorial,

    I am wondering if the Client Code generator helps accessing a specific entity by its Id (key).

    For example in your example of generated code consumption, you access ALL products:

               var products = dc.Products.ToList();

    How would you access a specific product giving its id, say Product with id 2

    in order to lead to the GET request ending with   /Products(2)

  24. layla liu says:

    @Amalah,

    dc.Products.Where(p=>p.ProductID == 2).Single();

    OData Client enables you to execute queries against a data service by using language integrated query, You can refer to msdn.microsoft.com/…/dd673933(v=vs.110).aspx for more details.

  25. Amalah &#39;MSDN&#39; says:

    @Layla Liu,

    Hi again Layla,

    That time I do have a question regarding the support of 'containment navigation property' as defined by attribute 'ContainsTarget' of a NavigationProperty in an *.edmx file.

    (see docs.oasis-open.org/…/odata-v4.0-os-part3-csdl.html)

    Extract from an edmx file:

       <EntityType Name=""NumericTimeSeries"" BaseType=""OIPlatform.Series.TimeSeries"">

           <NavigationProperty Name=""Entries"" Type=""Collection(OIPlatform.Series.NumericSeriesEntry)"" ContainsTarget=""true"" />

         </EntityType>

    When using the generated client code, I do not succeed to add/create entities in the 'Entries' property.

    Code like below works without error but does nothing (no http request is generated):

               NumericTimeSeries ntsToPopulate = seriesQuery.NumericTimeSeries.Where(nts => nts.InstanceId.Equals(tsToPopulateGuid)).Single();

               foreach (NumericSeriesEntry ntsEnt in numEntries)

               {

                   ntsToPopulate.Entries.Load(ntsEnt);

               }

               seriesQuery.SaveChanges();

  26. layla liu says:

    @Amalah,

    You should use

       public void AddRelatedObject(object source, string sourceProperty, object target)

    to add contained Navigation properties.

    Examples:

    foreach (NumericSeriesEntry ntsEnt in numEntries)

    {

       seriesQuery.AddRelatedObject(ntsToPopulate, "Entries", ntsEnt);

    }

    seriesQuery.SaveChanges();

  27. Mike P. says:

    This is not working!

    I tried with a file and with a URL

    I get this error

    Error 3 Running transformation: System.InvalidOperationException: The element 'edmx:Edmx' was unexpected for the root element. The root element should be Edmx.

      at Microsoft.VisualStudio.TextTemplatingE4BF626FDF4B9B84B0565D2DF4A14A87D361EC79BB56857389E5F55A85583C3C9F09C8CEDA2596F49CB08426DCD8467A170A93B4CF792E58BD5D1A93E9936193.GeneratedTextTransformation.CodeGenerationContext.get_EdmModel() in c:WorkOData2ProductServiceClientODataClient.tt:line 412

      at Microsoft.VisualStudio.TextTemplatingE4BF626FDF4B9B84B0565D2DF4A14A87D361EC79BB56857389E5F55A85583C3C9F09C8CEDA2596F49CB08426DCD8467A170A93B4CF792E58BD5D1A93E9936193.GeneratedTextTransformation.CodeGenerationContext.get_NamespacesInModel() in c:WorkOData2ProductServiceClientODataClient.tt:line 429

      at Microsoft.VisualStudio.TextTemplatingE4BF626FDF4B9B84B0565D2DF4A14A87D361EC79BB56857389E5F55A85583C3C9F09C8CEDA2596F49CB08426DCD8467A170A93B4CF792E58BD5D1A93E9936193.GeneratedTextTransformation.ODataClientTemplate.WriteNamespaces() in c:WorkOData2ProductServiceClientODataClient.tt:line 808

      at Microsoft.VisualStudio.TextTemplatingE4BF626FDF4B9B84B0565D2DF4A14A87D361EC79BB56857389E5F55A85583C3C9F09C8CEDA2596F49CB08426DCD8467A170A93B4CF792E58BD5D1A93E9936193.GeneratedTextTransformation.ODataClientTemplate.TransformText() in c:WorkOData2ProductServiceClientODataClient.tt:line 802

      at Microsoft.VisualStudio.TextTemplatingE4BF626FDF4B9B84B0565D2DF4A14A87D361EC79BB56857389E5F55A85583C3C9F09C8CEDA2596F49CB08426DCD8467A170A93B4CF792E58BD5D1A93E9936193.GeneratedTextTransformation.TransformText() in c:WorkOData2ProductServiceClientODataClient.tt:line 73 c:WorkOData2ProductServiceClientODataClient.tt 412 1 Client

  28. layla liu says:

    @Mike P.

    It seems like the EdmLib failed to parse the $metadata file. we ran into this error while the service is a V3 service.

    Could you please provide me the $metadata file?

  29. AdamCaviness says:

    The idea of a NamespacePrefix is a poor concept.  I do not want to simply prefix my server's namespace.  That makes many assumptions about how projects are named.  I want to use an entirely different client namespace and I don't think one should have to modify the T4 template for something so basic.

  30. DJO2112 says:

    I ran into the similar error: "The element 'edmx:Edmx' was unexpected for the root element. The root element should be Edmx". As mentioned above, I was attempting to use a MetadataDocumentUri that was against a V3 service. Are there any workarounds?

  31. Junlin Zheng says:

    @AdamCaviness

    We're just following the behavior as you add a new class into your project, the project's name will be used for namespace. If you want to keep the namespaces provided by service in metadata, you can just set the value of NamespacePrefix to empty string or null in T4 template; if you want to use your own one, just replace it.

  32. Junlin Zheng says:

    @DJO2112

    Please check your service version. OData Client Code Generator only supports OData V4 services. For V3 services please continue to use Add Service Reference built in VS.

  33. Telmo says:

    Hi,

    I m trying to run your sample but I am getting this exception

    Microsoft.OData.Core.ODataException was unhandled

     HResult=-2146233079

     Message=The entity instance value of type 'ODataDemo.Product' doesn't have a value for property 'ID'. To compute an entity's metadata, its key and concurrency-token property values must be provided.

    Any idea ?

  34. Allan says:

    Similar to AdamCaviness statement, this "feature" is not consistent.  NamespacePrefix should also be empty by default, not populated.  Default behaviour ends up producing MyClientNamespace.MyServerNamespace namespace.

    The tt file creates 2 namespaces, the namespace provided by service in metadata (good) e.g. Abc.Domain, and Default as long as the NamespacePrefix is empty.

    If I populate it with one that I want e.g. MyNamespace, I end up with MyNamespace.Abc.Domain and MyNamespace.Default.

    I was hoping to leave the Domain namespace alone but set the Default namespace.  As it is currently implemented I am unable to create 2 services Domain1 and Domain2.  My clients never use just one server.

    Can the Default namespace not be generated or provide a flag to turn it on or off?  if I add 2 tt files, I get numerous errors, starting with The namespace 'Default" already contains a definition for 'ExtensionMethods' (which is empty), and another The type 'Default.Container' already contains a definition from 'GeneratedEdmModel'.

    It would be better if we can set a postfix on Default only e.g.  Default.Security, Default.Master, Default.Application, etc.

    How can I change the Container name?  I can't follow the logic that sets that name:

       IEdmEntityContainer container = schemaElements.OfType<IEdmEntityContainer>().Single();

    How do I set this in Code-First that creates my server model?

  35. ing.alfano says:

    @Allan

    I used ODataConventionModelBuilder to build a webApi model from DBContext, then run the template against the up and running webAPI. Hope it helps.

    Anyway I would need more documentation on this, in particular on the client extensibility (new properties/method), any hint?

    Thankyou,

    Alessandro

  36. szymm14 says:

    Hi,

    Could you tell me how to set Authentication Header for client using OData Client Code Generator?

    Thankyou,

    Martin

  37. Khiraling says:

    I'm getting below error and also the *.odata.config is not getting generated.

    Running transformation: System.Net.WebException: Failed to access the metadata document. The OData service requires authentication for accessing it. Please download the metadata, store it into a local file, and set the value of “MetadataDocumentUri” in the .odata.config file to the file path. After that, run custom tool again to generate the OData Client code.