WCF Rest 服务一些问题备忘

47 篇文章 0 订阅
14 篇文章 0 订阅

1.如果要想让服务自动支持JSON格式,类的DataContract属性一定要加上Namespace。如果不加,则用改类作为参数的服务只能使用xml格式。

    [DataContract(Namespace = "")]
    public class UserProfile
    {}

2. 返回的xml中,如果不希望空节点输出 i:nil="true", 需要加上[XmlSerializerFormat]属性,但是加上该属性后不能再使用json格式的请求和返回。

3.如果服务中参数用到类,则请求该类的xml中各xml节点必须按字母顺序排序,否则系统自动反序列化得到的类有些字段得不到值。

因为wcf默认的序列化方式是 DataContractSerializer,对象的所有成员以XML Element的形式而不是以XMLAttribute的形式输出,所以对象在XML的输出顺序是按照字母排序。

 如果客户端生成的xml已经是按字母顺序排好的,没有问题。我们也可以在服务端把客户端请求的xml按字母顺序排序,这样客户端就不用注意节点顺序的问题了。实现方法如下:

   1). 实现IServiceBehavior接口

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            IErrorHandler handler = new FaultErrorHandler();

            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(handler);

                dispatcher.Endpoints.ToList().ForEach(
                    x => x.DispatchRuntime.MessageInspectors.Add(new MessageInspector()));
            }
        }

2).

public class MessageInspector:IDispatchMessageInspector
    {
        //int MaxMessageSize = PhoneCommon.ReceivedMaxSize;

        //XmlWriterSettings xws;

        public MessageInspector()
        {
            //this.xws = new XmlWriterSettings();
            //this.xws.Indent = true;
            //this.xws.Encoding = Encoding.UTF8;
        }

        #region IDispatchMessageInspector Members

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            // Get the request message from the request
            HttpRequestMessageProperty requestMessage = request.Properties["httpRequest"] as HttpRequestMessageProperty;
            string method = string.Empty;
            if (requestMessage != null)
            {
                // The method will be GET or POST.
                method = requestMessage.Method;
                if (requestMessage.Headers["Content-Type"].ToLower().Contains("xml"))
                {
                    if (method.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
                    {
                        ReOrderXmlElementAlphabetical(ref request);
                    }
                }
            }           
            Object correlationState = new object();
            return correlationState;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            //throw new NotImplementedException();
        }

        #endregion

        private void ReOrderXmlElementAlphabetical(ref Message message)
        {
            //MessageBuffer msgBuffer = message.CreateBufferedCopy(MaxMessageSize);
            //Message copy = msgBuffer.CreateMessage();

            //StringBuilder xmlsb = new StringBuilder();
            //XmlWriter writer = XmlWriter.Create(xmlsb, this.xws);           
            //copy.WriteMessage(writer);
            //writer.Flush();

            //message = msgBuffer.CreateMessage();
            //msgBuffer.Close();

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(message.ToString());
                XmlUtils.SortXml(doc);

                MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(doc.OuterXml));
                XmlReader bodyReader = XmlReader.Create(ms);

                message = Message.CreateMessage(message.Version, null, bodyReader);
            }
            catch (Exception ex)
            {
            }
        }
    }

3).

public abstract class XmlUtils
    {
        /// <summary>
        /// Alphabetical sorting of the XmlNodes
        /// and their  attributes in the <see cref="System.Xml.XmlDocument"/>.
        /// </summary>
        /// <param name="document"><see cref="System.Xml.XmlDocument"/> to be sorted</param>
        public static void SortXml(XmlDocument document)
        {
            SortXml(document.DocumentElement);
        }

        /// <summary>
        /// Inplace pre-order recursive alphabetical sorting of the XmlNodes child
        /// elements and <see cref="System.Xml.XmlAttributeCollection" />.
        /// </summary>
        /// <param name="rootNode">The root to be sorted.</param>
        public static void SortXml(XmlNode rootNode)
        {
            SortAttributes(rootNode.Attributes);
            SortElements(rootNode);
            foreach (XmlNode childNode in rootNode.ChildNodes)
            {
                SortXml(childNode);
            }
        }

        /// <summary>
        /// Sorts an attributes collection alphabetically.
        /// It uses the bubble sort algorithm.
        /// </summary>
        /// <param name="attribCol">The attribute collection to be sorted.</param>
        public static void SortAttributes(XmlAttributeCollection attribCol)
        {
            if (attribCol == null)
                return;

            bool hasChanged = true;
            while (hasChanged)
            {
                hasChanged = false;
                for (int i = 1; i < attribCol.Count; i++)
                {
                    if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name, true) < 0)
                    {
                        //Replace
                        attribCol.InsertBefore(attribCol[i], attribCol[i - 1]);
                        hasChanged = true;
                    }
                }
            }

        }

        /// <summary>
        /// Sorts a <see cref="XmlNodeList" /> alphabetically, by the names of the elements.
        /// It uses the bubble sort algorithm.
        /// </summary>
        /// <param name="node">The node in which its childNodes are to be sorted.</param>
        public static void SortElements(XmlNode node)
        {
            bool changed = true;
            while (changed)
            {
                changed = false;
                for (int i = 1; i < node.ChildNodes.Count; i++)
                {
                    if (String.Compare(node.ChildNodes[i].Name, node.ChildNodes[i - 1].Name, true) < 0)
                    {
                        //Replace:
                        node.InsertBefore(node.ChildNodes[i], node.ChildNodes[i - 1]);
                        changed = true;
                    }
                }
            }
        }
    }

 

publicobjectAfterReceiveRequest(refSystem.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)

02. {
03. // Get the request message from the request
04. HttpRequestMessageProperty requestMessage = request.Properties["httpRequest"]asHttpRequestMessageProperty;
05. stringmethod =string.Empty;
06. if(requestMessage !=null)
07. {
08. // The method will be GET or POST.
09. method = requestMessage.Method;
10. }
11.  
12. // Get the UriTemplateMatchResults from the request.
13. // Here you can see some of the fun things that are revealed.
14. UriTemplateMatch results = internalCopy.Properties["UriTemplateMatchResults"]asUriTemplateMatch;
15. if(results !=null)
16. {
17. // Get the operation name from the request.
18. // Here you can see what method was called in the Service.
19. // Since we have only one method (SchemeTest), it should be this.
20. // We can add a simple 'HelloWorld' method to see this value change.
21. stringoperationName =string.Empty;
22. if(results.RelativePathSegments.Count > 0)
23. operationName = results.RelativePathSegments[results.RelativePathSegments.Count - 1];
24.  
25. //
26. stringrequestUri = results.RequestUri.ToString();
27.  
28. // If the request method is GET, then you can play with the query parameters, uri template, and bound variables
29. if(method =="GET")
30. {
31.  
32. // Loop thru the querry parameters
33. NameValueCollection queryParameters = results.QueryParameters;
34. foreach(var pin queryParameters)
35. {
36. Console.WriteLine(p);
37. }
38.  
39. // The Uri template is the same as in the Attribute of the interface: [WebGet(UriTemplate = "SchemeTest?name={name}")]
40. stringtemplate = results.Template.ToString();
41.  
42. // You can loop thru the key in the variables passed in.
43. NameValueCollection boundVariables = results.BoundVariables;
44. foreach(stringkey in boundVariables.AllKeys)
45. {
46. // Variable names are always in UPPER case. Don't know why.
47. if(key =="NAME")
48. Console.WriteLine("This is the 'name' key");
49. }
50. }
51.  
52. Object correlationState =newobject();
53. returncorrelationState;
54. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值