Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared

I have a strange problem, I have a web service as part of my system that installed on some customers, meaning every customer have a identical copy of the WS.

When I compile the WS everything is working fine, on my server and on most of customers machine but there is one customer that sometimes reporting the following error(generally the WS working fine for this customer, 90% of the time):

Description:
AgentWS: [2852] [525] [Emergency] 
System.Xml.Schema.XmlSchemaException: The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared.
   at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   at System.Xml.Schema.BaseProcessor.SendValidationEvent(XmlSchemaException e, XmlSeverityType severity)
   at System.Xml.Schema.BaseProcessor.AddToTable(XmlSchemaObjectTable table, XmlQualifiedName qname, XmlSchemaObject item)
   at System.Xml.Schema.Compiler.Prepare(XmlSchema schema, Boolean cleanup)
   at System.Xml.Schema.XmlSchemaSet.Compile()
   at System.Xml.Serialization.XmlSchemas.Compile(ValidationEventHandler handler, Boolean fullCompile)
   at System.Web.Services.Description.SchemaCompiler.Compile(XmlSchemas schemas)
   at System.Web.Services.Description.WebServicesInteroperability.AnalyzeDescription(ServiceDescriptionCollection descriptions, BasicProfileViolationCollection violations)
   at System.Web.Services.Description.WebServicesInteroperability.CheckConformance(WsiProfiles claims, ServiceDescriptionCollection descriptions, BasicProfileViolationCollection violations)
   at ASP.defaultwsdlhelpgenerator_aspx.Page_Load(Object sender, EventArgs e) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\DefaultWsdlHelpGenerator.aspx:line 1439
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Any one has any idea?? thanks!

like image 948
Dor Cohen Avatar asked Jun 03 '12 14:06

Dor Cohen


3 Answers

Your problem is exactly what it says: you get that particular attribute defined twice. It can happen due to a bug in .NET (which I'll refer to it later) or simply due to a configuration issue. To understand what I am talking about, more so that you can figure out how to best deal with it in your particular environment, I'll give you a recipe on how to reproduce it. It is all based on the same XmlSchemaSet object, referred to in your stack trace.

Some of the steps are specific to the tool that I am using; I'll try to provide alternatives where I can think of something.

Base.xsd : this is in place of xml.xsd file

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="something">
        <xs:sequence>
            <xs:element name="aha" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Some.xsd: this is a palceholder for the other XSD files in your setup. What's special about it, is that through various include/imports it "reaches out" to the above Base.xsd.

<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">    
    <xsd:include schemaLocation="base.xsd"/>
    <xsd:include schemaLocation="http://localhost:9090/base.xsd"/>

    <xsd:element name="a" type="something"/>    
</xsd:schema>

I've set up two includes, to mimic more than one possible way to "reach out" to Base.xsd.

The localhost URL should come through some http server: use your local IIS, any other HTTP server or HTTP mocking software you can control as you need.

Write a little C# script that compiles "Some.xsd", based on XmlSchemaSet. Something such as this from the online help for the Compile method would work.

Firstly, make sure that the URL in the second include is not available. Run the script. You'll see that the result is successful compilation!

Then, make sure the URL is serving ok; run the script. You'll get the same error as in your scenario, content already defined.

You have to understand how schema loading works in .NET, and how schema compilation works. Bottom line is if you load the same content from the same uri twice or more, the XSD compiler is typically smart enough to figure it out. If you load the same content from two different URIs, then the compiler can't guess what your intention was; for all it cares, different URIs means different schemas, hence "already declared" error.

Based on the above, it may be that on the machine where you get the exception, there is access to xml.xsd through different URIs.

I would use a specialized tool that would load your WSDL and give you a graph of all its dependencies (other WSDLs and/or external XSDs). In it you should see immediately if xml.xsd comes from two different places.

If the above still doesn't yield enough understanding... To troubleshoot, first see if you can get your stuff run without external connectivity ("pull the network plug" he said...). Then, run an http debugger, Fiddler is an example, on the machine where the WS runs, where you get the exception and where you don't. Monitor for the error and correlate with the debug trace.

This should get you going in the right direction. Unlike some of the comments, I wouldn't bother disabling the WS-I BP check; as you figured it out already, that doesn't really deals with your question.

As to the bug in .NET, it is a very remote, but possible, scenario. I assume you've already checked the patch levels. The only reason I've mentioned it is because I ran myself into it, and I had to write my own resolver to get around it. Even with the latest .NET is still there but then it'll manifest itself all the time... Which is why I doubt it is this bug in your case...

like image 23
Petru Gardea Avatar answered Nov 13 '22 23:11

Petru Gardea


I had a similar problem where the following code also threw exceptions saying that global attributes were already defined.

    xmlSchemaSet = new XmlSchemaSet();
    xmlSchemaSet.Add(null, schemaFileName);
    xmlSchemaSet.Compile();

It's being cached somewhere since the definitions I'm using are correct. However, a simple solution is to add a validation handler and ignore the ones you don't want errors from.

Change the original code to have a schema validation event handler:

    xmlSchemaSet = new XmlSchemaSet();
    xmlSchemaSet.Add(null, schemaFileName);
    xmlSchemaSet.ValidationEventHandler += xmlSchemaSet_ValidationEventHandler;
    xmlSchemaSet.Compile();

and then have a handler like:

/// <summary>
/// Ignore the global attribute already declared errors we sometimes get because of some caching.
/// This happens with xml.xsd.
/// </summary>
private static void xmlSchemaSet_ValidationEventHandler(object sender, ValidationEventArgs e)
{
  if (!e.Exception.Message.Contains("has already been declared"))
  {
    throw e.Exception;
  }
}
like image 122
Herb F Avatar answered Nov 13 '22 23:11

Herb F


I had this problem when adding a web reference in Microsoft Visual Studio 2013 while the project was not compiling. This seems to cause multithreading issues in the WSDL generator code.

Issue does not occur when adding web reference when client code compiles.

like image 1
Dennis van der Pool Avatar answered Nov 13 '22 22:11

Dennis van der Pool