The object (composite type) parameter is passed when the WCF Service is called in a GET request. getwcf

Source: Internet
Author: User

The object (composite type) parameter is passed when the WCF Service is called in a GET request. getwcf

It is easy to implement the RESETFUL architecture of WCF. To put it bluntly, it enables WCF to respond to HTTP requests and return the required resources. If someone does not know how to implement WCF to Support HTTP requests, for more information, see implementing jquery in my previous article. ajax and native XMLHttpRequest call methods of the WCF Service, implementation of jquery. ajax and the native XMLHttpRequest Method for cross-origin calling of the WCF Service, which will not be repeated here.

It is easy to implement WCF to Support HTTP request calls, but it takes a little effort to implement the flexibility like mvc action and web api. Why? If the WCF parameter is of the common type (value type), it is easy to call and supports multiple HTTP request methods, such as GET and 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);        }    }

You only need to access http: // localhost: 14719/Service1.svc through a browser./Get/testNote that the deepening part must match the UriTemplate agreed on in the service method. It is similar to the route url of MVC, and POST is also very simple.

If the above call is successful, do you think this is all done? Have you ever wondered if the service method parameter of WCF is an object (composite type), for example:

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

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

Can you perform GET or POST requests as above? If yes, how can I call it? I (dream on the road) is a person who has encountered a problem and must understand and solve the problem. So I tried the experiment and first tried the POST method. The sample code is as follows:

<Html xmlns =" http://www.w3.org/1999/xhtml "> <Head> <title> </title> <script src =" jquery-1.4.4.min.js "type =" text/javascript "> </script> 

The call is successful and the result is shown as follows:

For more information, see DUDU's article: How to pass object parameters when jQuery calls the WCF Service

By the way, when the POST request uses the WCF Service method parameter as the object, note that the Data in the AJAX request must be a JSON string rather than a JSON object. If you do not understand the relationship between the two, here I will briefly describe,

{X: 1, Y: 2, Value: 'test'}, {'X': 1, 'y': 2, 'value ': 'test'} -- these are JSON objects no matter whether the KEY is enclosed in quotation marks. You can use JSON. the stringify method is converted to a JSON string.

"{X: 1, Y: 2, Value: 'test'}", "{'X': 1, 'y': 2, 'value ': 'test'} "-- these are JSON strings. You can use $. convert parseJSON to JSON object

Then try the GET method. It is a little difficult here. How can I make a GET request? How do I match the parameters? I changed the AJAX TYPE to GET, and then called it. The final result is returned as follows:

At first glance, the call fails, and a value cannot be assigned to the service method parameter point of WCF, that is, WCF cannot correctly resolve the request parameter to a POINT object instance, I tried to access it directly in a browser:

Http: // localhost: 14719/Service1.svc/GetPoint? Point = {x = 1 & y = 2 & value = test}. The result is still the same error. This problem has plagued me for a few days. I have also consulted DUDU and QQ groups, bo asked: GET = "*", but GET cannot be used here. Can't I use *? I don't give up. After multi-party verification, this article gives me a clear idea: deny.

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

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

In fact, the method implementation content has not changed, that is, a feature is added to the method: MyOperationBehavior. The purpose is to use the PointMessageFormatter defined above when a request calls this method, thus, custom Parsing is implemented.

Finally, we will try again through the GET request. Here I will directly access: http: // localhost: 14719/Service1.svc/GetPoint? X = 12 & y = 232 & value = test. The returned result is as follows:

It can be seen that the call is successful, and my parameters can be parsed normally. Of course, the implementation above may be rough and there are many restrictions, but here I just provide an idea, A solution. You can use this method to implement the functionality of B. In fact, there are a lot of areas where WCF can be expanded. For more information, see artech's articles on WCF. I feel that his articles are well written, but they are not easy to understand. I also spent a lot of energy on thinking and solving this article. I hope it will help you. If you think it is good, please give me a suggestion. Thank you!

  

Related Article

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.