Consuming WCF from jQuery as JSON

21,004

Solution 1

Your params is object and it forms { "name" : "someValue" } JSON string. If you say that message body style is Bare I think your service expects something like this:

[DataContract]
public class SomeDTO
{
    [DataMember(Name = "name")]
    public string Name { get; set; }
}

And because of that your operation should be defined defined as:

[OperationContract]
[WebInvoke(Method = "POST",
           ResponseFormat = WebMessageFormat.Json,
           RequestFormat = WebMessageFormat.Json,
           BodyStyle = WebMessageBodyStyle.Bare)]        
FooMessageType Foo(SomeDTO data);

If you want your current code to work you should probably change it to:

[OperationContract]
[WebInvoke(Method = "POST",
           ResponseFormat = WebMessageFormat.Json,
           RequestFormat = WebMessageFormat.Json,
           BodyStyle = WebMessageBodyStyle.WrappedRequest)]        
FooMessageType Foo(SomeDTO data);

Solution 2

i got the same issue. after setting BodyStyle=WebMessageBodyStyle.Wrapped it solved.

[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]

Solution 3

Try setting BodyStyle=WebMessageBodyStyle.Wrapped

source

Share:
21,004
Bullines
Author by

Bullines

cod'r #SOreadytohelp

Updated on July 23, 2022

Comments

  • Bullines
    Bullines almost 2 years

    With a contract:

    namespace ACME.FooServices
    {
        [ServiceContract]
        public interface IFooService
        {
            [OperationContract]
            [WebInvoke(Method = "POST",
                       ResponseFormat = WebMessageFormat.Json,
                       RequestFormat = WebMessageFormat.Json,
                       BodyStyle = WebMessageBodyStyle.Bare)]        
            FooMessageType Foo(string name);
        }
    
        [DataContract]
        public class FooMessageType
        {
            string _name;
            string _date;
    
            [DataMember]
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
            [DataMember]
            public string Date
            {
                get { return _date; }
                set { _date = value; }
            }
        }
    }
    

    And implementation:

    using System;
    using System.ServiceModel.Activation;
    
    namespace ACME.FooServices
    {
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
        public class FooService : IFooService
        {
            public FooMessageType Foo(string name)
            {
                string l_name = (String.IsNullOrWhiteSpace(name)) ? "Anonymous" : name;
    
                return new FooMessageType {Name = l_name, Date = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt")};
            }
        }
    }
    

    Configured in the web.config as:

    <system.serviceModel>
        <services>
            <service name="ACME.FooServices.FooService">
                <endpoint address="" behaviorConfiguration="ACME.FooBehaviour" binding="webHttpBinding" contract="ACME.FooServices.IFooService" />
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="ACME.FooBehaviour">
                    <webHttp />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    

    I'm trying to call Foo from a page via jQuery:

    <script type="text/javascript" language="javascript">
        $(document).ready(function () {
            $("#msgButton").click(function () {
                var params = {};
                params.name = $("#nameTextbox").val();
    
                $.ajax({
                    type: 'POST',
                    url: "http://acme.com/wcfsvc/FooService.svc/Foo",
                    data: JSON.stringify(params),
                    contentType: 'application/json; charset=utf-8',
                    success: function (response, status, xhr) { alert('success: ' + response); },
                    error: function (xhr, status, error) { alert("Error\n-----\n" + xhr.status + '\n' + xhr.responseText); },
                    complete: function (jqXHR, status) { alert('Status: ' + status + '\njqXHR: ' + JSON.stringify(jqXHR)); }
                });
            });
        });        
    </script>
    

    But I'm getting a 400 - Bad Request error with the message "The server encountered an error processing the request. The exception message is 'There was an error deserializing the object of type System.String. End element 'root' from namespace '' expected. Found element 'name' from namespace".

    Am I missing something?

  • Bullines
    Bullines almost 13 years
    I gather Bare and a DTO would be a best practice?
  • Kuttan Sujith
    Kuttan Sujith almost 9 years
    What Ladislav Mrnka suggested is a work around.But BodyStyle=WebMessageBodyStyle.Wrapped is a right fix