none
How to generate an Xml Serialization assembly for a custom XmlSerializer to prevent csc.exe being launched?

    Question

  •  

    I have a custom XmlSerializer within my class to output XML in a different structure to what would be produced with the default serializer. I guess internally .NET still generates a serialization assembly but I would like to generate this assembly after compilation (e.g. using sgen.exe) so it's not generated at runtime. How can I generate a serialization assembly for this custom serializer? If I use sgen for that type it only generates the default serializer.

    In particular the reason I need to generate the serialization assembly is that my .NET assembly is called from within the Internet Explorer process, which runs in Protected Mode. If the .net runtime tries to generate a serialization assembly it calls csc.exe and the user is prompted to allow/deny this process to be run. I don't want users to be prompted! So need all serialization/deserialization to be done without csc.exe.I've tried using sgen.exe /k on the assembly and comparing the .cs file from that with the auto-generated .cs file created when running the program (which I found in c:\users\<myuserame>\appdata\local\temp\low). I can see that the one generated when running the program is the custom XmlSerializer and the one from running sgen.exe is not - for example there are properties with XmlIgnore in the default serializer that don't appear in the sgen.exe version but correctly do appear in the runtime version because the custom XmlSerializer has turned off XmlIgnore on those properties.

     

    One option I can think of is capturing that .cs that's generated at runtime, putting it in a separate assembly and then including that in my product. Apart from being a bit icky, that raises the problem of how to auto-generate that .cs as part of my build process ...

    Perhaps also worth mentioning: my custom XmlSerializer also serializes nested classes, so maybe there would be auto-generated serializers for them too. My custom serialization is mostly done along the lines below - it adds XmlIgnore to some properties and removes XmlIgnore from others. Many of these properties return objects that would need to be serialized, some of which implement IXmlSerializable, some use default serialization.

     

     

    	    public void SerializeToCustomXml1(XmlWriter writer)
    
    	    {
    
    	        try
    
    	        {
    
    	            CustomXmlSerializer1.Serialize(writer, this);
    
    	        }
    
    	        catch (Exception)
    
    	        {
    
    	        }
    
    	    }
    
    	    /// <summary>
    
    	    /// Static serializer so it's created just once. There's another one like this CustomXmlSerializer2 with a slightly different format again.
    
    	    /// </summary>
    
    	    private static XmlSerializer CustomXmlSerializer1
    
    	    {
    
    	        get
    
    	        {
    
    	            if (_customXmlSerializer == null)
    
    	            {
    
                        XmlAttributes dontIgnore = new XmlAttributes();
    
                        dontIgnore.XmlIgnore = false;
    
                        
    
                        XmlAttributes attributes;
    
    	                XmlAttributeOverrides overrides = new XmlAttributeOverrides();
    
    				
    
    					// Include some fields in the XML that wouldn't be there otherwise.
    
                        overrides.Add(typeof (WebResource), "ID", dontIgnore);
    
                        overrides.Add(typeof (WebResource), "HasDestinationURLs", dontIgnore);
    
    	                overrides.Add(typeof (Resource), "AccessDefindBy", dontIgnore);
    
    
    
    					
    
    	                attributes = new XmlAttributes();
    
    	                attributes.XmlIgnore = false;
    
    	                attributes.XmlElements.Add(new XmlElementAttribute("ActionID"));
    
    	                overrides.Add(typeof(Action), "ID", attributes);
    
    					
    
    	                // Instead of serializing the Actions field we serialize CustomActionsXmlSerializer,
    
    	                // which outputs different content in the XML
    
    	                overrides.Add(typeof (WebResource), "Actions", ignore);
    
    	                attributes = new XmlAttributes();
    
    	                attributes.XmlIgnore = false;
    
    	                attributes.XmlElements.Add(new XmlElementAttribute("Actions"));
    
    	                overrides.Add(typeof (WebResource), "CustomActionsXmlSerializer", attributes);					
    
    					
    
    					// ... more of these overrides here ... 
    
    
    
    	                _customXmlSerializer1 = new XmlSerializer(typeof(WebResource), overrides);
    
    	            }
    
    	            return _customXmlSerializer1;
    
    	        }
    

     

     

    Any ideas?

    thanks, 

    Rory

    (Cross-posted to ASMX Web Services and XML Serialization forum here and Stack Overflow here.)
    • Edited by Rory PS Wednesday, September 07, 2011 5:05 PM
    Wednesday, September 07, 2011 5:01 PM

All replies

  • Hi,

     

    Thank you for your question, we're doing research on this case, it might take some time before we get back to you.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, September 08, 2011 2:18 AM
  • Thanks Eric. From what I've determined, XmlSerializer doesn't ever look for an existing assembly when using the Serialize method that takes overrides. Therefore there's no way to use XmlSerializer directly in this way without it calling csc.exe.

    My options as I see it: 

    • Restructure all the XmlIgnore (etc) attributes on my classes so the XmlSerializer.Deserialize() method without overrides can be used. Then use sgen.exe to generate the XmlSerializers assembly and ship it with my product. This would require quite a few changes to many classes in my existing code so isn't ideal.
    • Capture the .cs code that's generated when I use the XmlSerializer.Deserialize() method with overrides. Add this to my project and call that code directly instead of calling XmlSerializer.Deserialize(). It's not clear how to generate/capture this .cs code in an automated way to include in my build process. Besides that problem, this would require fewest changes to existing code.
    • Rewrite my serialization to use a different technique. I think this would be a lot of work and error prone. e.g. I could implement IXmlSerializable and use a class field to indicate which XML format is desired. The caller would set that field, then call XmlSerializer.Serialize/Deserialize and within WriteXml/ReadXml my object would write/read xml in a format based on the value of that field. Implementing IXmlSerializable is a real drag, and with many nested objects I'd need to implement this field & IXmlSerializable on several different classes, which would be a lot of work, error prone, and not resiliant to future class changes.

    If you have any suggestions that would be great!

    thanks, 

    Rory


    • Edited by Rory PS Friday, September 09, 2011 9:35 AM
    Thursday, September 08, 2011 9:40 PM
  • Hi Rory ,

    Are you able to figur this out if not ,  I will suggest you to open a ticket with Micsrosoft CSS. Below is the link you can use :

    http://support.microsoft.com/contactus/?ws=support

    Thanks

     

    Saturday, October 08, 2011 6:58 AM
  • My current solution is as follows: 

    1. Run my app within Internet Explorer with Protected Mode On, logged in as an Admin. 
    2. IE prompts me asking if I want to run csc.exe at the point my XmlSerializer.Deserialize() is called. I don't click Yes or No just yet.
    3. I open C:\Users\<username>\AppData\Local\Temp\Low in Explorer
    4. Grab the randomly named .cs file and save it into my project. I name it using the same filename every time so it works with the project and source control.
    5. Edit the file & comment out the assembly attribute about line 6, else it'll conflict with my other version attribute: [assembly:System.Reflection.AssemblyVersionAttribute("4.0.10.0")]
    6. Modify the line that creates my XmlSerializer with XmlAttributeOverrides, changing it to: 
      XmlSerializer serializer = (new Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract()).GetSerializer(typeof( < my type > )); 
    Now when I run my app it doesn't need to call csc.exe because it uses the serializer that was already generated by csc.exe in that randomly-named cs file.

    This works but is horrible. Each time I make a change to any of my business objects that are serialized I need to comment out the line from step 7, changing it back to the old XmlSerializer, then run through those steps again. Apart from being manual, what if IE changes its behavior to not prompt but just to block csc.exe from being run? It would be great if there were a way of automating this process. Any suggestions very welcome!

    thanks, 

    Rory

     

     

     

    Sunday, October 09, 2011 10:06 PM
  • Is there a more specific link you could suggest for contacting Microsoft CSS? (and what is CSS?) That link takes me to a multitude of pages that try to stop me from contacting anyone.

    thanks,

    Rory

    Sunday, October 09, 2011 10:10 PM
  • Rory CSS is "Customer Support Service" . You will speak Tech Router ,Based on your Issue they will route you to engineer who are specialised in that area.  TR Line :  US - 1-800-936-5800
     
    Regards
    Madhuban
    Tuesday, October 11, 2011 2:14 AM