OData / OData/ODataConnectedService

Class property Context appears to be defined using the incorrect type of string vs DataServiceContext

Open
#331 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
84
Forks
52
Avg merge
8h 39m
Merged PRs (30d)
7

Description

When generating client proxies the variable _Context as defined in the C# proxy for a entity can result in compile time errors.
To reproduce the problem, the OData metadata being used is that for Microsoft Dynamics HR. In this case all types and all bound actions are selected for generation. The following is the URL I was using with the some tenant id being that relevant for my scenario. A custom header was used to specify the bearer token for authentication purposes. I have attached the metadata as a text file to save you the trouble of going to the service end point.

eg. https://aos-rts-sf-c8d2e0b7ff3-prod-westeurope.hr.talent.dynamics.com/namespaces/some tenant id/data

In particular the following two compile time errors are created:

CS1061: 'string' does not contain a definition for 'EntityTracker' and no accessible extension method 'EntityTracker' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
CS1503: Argument 1: cannot convert from 'string' to 'Microsoft.OData.Client.DataServiceContext'

and these occur with the entity type <EntityType Name="EssWorkflowWorkItem"> where the bound action "complete" results in generation of the code

        [global::Microsoft.OData.Client.OriginalNameAttribute("complete")]
        public virtual global::Microsoft.OData.Client.DataServiceActionQuery Complete(string outcome, string comment)
        {
            global::Microsoft.OData.Client.EntityDescriptor resource = Context.EntityTracker.TryGetEntityDescriptor(this);
            if (resource == null)
            {
                throw new global::System.Exception("cannot find entity");
            }

            return new global::Microsoft.OData.Client.DataServiceActionQuery(this.Context, resource.EditLink.OriginalString.Trim('/') + "/Microsoft.Dynamics.DataEntities.complete", new global::Microsoft.OData.Client.BodyOperationParameter("outcome", outcome),
                    new global::Microsoft.OData.Client.BodyOperationParameter("comment", comment));
        }

On inspection the property Context appears to be type string but should be type DataServiceContext. The following snippet is the generated fragment.

        [global::Microsoft.OData.Client.OriginalNameAttribute("Context")]
        public virtual string Context
        {
            get
            {
                return this._Context;
            }
            set
            {
                this.OnContextChanging(value);
                this._Context = value;
                this.OnContextChanged();
                this.OnPropertyChanged("Context");
            }
        }

There is also the definition of a property ContextString which I believe to be causing some confusion in the template.

        [global::Microsoft.OData.Client.OriginalNameAttribute("ContextString")]
        public virtual string ContextString
        {
            get
            {
                return this._ContextString;
            }
            set
            {
                this.OnContextStringChanging(value);
                this._ContextString = value;
                this.OnContextStringChanged();
                this.OnPropertyChanged("ContextString");
            }
        }

[metadata.txt](https://github.com/OData/ODataConne
metadata.txt
ctedService/files/10345616/metadata.txt)

At this point the workaround for me has been to alter the generated code such that property _Context is defined as DataServiceContext. viz.

    [global::Microsoft.OData.Client.OriginalNameAttribute("Context")]
    public virtual DataServiceContext Context
    {
        get
        {
            return this._Context;
        }
        set
        {
            this.OnContextChanging(value);
            this._Context = value;
            this.OnContextChanged();
            this.OnPropertyChanged("Context");
        }
    }
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "#VersionNumber#")]
    private DataServiceContext _Context;
    partial void OnContextChanging(**DataServiceContext** value);

This would point to some error in the T4 template caused by the confusion between Context and ContextString

VisualStudio Version v17.4.3
Microsoft.Odata.Client v7.13.x
metadata.txt

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attached metadata.txt and the generated C# proxy for EssWorkflowWorkItem, then inspect the T4 template where Context and ContextString are handled. Regenerate the proxy against this metadata and verify that the bound complete action compiles with Context typed as DataServiceContext rather than string.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
devtools, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.