To implement a pass-through object (composite type) parameter when a WCF service is invoked under a GET request

Source: Internet
Author: User

WCF implements the Resetful schema very easily, and plainly, that is, to enable WCF to respond to HTTP requests and return the required resources, if someone does not know how to implement WCF support HTTP requests, see my previous article, " Implementing Jquery.ajax and native XMLHttpRequest methods for invoking WCF services, "Implementing Jquery.ajax and native XMLHttpRequest methods for invoking WCF services across domains," is not restated here.

Implementing WCF support for HTTP request invocation is easy, but it takes a bit of effort to implement an MVC-like action and Web API, and that would take some time. Because if the parameters of WCF are normal types (that is, value types), then the invocation is easy and supports multiple request methods for HTTP, such as common: Get,post, for example:

    [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);        }    }

We only need to access through the browser such as: Http://localhost:14719/Service1.svc/get/test attention to my deepened part, need to be with the service method agreed on the UriTemplate match, Similar to MVC's route URL, post is simple and is no longer explained here.

If the above call succeeds, do you think it's over? Ever wondered if WCF's service method parameters are objects (composite types), for example:

        [OperationContract]        [WebInvoke (Method = "*", Requestformat = Webmessageformat.json, Responseformat = Webmessageformat.json, BodyStyle = Webmessagebodystyle.wrappedrequest)] Point        getpoint;

The point definition:

    [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        {            if (point = = null)            {                throw new ArgumentNullException ("point");            }            return point;        }

Can you make a GET or POST request like the one above? If so, how do you call it? I (Dream on the road) is a problem, it must be understood and necessary to solve the people, so I experimented, first try the Post method, the sample code is as follows:

Successful invocation, the results are as follows:

You can also see the article Dudu: How to pass object parameters when jquery calls a WCF service

Here, incidentally, when the POST request WCF service method parameter is an object, note that the AJAX request data must be a JSON string, not a JSON object, if you do not understand the relationship between the two, I briefly explain here,

{x:1,y:2,value: ' Test '}, {' X ': 1, ' Y ': 2, ' Value ': ' Test '}--these are JSON objects that can be converted to JSON strings by json.stringify method, regardless of the key.

"{x:1,y:2,value: ' Test '}", "{' X ': 1, ' Y ': 2, ' Value ': ' Test '}"-these are JSON strings that can be converted to JSON objects by the $.parsejson method

Then try the Get method, I'm a little bit difficult here, how to make a GET request? How does the parameter correspond? I changed the type of Ajax to get and then called, and the final result is returned as:

As you can see, the call fails to assign a value to the WCF service method parameter point, which means that WCF cannot correctly parse the requested parameter into a point type object instance, and I try to access it directly in the browser:

Http://localhost:14719/service1.svc/getpoint?point={x=1&y=2&value=test}, the result is still reported the same error, this problem is troubled me for a few days, I have consulted the DUDU,QQ group, Bo asked: http://q.cnblogs.com/q/77775/, no one can answer me, some people say that the composite type does not support get, do not use get not to use such words, I think, my service contract is defined as Method = "* "And here get but not, can not use *, I do not give up, after a multi-check, this article gave me a clear idea: http://www.cnblogs.com/huangxincheng/p/4621971.html, You can customize the Messageformatter to achieve the resolution that you want, well nonsense not much to say, directly on the code.

Custom Pointmessageformatter:

    public class Pointmessageformatter:idispatchmessageformatter {private IDispatchMessageFormatter Innerformat        ter Public Pointmessageformatter (IDispatchMessageFormatter innerformatter) {this.innerformatter = InnerForm        Atter;            } 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] = Deserializef Romquerystring (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, OB        Ject result) {return innerformatter.serializereply (messageversion, parameters, result); }   } 

Custom 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)        {        }    }

Then modify the GetPoint service method implementation:

        [Myoperationbehavior]        Public point GetPoint        {            if (point = = null)            {                throw new ArgumentNullException ("point");            }            return point;        }

In fact, the method implementation content has not changed, is to add a feature on its method: Myoperationbehavior, the purpose is: when the request calls the method, will use the pointmessageformatter that I defined above, thus realizes the custom parsing.

Finally we'll experiment with GET request, here I go directly through the browser: http://localhost:14719/Service1.svc/GetPoint?x=12&y=232&value=test, The result of the final return is as follows:

As can be seen, the call succeeded, has been able to parse the normal parameters of my, of course, my above implementation may be rough, there are a lot of restrictions, but I just provide a way of thinking, a solution, you can be based on this idea to achieve a more bull B function. In fact, there is a lot of extensibility in WCF, you can see Artech Daniel's series on WCF, I feel his article is more in-depth, but it is not easy to understand. This article I also spent a lot of energy to think and solve, hope to help everyone, if you feel good, give a recommendation, thank you!

  

To implement a pass-through object (composite type) parameter when a WCF service is invoked under a GET request

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.