既然我们已经了解了AddCategories方法,现在就让我们来看看AddCategories方法所用到的助手方法。首先,我们看看ValidateXml方法。像前面所提到的那样,该方法负责确保被添加的Categories XML数据遵从Categories.xsd中所预先定义好的XML模式。 
  
private bool ValidateXml(string xml) 
{ 
  bool validXml = false; 
  //Load the XML data into memory 
  XmlValidatingReader valReader = new  
    XmlValidatingReader(xml,XmlNodeType.Document,null); 
  valReader.Schemas.Add(null, Server.MapPath("Categories.xsd")); 
  valReader.ValidationType = ValidationType.Schema; 
  valReader.ValidationEventHandler += new  
    ValidationEventHandler(ValidationHandler); 
  //Loop through the XML file  
  while(valReader.Read()) 
  {} 
  if (builder.Length > 0) 
    validXml = false; 
  else 
    validXml = true; 
  valReader.Close(); 
  return validXml; 
} 
  
以上代码首先把被添加的XML数据传递给构造函数,创建一个XmlValidatingReader类实例。然后,把Categories.xsd添加到XmlValidatingReader对象的Schemas集合中。接着,设置ValidationType为 ValidationType.Schema,表明我们是在根据XML模式来验证XML数据。当你在使用XmlValidatingReader类验证XML数据时,你必须创建一个事件处理对象,并把它与ValidationEventHandler事件相关联。一旦做完这些后,校验错误和警告就通过这个回调事件处理对象被报告出来。ValidationEventHandler具有一个ValidationEventArgs类型的参数。ValidationEventArgs类提供两个重要属性,Message和Serverity。这两个属性提供更多的有关于校验错误的信息。 
在这种情况下,我们把ValidationEventHandler事件与ValidationHandler方法相关联。在这个方法中,我们附加错误信息到StringBuilder对象中,而该StringBuilder对象定义在模块中。如果没有任何校验错误,那么StringBuilder对象的Length属性将返回0。我们就是使用这个来检查XML模式校验是否失败。ValidationHandler方法定义如下。 
  
public void ValidationHandler(object sender, 
                              ValidationEventArgs args) 
{ 
  builder.Append("Validation error" + "<br>"); 
  builder.Append("Severity:" +  args.Severity + "<br>"); 
  builder.Append("Message:" + args.Message + "<br>"); 
} 
  
下面,让我们来看看RaiseException方法的代码。 
  
public SoapException RaiseException(string uri, 
                                    string webServiceNamespace, 
                                    string errorMessage, 
                                    string errorNumber, 
                                    string errorSource, 
                                    FaultCode code) 
{ 
  XmlQualifiedName faultCodeLocation = null; 
  //Identify the location of the FaultCode 
  switch (code) 
  { 
    case FaultCode.Client: 
      faultCodeLocation = SoapException.ClientFaultCode; 
      break; 
    case FaultCode.Server: 
      faultCodeLocation = SoapException.ServerFaultCode; 
      break; 
  } 
  XmlDocument xmlDoc = new XmlDocument(); 
  //Create the Detail node 
  XmlNode rootNode = xmlDoc.CreateNode(XmlNodeType.Element, 
                     SoapException.DetailElementName.Name, 
                     SoapException.DetailElementName.Namespace); 
  //Build specific details for the SoapException 
  //Add first child of detail XML element. 
  XmlNode errorNode = xmlDoc.CreateNode(XmlNodeType.Element,"Error", 
                                        webServiceNamespace); 
  //Create and set the value for the ErrorNumber node 
  XmlNode errorNumberNode =  
    xmlDoc.CreateNode(XmlNodeType.Element,"ErrorNumber", 
                      webServiceNamespace ); 
  errorNumberNode.InnerText = errorNumber; 
  //Create and set the value for the ErrorMessage node 
  XmlNode errorMessageNode =xmlDoc.CreateNode(XmlNodeType.Element, 
                                              "ErrorMessage", 
                                              webServiceNamespace); 
  errorMessageNode.InnerText = errorMessage; 
  //Create and set the value for the ErrorSource node 
  XmlNode errorSourceNode =  
    xmlDoc.CreateNode(XmlNodeType.Element,"ErrorSource", 
                      webServiceNamespace); 
  errorSourceNode.InnerText = errorSource; 
  //Append the Error child element nodes to the root detail node. 
  errorNode.AppendChild(errorNumberNode); 
  errorNode.AppendChild(errorMessageNode); 
  errorNode.AppendChild(errorSourceNode); 
  //Append the Detail node to the root node 
  rootNode.AppendChild(errorNode); 
  //Construct the exception 
  SoapException soapEx = new SoapException(errorMessage, 
                                           faultCodeLocation, uri, 
                                           rootNode); 
  //Raise the exception  back to the caller 
  return soapEx; 
} 
  
正如其名所提示的那样,RaiseException方法用于以SoapException对象的形式抛出Web服务中的异常。上面所示代码首先检查包含在FaultCode中的枚举参数的值,而该枚举参数用来标识异常发生的源头。如果是因为服务器端的问题(例如,数据库服务器已经关闭)而发生异常,那么应该设置FaultCode的值为SoapException.ServerFaultCode。接着,RaiseException方法创建一个XmlDocument对象来保存detail元素的内容。该对象添加detail元素下的所有子元素,然后把detail节点传递给SoapException对象的构造函数。最后,方法用return语句把SoapException对象返回给调用者。如果你检查SoapException对象内部的detail元素,你会发现它与下面内容有点类似。 
  
<detail> 
        <Error xmlns=" http://tempuri.org/CategoriesService /"> 
          <ErrorNumber>1000</ErrorNumber> 
          <ErrorMessage>Exception Information</ErrorMessage> 
          <ErrorSource>Exception Source</ErrorSource> 
        </Error> 
</detail> 
  
当客户应用程序接收到Web服务的异常时,它可以查看SoapException对象的Detail属性以获取更多的有关于已产生的异常的信息。 
使用SoapException的优点: 
使用SoapException类把异常信息返回给Web服务的客户端,这种方法具有很多的优点。如下: 
l         能够以一致的方式来处理异常情况 
l         基于SOAP规范 
l         通过显示的产生异常,这可以传达更多的信息,例如,异常原因,Web服务方法的URL等等(使用诸如Actor、Code和Detail之类的属性) 
l         使用FaultCode,可以清楚地表示异常归因于客户端还是服务器端 
l         使用Detail属性,可以更详细地描述异常信息  
 
  |