_From @dsplaisted on May 10, 2017 18:48_
Adding a .resx file to an SDK project using Visual Studio results in the following added to the project file:
<ItemGroup>
<Compile Update="Resource1.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource1.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resource1.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource1.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
Ideally, nothing would be added to the project file when you add a .resx to the project. We may be able to do this in the SDK just by setting the appropriate metadata on the implicit EmbeddedResource items and the Compile items for .Designer.cs files.
_Copied from original issue: dotnet/sdk#1199_
_From @wli3 on September 14, 2017 0:48_
It need a way to link each other, by convention? I am thinking start from blah.resx, and look for in @(Compile), if there is a file matches blah.Designer.cs then "link" them.
Related #1441
_From @wli3 on September 20, 2017 17:12_
(Some what related https://github.com/Microsoft/VSProjectSystem/issues/169 https://github.com/dotnet/project-system/issues/1467#issuecomment-327064967)
_From @davkean on September 26, 2017 0:39_
I've done some research on what some of this metadata is used for:
Conclusion, we can remove all metadata from the designer file.
_From @wli3 on July 19, 2018 18:46_
@dsplaisted @davkean sorry for the long delay. Conclude from David's research, can we close this issue?
_From @davkean on July 19, 2018 23:31_
We never removed the metadata, so the bug is still relevant. We should move to project system.
@davkean is this distinct from #1158?
Is the result of this isseu a failure to nest files in the solution explorer?
Using this explicitly:
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<Dependent

But commenting that out yield this:

Is there a workaround for this? I attempted to follow this stackoverflow answer to implicitly add the metadata, but then VS still doesn't seem to nest or autogenerate the file as needed.
I think that in recent VS releases, the items in solution explorer should now be automatically nested appropriately without any explicit metadata in the project file. Is this correct @davkean?
It doesn't seem to be the behavior that I have observed, using VS2019 16.5 and donetsdk 3.1.201 - at least for a Microsoft.NET.Sdk project.
I did determine that you can use the stackoverflow answer, but if you're intending to share the settings, it must be done via Directory.Build.targets instead of Directory.Build.props - which is where I first attempted to use it and it didn't work.
I don't think it nests yet, and besides that it also adds or fills this back in to the csproj every time you save the .resx file:
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
(By constrast, non-standalone .resx files nest automatically and don't insert pollution into the csproj when edited.)
it also adds or fills this back in to the csproj every time you save the .resx file
What version of Visual Studio are you using? https://github.com/dotnet/project-system/issues/2873 should have solved that in 16.5, where any item metadata will not be written to the project file if it already has that value at that point of the evaluation (ie, if your globbing is in Directory.Build.props or something imported at the start of the project)
It's reproing in 16.5.2, both the lack of nesting and generating the block I posted above. I'll put a repro project here I guess.
Use any SDK csproj, such as this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
And add this empty .resx file at PropertiesResources.resx, or add one using the Add New Item dialog:
Click to expand
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
If you didn't use the Add New Item dialog, open the .resx and select either the Internal or Public access modifier to get it to generate the corresponding designer file. Now, save and look at the csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
Why is this there? Surely Internal is the default and there should be nothing at all in the csproj representing that, and Public would be a single piece of metadata added as an attribute to save space.
Here's the result:

Now, let's remove these values from the csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
The nesting is gone:

Now, let's say I remove what seems to be inessential or should be SDK defaults, but I leave the metadata that appears to be required in order to nest, and I leave the metadata that appears to be required to keep the RESX designer from switching from Internal to (custom):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs" DependentUpon="Resources.resx" />
<EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator" />
</ItemGroup>
</Project>
For one thing, VS constantly tries to auto expand these to fill out the metadata I removed, while I'm typing. It's a little weird. I fight it using Ctrl+Z several times and manage to save.
Now I open the RESX designer, add a single string entry, and click Save. The csproj bloats back up:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs" DependentUpon="Resources.resx">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
<EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator">
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
.settings files act just the same as the description above of .resx files:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>
All the above appears to repro in VS 16.6-p2.1 as well.
Sorry, I misunderstood what you were saying originally. I thought you meant you had globs in place that would mean all of that extra info in the project file wasn't needed. Without anything custom involved, indeed the SDK doesn't default any of that info. We do have https://github.com/dotnet/project-system/issues/5707 logged to improve that situation, but what you're seeing in these comments is what would be expected with the current SDK.
I'm sorry! Thanks for that issue reference. I'll follow that then.
So if #5707 handles the request that the metadata should already be added by the SDK, which issue handles the bug that Visual Studio adds the metadata for specifc files again even if all metadata is already correctly set by glob updates? This one?
I did determine that you can use the stackoverflow answer, but if you're intending to share the settings, it must be done via
Directory.Build.targetsinstead ofDirectory.Build.props- which is where I first attempted to use it and it didn't work.
I also noticed that setting the metadata in glob updates in the Directory.Build.props file doesn't work. Very weird, since this is the correct location for such things, right? Will this also be handled in this issue? Or is there a seperate issue for it?
which issue handles the bug that Visual Studio adds the metadata for specifc files again even if all metadata is already correctly set by glob updates?
https://github.com/dotnet/project-system/issues/2873 fixed things so that metadata would not be written for items if it already matched the value at that point in evaluation, so it would rely on globs being in props and not targets. It sounds like its worth logging a new issue for the problems you had with using a props file to see if there is another bug there.
It looks like something is off in the project system for the general (non-.resx) case.
Please consider the example -- CodegenProjects. Load it into VS (using 16.7.7 right now), then try to copy the Test.tt file. Also, try adding a new Test2.tt file, then save all files and observe the diff for the project file. It looks like it adds unnecessary files and sometimes even breaks evaluation (adding things like <LastGenOutput>%(Filename).cs</LastGenOutput> instead of <LastGenOutput>Test1 - Copy.cs</LastGenOutput>).
P.S. I'm not sure if this is a perfect issue to add this comment to; I would gladly move it to a new issue if considered a separate one.