2

我在我的 ASP.NET 网站上创建了一个 WCF 服务。但是当我在托管服务器上运行网站时(例如在真实域 somedomain.com 上),WCF 服务无法运行或被来自 javascript 的任何请求调用。它只能在我的本地主机上运行。

这是我的 web.config 文件中的配置;它在配置标签中只有一些 xml 行:

<configuration>
<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <behaviors>
      <endpointBehaviors>
        <behavior name="ServiceAspNetAjaxBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="Service">
        <endpoint address="" behaviorConfiguration="ServiceAspNetAjaxBehavior"
          binding="webHttpBinding" contract="Service" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

web.config 中的信息由 Visual Studio 2008 在创建 WCF 服务时生成。服务行为名为“ServiceAspNetAjaxBehavior”,并且在端点标记中也定义了它。它使用 webHttpBiding 供客户端调用 Web 服务。

Service.svc 文件只有一行:

<%@ ServiceHost Language="C#" Debug="true" Service="Service" CodeBehind="~/App_Code/Service.cs" %>

我网站根目录的 App_Code 文件夹中的 Service.cs 文件。Service.cs 的内容如下。由于Service.cs的行数太多,所以我只贴一些代码示例,让大家看看Service.cs文件的基本构造函数。

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Web;
using System.Configuration;
using System.Data.SqlClient;
using System.Collections;
using DotNetNuke.Entities.Users;

[ServiceContract(Namespace = "IELTSpedia")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
    public Class1 class1 = new Class1();
    public static string defaultPortalAlias = Class1.GetDefaultPortalAlias1();
    public static string testViewPage = "";
    /// <summary>
    /// Reads the available products to provide data for the Kendo Grid
    /// </summary>
    /// <returns>All available products</returns>
    [OperationContract]
    [WebInvoke(ResponseFormat = WebMessageFormat.Json,
                  RequestFormat = WebMessageFormat.Json)]
    public DataSourceResult Read(int skip, int take, IEnumerable<Sort> sort, Filter filter)
    {
        take = skip + take;
        skip = skip + 1;
        return new DataSourceResult();
    }
}

Service.cs 文件有一个“Read”方法,当使用 javascript 调用时,该方法将返回一个对象以填充客户端网页上的网格视图。我用来调用服务的javascript函数如下:

read: {
    url: "http://localhost:8698/dotnetnuke_community_06.02.01_install/Service.svc/Read", //specify the URL which data should return the records. This is the Read method of the Products.svc service.
    contentType: "application/json; charset=utf-8", // tells the web service to serialize JSON
    type: "POST" //use HTTP POST request as the default GET is not allowed for svc
},
parameterMap: function(data, operation) {
    if (operation != "read") {
        // web service method parameters need to be send as JSON. The Create, Update and Destroy methods have a "products" parameter.
        return JSON.stringify({ service: data.models })
    } else {
        return JSON.stringify(data);
    }
}

在javascript中;我已经通过我的 Web 服务的 localhost url 调用了该服务。当我在 localhost 上运行我的网站时,此 url 有效。当我将我的网站上传到托管服务器时,我已将 url 更改为http://somedomain.com/Service.svc/Read 问题是 WCF 服务只能在我的本地主机上调用,而不能在托管上调用服务器。在本地主机上运行网站时,我已经测试了该服务;它成功并且对象正常返回但不在托管服务器上。

最后,我的问题是如何在 web.config 文件中的托管服务器上配置 WCF 服务。

我希望我的示例代码可以让您清楚地了解我的问题。我处于问题的边缘,需要 stackoverflow 社区的帮助。请帮助我。

4

3 回答 3

3

为了从 javascript 访问 WCF 服务,它应该是 RESTful 服务。因此尝试使 WCF 成为 RESTful 服务。可以参考 http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide

于 2013-04-24T10:16:52.907 回答
1
于 2013-04-24T13:41:58.110 回答
0

This is just an add-on to @tri-nguyen-dung's last comment, which I used to get my service working in a virtual directory on a hosted server (arvixe).

Here's my version of his Web.config section, that is sitting inside \wwwroot\<virtualdirectory>\Web.config:

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="<virtualdirectory>Behaviour" >
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceMetadata httpGetEnabled="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="<virtualdirectory>Behaviour">
                <enableWebScript />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false" minFreeMemoryPercentageToActivateService="0">
        <baseAddressPrefixFilters>
            <add prefix="http://<yourserver>.com"/>
        </baseAddressPrefixFilters>             
    </serviceHostingEnvironment>
    <services>
        <service name="<virtualdirectory>.Services.<virtualdirectory>Service" behaviorConfiguration="<virtualdirectory>Behaviour">
            <host>
                <baseAddresses>
                    <add baseAddress="http://<yourserver>.com"/>
                </baseAddresses>
            </host>
            <endpoint address="http://<yourserver>.com/<virtualdirectory>/Services/<virtualdirectory>Service.svc"
                    behaviorConfiguration="EDGEBehaviour"
                    binding="webHttpBinding"
                    contract="virtualdirectory.Services.I<virtualdirectory>Service" />
        </service>
    </services>
</system.serviceModel>

With <yourserver> and <virtualdirectory> being your app address; to get your e.g. service help page my address was http://<yourserver>.com/<virtualdirectory>/Services/<virtualdirectory>Service.svc/help. You don't have to use my naming convention for your app code, but it worked for me.

Here's my I<virtualdirectory>Service.cs code:

namespace <virtualdirectory>.Services
{
    [ServiceContract]
    public interface I<virtualdirectory>Service
    {
        [OperationContract]
        object GetFormResult(string form_id);

Here's the implementation (<virtualdirectory>Service.svc.cs):

namespace <virtualdirectory>.Services
{
    using <lots>;

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class <virtualdirectory>Service : I<virtualdirectory>Service 
    {
        [WebGet(UriTemplate = "GetFormResult?form_id={form_id}", ResponseFormat = WebMessageFormat.Json)]
        public object GetFormResult(string form_id)
        {

Implementation markup (<virtualdirectory>Service.svc):

<%@ ServiceHost Language="C#" Debug="true" Service="<virtualdirectory>.Services.<virtualdirectory>Service" Factory="<virtualdirectory>.WebServiceHostFactory3WithJsonP" CodeBehind="<virtualdirectory>Service.svc.cs" %>

Note that I got WebServiceHostFactory3WithJsonP from google somewhere, to serve REST+JSON over WCF. The newer WebAPI stuff in .NET 4.5 is better, but my site is in .NET4.

For completeness, here's my javascript that is calling this:

jQuery(document).ready(function ($) {
    jQuery('#formdetails').submit(function () {
    jQuery('.widget_formdetails input[type="submit"]').hide();
    jQuery('.formloading').show();
    var form_parameters = jQuery(this).serialize();
    var form_type = jQuery('#form_type').val();
    switch (form_type) {
        case '<someoption>':
        var js<someoption> = new f<someoption>(  // object helper function
                    jQuery('#textfield1').val(), 
                    jQuery('#textfield2').val(), 
                    jQuery('#textfield3').val()
                    );
        var json<someoption> = JSON.stringify({ Message: js<someoption>});
        $.getJSON(
            '/<virtualdirectory>/Services/<<virtualdirectory>Service.svc/GetFormResult',
            'form_request=' + json<someoption>,
            form_request // callback function
        );
        break;
于 2013-10-01T11:16:00.323 回答