New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code generation from T4 template - IgnoreUnexpectedElementsAndAttributes doesn't seem to work. #1044

Closed
philcarbone opened this Issue Jan 24, 2018 · 7 comments

Comments

Projects
None yet
4 participants
@philcarbone

philcarbone commented Jan 24, 2018

IgnoreUnexpectedElementsAndAttributes = 'true' in the T4 template doesn't seem to ignore attributes that were unexpected. Specifically, 'ConcurrencyMode' is an attribute that our endpoint has in it's metadata and we need it to be ignored.

Reproduce steps

Set: IgnoreUnexpectedElementsAndAttributes = 'true' in the T4 Template
Use mateadata that contains ConcurrencyMode attributes.

Expected result

There would be no runtime errors

Actual result

runtime error:

EdmParseException: Encountered the following errors when parsing the EDMX document: UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (8, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (17, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (37, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (47, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (66, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (84, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (101, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (111, 57) UnexpectedXmlAttribute : The attribute 'ConcurrencyMode' was not expected in the given context. : (124, 57) UnexpectedXmlAttribute : The attribute 'Concurr...

Additional detail

This was originally discussed here: #731 (comment)

@AlanWong-MS AlanWong-MS added the P3 label Jan 25, 2018

@AlanWong-MS

This comment has been minimized.

Contributor

AlanWong-MS commented Jan 25, 2018

The issue appears to be that the IgnoreUnexpectedElementsAndAttributes setting is not propagated to the CsdlReader parser and therefore an exception is thrown when an unexpected element/attribute is read, namely ConcurrencyMode in the reported example.

The setting can be applied in src/CodeGen/ODataT4CodeGenerator.tt, and it should be set wthin src/CodeGen/ODataT4CodeGenerator.ttinclude. Within ODataT4CodeGenerator.ttinclude, the setting is supposed to be propagated to a singleton IEdmModel, but this part of the code does not appear to be ported into the .cs proxy file generated by the Code Gen extension. Rather, the exception is thrown when the code tries to create a new IEdmModel from private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString();, where

private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString()
{
    global::System.Xml.XmlReader reader = CreateXmlReader(Edmx);
    try
    {
        return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader);
    }
    finally
    {
        ((global::System.IDisposable)(reader)).Dispose();
    }
}

I currently do not have the opportunity to pursue the issue further; the next step would be to determine why this particular part of ODataT4CodeGenerator.ttinclude didn't transfer into the generated .cs file.

@tchuan

This comment has been minimized.

Contributor

tchuan commented Jan 30, 2018

This line is generated from here

return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, getReferencedModelFromMap);

I think you need to update the LoadModelFromString() to use the same code as L482 to parse edmModel.

@johnofsaints

This comment has been minimized.

johnofsaints commented Feb 8, 2018

I solved this by adding the following code:
global::Microsoft.OData.Edm.IEdmModel model; System.Collections.Generic.IEnumerable<Microsoft.OData.Edm.Validation.EdmError> errors = null; global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, true, out model, out errors); return model;
Like this we're passing the argument IgnoreUnexpectedElementsAndAttributes = 'true' into the reader.

Unfortunately I'm still getting another exception after this:
'When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataResourceWriter method or the ODataResourceSerializationInfo must be set on the ODataResource or ODataResourceSet that is being written'

@tchuan

This comment has been minimized.

Contributor

tchuan commented Feb 9, 2018

@johnofsaints Replace LoadModelFromString() with the following one, this works perfectly for me.

            private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString()
            {
                global::System.Xml.XmlReader reader = CreateXmlReader(Edmx);
                try
                {
                    return global::Microsoft.OData.Edm.Csdl.EdmxReader.Parse(reader, getReferencedModelFromMap);
                    global::Microsoft.OData.Edm.Csdl.CsdlReaderSettings edmxReaderSettings = new global::Microsoft.OData.Edm.Csdl.CsdlReaderSettings()
                    {
                        GetReferencedModelReaderFunc = getReferencedModelFromMap,
                        IgnoreUnexpectedAttributesAndElements = true 
                    };
                    global::System.Collections.Generic.IEnumerable<global::Microsoft.OData.Edm.Validation.EdmError> errors;
                    global::System.Collections.Generic.IEnumerable<global::Microsoft.OData.Edm.IEdmModel> references = global::System.Linq.Enumerable.Empty<global::Microsoft.OData.Edm.IEdmModel>();
                    global::Microsoft.OData.Edm.IEdmModel edmModel;
                    if (!global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, references, edmxReaderSettings, out edmModel, out errors))
                    {
                        throw new global::System.InvalidOperationException("");
                    }

                    return edmModel;
                }
                finally
                {
                    ((global::System.IDisposable)(reader)).Dispose();
                }
            }
@johnofsaints

This comment has been minimized.

johnofsaints commented Feb 10, 2018

Thanks for the tip, @tchuan !

Can you please share if you're using all latest versions?
Because as mentioned here: Issue1049
The method :
global::Microsoft.OData.Edm.Csdl.EdmxReader
is now renamed to:
global::Microsoft.OData.Edm.Csdl.CsdlReader

@tchuan

This comment has been minimized.

Contributor

tchuan commented Feb 11, 2018

yes, have upgraded all references to 7.4

@AlanWong-MS

This comment has been minimized.

Contributor

AlanWong-MS commented Jun 26, 2018

Fixed with #1150.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment