WCF实现RESETFUL架构很容易,说白了,就是如果WCF能够响应HTTP请求并返回所急需的资源,如果有人非亮堂如何贯彻WCF支持HTTP请求的,可参见我事先的篇章《心想事成jquery.ajax及原生的XMLHttpRequest调用WCF服务之法子》、《兑现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务之办法》,在斯就未发重述。

贯彻WCF支持HTTP请求调用容易,但只要落实类似MVC的ACTION及WEB
API那样的利落,那即便得花费点功夫,为什么这么说呢?因为若WCF的参数为常见档次(即:值类型),那么调用很容易,也支撑HTTP的多种要方法,比如大规模的:GET,POST,例如:

    [ServiceContract]
    public interface IService1
    {
                  [OperationContract]
        [WebInvoke(Method = "*", UriTemplate = "Get/{value}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        string GetData(string value);
    }

    public class Service1 : IService1
    {
        public string GetData(string value)
        {
            return string.Format("You entered: {0}", value);
        }
    }

咱只有待经过浏览器访问使:http://localhost:14719/Service1.svc**/Get/test
 **
注意自己加深的部份,需要和拖欠服务方式及预定的UriTemplate相匹配,与MVC的ROUTE
URL类似,POST也充分简短,在此即不再说明。

上面的调用成功了,你是否就觉着这么即便截止了啊?有没来思了要WCF的服务方法参数为对象(复合类型),例如:

        [OperationContract]
        [WebInvoke(Method = "*",RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        Point GetPoint(Point point);

Point定义:

    [DataContract(Namespace="http://www.zuowenjun.cn/")]
    public class Point
    {
        [DataMember]
        public int X { get; set; }

        [DataMember]
        public int Y { get; set; }

        [DataMember]
        public string Value { get; set; }
    }

        public Point GetPoint(Point point)
        {
            if (point == null)
            {
                throw new ArgumentNullException("point");
            }
            return point;
        }

汝是不是可以像上面那样来拓展GET或POST请求呢?如果可以,那么该怎么调用呢?本人(梦以半路)是一个遇上了问题,就得待将明白和必要解决的食指,所以自己进行了试,首先试一下POST方法,示例代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="jquery-1.4.4.min.js" type="text/javascript"></script>
</head>
<body>
    X:<input id="Text1" type="text" />
    Y:<input id="Text2" type="text" />
    Value:<input id="Text3" type="text" />
    <input id="Button1" type="button" value="button" />
    <fieldset>
        <legend>结果输出:</legend>
        <div id="resultbox">

        </div>
    </fieldset>
    <script type="text/javascript">
        $(function () {
            $("#Button1").click(function () {
                $.ajax({
                    url: "Service1.svc/GetPoint",
                    contentType:"application/json",
                    type: "post",
                    datatype: "json",
                    data: JSON.stringify({ 'point': { 'X': $("#Text1").val(), 'Y': $("#Text2").val(), 'Value': $("#Text3").val()} }),
                    success: function (r,s,x) {
                        $("#resultbox").append("<p>" + JSON.stringify(r) + "</p>");
                    }
                });
            });
        });
    </script>
</body>
</html>

经调用成功,结果如下图示:

jQuery 1

为堪参见DUDU的稿子:jQuery调用WCF服务经常怎样传递对象参数

此地顺便提醒一下,在POST请求WCF服务方式参数为对象时,注意AJAX请求的Data必需是JSON字符串,不能够是JSON对象,如果无明白两者的关联,我这边大概说明一下,

{X:1,Y:2,Value:’test’}
、{‘X’:1,’Y’:2,’Value’:’test’}–这些不论KEY加不加引号,都是JSON对象,可以透过JSON.stringify方法易成JSON字符串

“{X:1,Y:2,Value:’test’}”、”{‘X’:1,’Y’:2,’Value’:’test’}”–这些虽是JSON字符串,可以透过$.parseJSON方法换成JSON对象

然后就是试一下GET方法,在此我就是发硌难矣,该如何开展GET请求呢?参数该怎么对应为?我用AJAX的TYPE改呢GET,然后调用,最后结果返回如下图:

jQuery 2

无异于看即知晓,调用失败,无法为WCF的劳动措施参数point赋值,也不怕是WCF无法正确用请的参数解析成POINT类型对象实例,我尝试着一直当浏览器被走访:

http://localhost:14719/Service1.svc/GetPoint?point={x=1&y=2&value=test},结果仍是报同样的错误,这个问题却是困扰了我几天,我也曾请教过DUDU,QQ群,博问:http://q.cnblogs.com/q/77775/,都没有人能够回答我,有人说复合类型不支持GET,用无了GET就毫无就此之类的讲话,我便想,我的劳务契约上定义之是Method

“*”,而这边GET却死,难道不克因此*,我未放弃,经过多方考察,这首文章让了我肯定的笔触:http://www.cnblogs.com/huangxincheng/p/4621971.html,可以通过自定义MessageFormatter来实现自己想要的解析,好了废话不多说,直接上代码。

自定义PointMessageFormatter:

    public class PointMessageFormatter:IDispatchMessageFormatter
    {
        private IDispatchMessageFormatter innerFormatter;

        public PointMessageFormatter(IDispatchMessageFormatter innerFormatter)
        {
            this.innerFormatter = innerFormatter;
        }

        public void DeserializeRequest(System.ServiceModel.Channels.Message message, object[] parameters)
        {
            innerFormatter.DeserializeRequest(message, parameters);

            if (message.Properties["HttpOperationName"].ToString().Equals("GetPoint",StringComparison.OrdinalIgnoreCase) && parameters.Count() > 0 && parameters[0] == null)
            {
                var request = message.Properties.Values.ElementAt(1) as HttpRequestMessageProperty;
                if (request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase))
                {
                    parameters[0] = DeserializeFromQueryString(request.QueryString);
                }
            }

        }

        private object DeserializeFromQueryString(string queryString)
        {
            if (string.IsNullOrEmpty(queryString)) return null;
            var t=typeof(Point);
            var point = new Point();
            foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                Regex regx = new Regex(string.Format(@"(?<={0}=)(.*?)(?=\&|$)", p.Name), RegexOptions.IgnoreCase);
                string value = regx.Match(queryString).Groups[1].Value;
                try
                {
                    var pValue = Convert.ChangeType(value,p.PropertyType);
                    p.SetValue(point, pValue, null);
                }
                catch
                { }

            }
            return point;
        }

        public System.ServiceModel.Channels.Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            return innerFormatter.SerializeReply(messageVersion, parameters, result);
        }
    }

自定义MyOperationBehavior:

    public class MyOperationBehavior : Attribute, IOperationBehavior
    {
        public int MaxLength { get; set; }

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {

        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.Formatter = new PointMessageFormatter(dispatchOperation.Formatter);
        }

        public void Validate(OperationDescription operationDescription)
        {

        }
    }

下一场修改GetPoint服务方法实现:

        [MyOperationBehavior]
        public Point GetPoint(Point point)
        {
            if (point == null)
            {
                throw new ArgumentNullException("point");
            }
            return point;
        }

事实上方法实现内容无换,就是在那个道及加码了一个表征jQuery:MyOperationBehavior,目的是:当请求调用该方式时,会以自己者定义之PointMessageFormatter,从而实现了由定义解析。

说到底我们再次考试通过GET请求,这里我不怕直通过浏览器访问:http://localhost:14719/Service1.svc/GetPoint?x=12&y=232&value=test,最后返回的结果如下:

jQuery 3

可以看出,调用成功,已经能够正常解析到本人之参数了,当然我上面的实现可能比粗糙,也发为数不少的界定,但我这边只是提供相同栽思路,一栽缓解方案,大家可以根据这个思路实现还牛B的效应。其实WCF的而扩大的地方大多,可以参见artech大牛关于WCF的一连串文章,我感到他的文章写得较透,但就算是理解。这首文章我吧是花了诸多生机勃勃来琢磨和解决,希望会帮忙及大家,如果以为对,给个推荐吧,谢谢!

  

相关文章

网站地图xml地图