从.ASMX Web服务
我最近更新.ASMX Web服务在其被返回一个XElement
和跨越此错误消息来返回一个的XElement:从.ASMX Web服务
,如今更是产生这个错误下面的代码;
public class FooBarService : System.Web.Services.WebService
{
[WebMethod]
public XElement Foo(string Bar)
{
return null;
}
}
不过,如果我更改代码以接受XElement
而不是String
;
public class FooBarService : System.Web.Services.WebService
{
[WebMethod]
public XElement Foo(XElement Bar)
{
return null;
}
}
然后Web服务不会抛出错误。
那么为什么接受一个XElement并返回一个XElement工作,而不是另一个方法的方法呢?
下手将堆栈跟踪,这表明在异常发生的地方圣
at System.Xml.Serialization.XmlSchemaExporter.ExportElement(ElementAccessor accessor)
at System.Xml.Serialization.XmlSchemaExporter.ExportTypeMapping(XmlTypeMapping xmlTypeMapping)
at System.Web.Services.Description.MimeXmlReflector.ReflectReturn()
at System.Web.Services.Description.HttpProtocolReflector.ReflectMimeReturn()
at System.Web.Services.Description.HttpPostProtocolReflector.ReflectMethod()
使用ILSpy我们可以观察到其触发异常的条件:
// System.Xml.Serialization.XmlSchemaExporter
private XmlSchemaElement ExportElement(ElementAccessor accessor)
{
if (!accessor.Mapping.IncludeInSchema && !accessor.Mapping.TypeDesc.IsRoot)
{
return null;
}
if (accessor.Any && accessor.Name.Length == 0)
{
throw new InvalidOperationException(Res.GetString("XmlIllegalWildcard"));
}
// truncated method body
}
进一步浏览代码:
// System.Web.Services.Description.MimeXmlReflector
internal override bool ReflectReturn()
// System.Xml.Serialization.XmlReflectionImporter
private ElementAccessor
ImportElement(TypeModel model,
XmlRootAttribute root,
string defaultNamespace,
RecursionLimiter limiter)
a第二等等,我们得到这个方法:
// System.Xml.Serialization.XmlReflectionImporter
private static ElementAccessor
CreateElementAccessor(TypeMapping mapping, string ns)
{
ElementAccessor elementAccessor = new ElementAccessor();
bool flag = mapping.TypeDesc.Kind == TypeKind.Node;
if (!flag && mapping is SerializableMapping)
{
flag = ((SerializableMapping)mapping).IsAny;
}
if (flag)
{
elementAccessor.Any = true;
}
else
{
elementAccessor.Name = mapping.DefaultElementName;
elementAccessor.Namespace = ns;
}
// truncated
}
看来,XElement
类型映射获取设置为true
的Any
属性值,但没有得到一个DefaultElementName
。
简单的解决方法的问题是创建一个派生类:
public class FooBarService : System.Web.Services.WebService
{
[WebMethod]
public MyXElement Foo(string bar)
{
return null;
}
}
public class MyXElement : XElement
{
public MyXElement()
: base(XName.Get("default")) { }
}
将在堆栈拨打:
System.Web.Services.Description.SoapProtocolReflector.ReflectMethod()
代替HttpPostProtocolReflector.ReflectMethod()
方法和名称被正确地分配:
messagePart.Name = members[0].MemberName;
要回答你的问题,为什么方法调用在您将XElement
指定为参数时起作用是因为类型映射是通过其他方法创建的,并且name
成员不为空。所以引发异常的情况不会发生。
这是一个很好的答案,谢谢!也感谢您对这个问题的调查! –
当我尝试使用在VS2010中使用Web引用接受&返回MyXElement的服务时,它会创建DataSet类型化参数和返回类型。你如何使用XElement? – xr280xr
相关问题在这里; http://*.com/questions/349769/returning-an-xelement-from-a-web-service - 似乎它可能是一个错误? –
@ChrisMcAtackney是的,我已经读过这个问题,这个链接是从其中一个答案中断开的,其余的并没有解决问题。 –
为什么不返回一个字符串呢? –