The most common reason for VS-triggered sgen (i.e. via Properties->Build->Generate serialization assembly) to not actually produce a serialization assembly is because the default Sgen build task in VS includes the /proxytypes switch by default, and there is no way to turn it off. This switch tells sgen to only generate serializers for Xml Web service proxy types, as documented here. To generate serializers for other types, you can override the default behavior by adding your own custom task as described in Generating an Xml Serialization assembly as part of my build. You can go further and specify only the types you want serialization code generated for via the Types parameter, e.g.:
<PropertyGroup>
<!-- Specific set of types to create serialization assemblies for -->
<SerializationTypes>
Type1;
Type2
</SerializationTypes>
</PropertyGroup>
<!-- Custom non-proxy SGEN invocation to create pre-compiled serialization assemblies -->
<Target Name="GenerateNonProxySerializationAssemblies"
DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
Outputs="$(OutputPath)$(_SGenDllName)">
<SGen BuildAssemblyName="$(TargetFileName)" Types="$(SerializationTypes)"
BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)"
ShouldGenerateSerializer="true" UseProxyTypes="false"
KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)" ToolPath="$(SGenToolPath)">
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
</Target>