【问题标题】:Need some clarification on JSONP with JQuery/WCF需要对带有 JQuery/WCF 的 JSONP 进行一些说明
【发布时间】:2011-08-02 07:14:27
【问题描述】:

目标:公开一个简单的 WCF 服务,该服务将作为用户名的字符串作为参数,并查看它是否已经存在。该服务将在我正在开发的网站的注册页面上使用,因此当用户输入用户名时,它会自动检查是否被使用。

我实际上已经让这个功能工作了,但是我必须为 WCF 服务启用 crossDomainScripting。我的问题是“为什么?”

到代码!

我的 WCF 服务托管在我的 MVC3 站点中(我最初将它放在一个单独的站点中,但为了消除对跨站点脚本的所有顾虑,我将其移至本地。)

WCF 服务接口

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

实施:

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

网页配置

<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 实现调用:

$(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 username is already taken!');
                availabilityMessage.addClass('usernameTaken');
                availabilityMessage.removeClass('usernameAvailable');
            }
        });

    }
});

});

现在这一切都很好。我可以在注册表单的文本框中输入用户名,当我离开该字段时,onBlur 事件会触发并调用 WCF 服务并按预期返回结果...但 只有 如果我有 crossDomainScriptAccessEnabled="true “在我的 web.config 中。这让我很困惑。也许是对 JSON 和 JSONP 缺乏了解(完全有可能。我对使用 JSON 还很陌生),但是由于服务托管在同一个域中,为什么我需要这个集合?

我查看了 Fiddler 发送的内容:

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

还有我在 JQuery 文档中看到的回调参数。

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

如果 URL 包含字符串“callback=?” (或类似的,由服务器端 API 定义),请求被视为 JSONP。有关详细信息,请参阅 $.ajax() 中对 jsonp 数据类型的讨论。

这是否意味着有一个成功回调的简单行为将迫使 GetJSON 使用 JSONP?

任何意见表示赞赏。

【问题讨论】:

    标签: jquery wcf json jsonp


    【解决方案1】:

    这是否意味着简单的行为 有一个成功回调将 强制 GetJSON 使用 JSONP?

    简单的答案是肯定的。

    如果您添加参数或将类型设置为 jsonp,jQuery 将自动为您完成所有繁重的工作。您还需要您的服务足够聪明,以便在将数据发送给您之前将数据包装在函数调用中——但如果给定参数,.net 会这样做。

    在 SO 上还有很多其他的答案是关于如何通过 jQuery 使用 jsonp。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 2016-06-16
      • 2014-10-02
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 2013-07-17
      相关资源
      最近更新 更多