Skip to content

Commit

Permalink
Fix #115: MetadataDocumentUri not properly escaping local file paths …
Browse files Browse the repository at this point in the history
…when generating T4 templates (#116)

* Fix #115

* Regenerate `ODataT4CodeGenerator.cs`
  • Loading branch information
unchase authored May 14, 2020
1 parent 6226e4f commit 6d187e4
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 43 deletions.
2 changes: 1 addition & 1 deletion src/CodeGeneration/V4CodeGenDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private async Task AddT4FileAsync()
var text = File.ReadAllText(Path.Combine(t4Folder, "ODataT4CodeGenerator.tt"));

text = Regex.Replace(text, "ODataT4CodeGenerator(\\.ttinclude)", this.GeneratedFileNamePrefix + "$1");
text = Regex.Replace(text, "(public const string MetadataDocumentUri = )\"\";", "$1\"" + ServiceConfiguration.Endpoint + "\";");
text = Regex.Replace(text, "(public const string MetadataDocumentUri = )\"\";", "$1@\"" + ServiceConfiguration.Endpoint + "\";");
text = Regex.Replace(text, "(public const bool UseDataServiceCollection = ).*;", "$1" + ServiceConfiguration.UseDataServiceCollection.ToString().ToLower(CultureInfo.InvariantCulture) + ";");
text = Regex.Replace(text, "(public const string NamespacePrefix = )\"\\$rootnamespace\\$\";", "$1\"" + ServiceConfiguration.NamespacePrefix + "\";");
if (this.TargetProjectLanguage == LanguageOption.GenerateCSharpCode)
Expand Down
18 changes: 9 additions & 9 deletions src/Templates/ODataT4CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ The above copyright notice and this permission notice shall be included in all c

public static class Configuration
{
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
// ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
// MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
Expand All @@ -183,14 +183,14 @@ public static class Configuration
// The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
public const bool UseDataServiceCollection = true;

// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// unless the model has several namespaces.
public const string NamespacePrefix = "$rootnamespace$";

// The target language of the generated client code. The value must be set to "CSharp" or "VB".
public const string TargetLanguage = "OutputLanguage";

// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// For example - "C:\\temp\\Test.xml"
public const string MetadataFilePath = "";

Expand All @@ -214,7 +214,7 @@ public static class Configuration

// (Optional) Custom http headers as a multiline string
public const string CustomHttpHeaders = "";

// Comma-separated list of the names of operation imports to exclude from the generated code
public const string ExcludedOperationImports = "";

Expand Down Expand Up @@ -1726,7 +1726,7 @@ internal void WriteNamespace(string fullNamespace)
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{enumType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand All @@ -1749,7 +1749,7 @@ internal void WriteNamespace(string fullNamespace)
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{complexType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand All @@ -1770,7 +1770,7 @@ internal void WriteNamespace(string fullNamespace)
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{entityType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand Down Expand Up @@ -1802,7 +1802,7 @@ internal void WriteNamespace(string fullNamespace)
if (schemaElements.OfType<IEdmEntityType>().Any() ||
schemaElements.OfType<IEdmOperation>().Any(o => o.IsBound))
{
if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"ExtensionMethods{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand Down Expand Up @@ -2007,7 +2007,7 @@ internal void WriteNamespace(string fullNamespace)
}

this.WriteExtensionMethodsEnd();
if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
this.WriteNamespaceEnd();
context.MultipleFilesManager.EndBlock();
Expand Down
10 changes: 5 additions & 5 deletions src/Templates/ODataT4CodeGenerator.tt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<#+
public static class Configuration
{
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
// ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
// MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
Expand All @@ -11,14 +11,14 @@ public static class Configuration
// The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
public const bool UseDataServiceCollection = true;

// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// unless the model has several namespaces.
public const string NamespacePrefix = "$rootnamespace$";

// The target language of the generated client code. The value must be set to "CSharp" or "VB".
public const string TargetLanguage = "OutputLanguage";

// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// For example - "C:\\temp\\Test.xml"
public const string MetadataFilePath = "";

Expand All @@ -42,7 +42,7 @@ public static class Configuration

// (Optional) Custom http headers as a multiline string
public const string CustomHttpHeaders = "";

// Comma-separated list of the names of operation imports to exclude from the generated code
public const string ExcludedOperationImports = "";

Expand Down Expand Up @@ -96,4 +96,4 @@ public static class Customization
return upperNamespace;
}
}
#>
#>
12 changes: 6 additions & 6 deletions src/Templates/ODataT4CodeGenerator.ttinclude
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,7 @@ public abstract class ODataClientTemplate : TemplateBase
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{enumType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand All @@ -1603,7 +1603,7 @@ public abstract class ODataClientTemplate : TemplateBase
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{complexType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand All @@ -1624,7 +1624,7 @@ public abstract class ODataClientTemplate : TemplateBase
continue;
}

if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"{entityType.Name}{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand Down Expand Up @@ -1656,7 +1656,7 @@ public abstract class ODataClientTemplate : TemplateBase
if (schemaElements.OfType<IEdmEntityType>().Any() ||
schemaElements.OfType<IEdmOperation>().Any(o => o.IsBound))
{
if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
context.MultipleFilesManager.StartNewFile($"ExtensionMethods{(this.context.TargetLanguage == LanguageOption.VB ? ".vb" : ".cs")}",false);
this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false));
Expand Down Expand Up @@ -1861,7 +1861,7 @@ public abstract class ODataClientTemplate : TemplateBase
}

this.WriteExtensionMethodsEnd();
if(context.GenerateMultipleFiles)
if(context.GenerateMultipleFiles)
{
this.WriteNamespaceEnd();
context.MultipleFilesManager.EndBlock();
Expand Down Expand Up @@ -5815,4 +5815,4 @@ End Namespace
<#+
}
}
#>
#>
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public void TestAddGenerateClientCode_GeneratesMultipleFiles()
File.WriteAllText(file1TempPath, "Contents1");
var file2TempPath = Path.Combine(Path.GetTempPath(), "File2.cs");
File.WriteAllText(file2TempPath, "Contents2");

codeGenDescriptor.AddGeneratedClientCodeAsync().Wait();
var expectedMainFilePath = Path.Combine(TestProjectRootPath, ServicesRootFolder, serviceName, "Main.cs");
var mainFile = handlerHelper.AddedFiles.FirstOrDefault(f => f.CreatedFile == expectedMainFilePath);
Expand Down Expand Up @@ -440,7 +440,7 @@ public void TestAddNugetPackageAsync_ShouldNotInstalledODataClientLibrariesIfAlr
installerServices.InstalledPackages.Add(Common.Constants.V4ClientNuGetPackage);

descriptor.AddNugetPackagesAsync().Wait();

var installer = descriptor.PackageInstaller as TestVsPackageInstaller;
Assert.IsFalse(installer.InstalledPackages.Contains(Common.Constants.V4ClientNuGetPackage));
Assert.IsFalse(installer.InstalledPackages.Contains(Common.Constants.V4EdmNuGetPackage));
Expand Down Expand Up @@ -573,7 +573,7 @@ static Project CreateTestProject(string projectPath, ODataT4CodeGenerator.Langua
projectPropertiesMock.Setup(p => p.Item(It.Is<string>(s => s == "FullPath")))
.Returns(fullPathPropertyMock.Object);



var projectMock = new Mock<Project>();
projectMock.SetupGet(p => p.Properties)
Expand Down Expand Up @@ -643,7 +643,7 @@ public TestODataT4CodeGeneratorFactory(ODataT4CodeGenerator generatorToReturn =
}

public ODataT4CodeGenerator LastCreatedInstance { get; private set; }

public ODataT4CodeGenerator Create()
{
var generator = generatorToReturn ?? new TestODataT4CodeGenerator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
<#+
public static class Configuration
{
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
// ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
// MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
public const string MetadataDocumentUri = "https://service/$metadata";
public const string MetadataDocumentUri = @"https://service/$metadata";

// The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
public const bool UseDataServiceCollection = true;

// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// unless the model has several namespaces.
public const string NamespacePrefix = "MyNamespace";

// The target language of the generated client code. The value must be set to "CSharp" or "VB".
public const string TargetLanguage = "CSharp";

// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// For example - "C:\\temp\\Test.xml"
public const string MetadataFilePath = @"$$CsdlFullPath$$";

Expand All @@ -42,7 +42,7 @@ public static class Configuration

// (Optional) Custom http headers as a multiline string
public const string CustomHttpHeaders = @"Key1:val1\nKey2:val2";

// Comma-separated list of the names of operation imports to exclude from the generated code
public const string ExcludedOperationImports = "Operation1;Operation2";

Expand Down Expand Up @@ -96,4 +96,4 @@ public static class Customization
return upperNamespace;
}
}
#>
#>
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
<#+
public static class Configuration
{
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
// ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
// MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
public const string MetadataDocumentUri = "https://service/$metadata";
public const string MetadataDocumentUri = @"https://service/$metadata";

// The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
public const bool UseDataServiceCollection = false;

// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// unless the model has several namespaces.
public const string NamespacePrefix = "";

// The target language of the generated client code. The value must be set to "CSharp" or "VB".
public const string TargetLanguage = "CSharp";

// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// For example - "C:\\temp\\Test.xml"
public const string MetadataFilePath = @"$$CsdlFullPath$$";

Expand All @@ -42,7 +42,7 @@ public static class Configuration

// (Optional) Custom http headers as a multiline string
public const string CustomHttpHeaders = @"";

// Comma-separated list of the names of operation imports to exclude from the generated code
public const string ExcludedOperationImports = "";

Expand Down Expand Up @@ -96,4 +96,4 @@ public static class Customization
return upperNamespace;
}
}
#>
#>
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
<#+
public static class Configuration
{
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path
// eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
// ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
// MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
public const string MetadataDocumentUri = "https://service/$metadata";
public const string MetadataDocumentUri = @"https://service/$metadata";

// The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
public const bool UseDataServiceCollection = false;

// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// The namespace of the client code generated. It replaces the original namespace in the metadata document,
// unless the model has several namespaces.
public const string NamespacePrefix = "";

// The target language of the generated client code. The value must be set to "CSharp" or "VB".
public const string TargetLanguage = "VB";

// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path.
// For example - "C:\\temp\\Test.xml"
public const string MetadataFilePath = @"$$CsdlFullPath$$";

Expand All @@ -42,7 +42,7 @@ public static class Configuration

// (Optional) Custom http headers as a multiline string
public const string CustomHttpHeaders = @"";

// Comma-separated list of the names of operation imports to exclude from the generated code
public const string ExcludedOperationImports = "";

Expand Down Expand Up @@ -96,4 +96,4 @@ public static class Customization
return upperNamespace;
}
}
#>
#>

0 comments on commit 6d187e4

Please sign in to comment.