开发者

Need some clarification on JSONP with JQuery/WCF

Goal: Expose a simple WCF service that would take as a parameter a string that was a username and see if it already existed. This service would be used on the registration page of the site I'm working on so when a user typed a username it would automatically check to see if it was taken.

I've actually gotten this functionality to work, but I had to enable crossDomainScripting for the WCF service. My question is "why?"

To the code!

My WCF service is hosted within my MVC3 site (I originally had it in a separate site but to remove any and all concern about cross site scriptiong I moved it local.)

Interface for WCF Service

    [ServiceContract]
public interface IMembershipServices
{
    [OperationContract]
    [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "IsUsernameAvailable/{username}",
        BodyStyle = WebMessageBodyStyle.Bare)]
    MembershipUserAvailability IsUsernameAvailable(string username);

    [OperationContract]
    [WebGet(UriTemplate = "helloto/{name}", ResponseFormat = WebMessageFormat.Json)]
    string Hello(string name);
}

Implementation:

    [AspNetCompatibilityRequirements(RequirementsMode
    = AspNetCompatibilityRequirementsMode.Allowed)]
public class MembershipServices : IMembershipServices
{
    #region IMembershipServices Members

    public string Hello(string name)
    {
        return String.Format("Hello:{0}", name);
    }


    public MembershipUserAvailability IsUsernameAvailable(string username)
    {
        if (String.IsNullOrWhiteSpace(username))
        {
            throw new ArgumentException(username);
        }

        MembershipUser membershipUser = Membership.GetUser(username, false);

        var membershipUserAvailability = new MembershipUserAvailability
                                             {
                                                 UserName = username,
                                                 IsAvailable = membershipUser == null ? true : false
                                             };

        return membershipUserAvailability;
    }

    #endregion
}

Web.config

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
        <!-- This section is optional with the default configuration
    model introduced in .NET Framework 4 -->
        <service name="MedicalPracticeWeb.Services.MembershipServices" behaviorConfiguration="MembershipServicesBehaviors">

            <!-- This endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc  -->
            <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBindingJsonP" contract="MedicalPracticeWeb.Services.IMembershipServices" behaviorConfiguration="EndpBehavior" />

            <!-- The mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex -->
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MembershipServicesBehaviors">
                <!-- Add the following element to your service behavior configuration. -->
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="EndpBehavior">
                <webHttp />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <webHttpBinding>
            <binding name="webHttpBindingJsonP" crossDomainScriptAccessEnabled="true"></binding>
        </webHttpBinding>
    </bindings>
</system.serviceModel>

Jquery to imlement call:

$(document).ready(function () {

var usernameTextbox = $('#username');
var usernameUnavailableRow = $('#usernameUnavailableRow');
var availabilityMessage = $('#availabilityMessage');

usernameTextbox.blur(function () {
    if ($(this).val()) {

        $.getJSON('/Services/MembershipServiceHost.svc/IsUsernameAvailable/' + escape($(this).val()), function (results) {
            if (results.IsAvailable) {
                if (usernameUnavailableRow.is(':visible')) {
                    availabilityMessage.html('This username is available.');
                    availabilityMessage.addClass('usernameAvailable');
                    availabilityMessage.removeClass('usernameTaken');
                }
            }
            else {
                usernameUnavailableRow.show();
                availabilityMessage.html('This u开发者_开发知识库sername is already taken!');
                availabilityMessage.addClass('usernameTaken');
                availabilityMessage.removeClass('usernameAvailable');
            }
        });

    }
});

});

Now this all works great. I can type a username into the textbox on my registration form and when I leave the field the onBlur event fires and calls the WCF service returning results as expected...but only if I have crossDomainScriptAccessEnabled="true" in my web.config. This puzzles me. Perhaps it's a lack of understanding of JSON and JSONP (entirely possible. I'm fairly new to working with JSON) but since the service is hosted in the same domain why would I need this set?

I took a look at what Fiddler was sending:

GET /Services/MembershipServiceHost.svc/IsUsernameAvailable/Tim?callback=jQuery1510988704698288691_1302393437642&_=1302393485350 HTTP/1.1

And there's the callback parameter that I see mentioned in the JQuery docs.

http://api.jquery.com/jQuery.getJSON/

If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.

Does this mean the simple act of having an on success callback will force GetJSON to utilize JSONP?

Any input appreciated.


Does this mean the simple act of having an on success callback will force GetJSON to utilize JSONP?

The simple answer is yes.

If you add in the parameter or set the type to jsonp, jQuery will auto-magically do all the hard work for you. You also need your service to be smart enough to wrap the data in a function call before it sends it to you -- but .net does this if given the parameter.

There are a number of other answers on SO that talk about how to use jsonp via jQuery.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜