JQuery/WCF без ASP.NET AJAX:

Я правильно пытаюсь получить этот "волшебный" момент, когда WCF настроен красиво, и jQuery хорошо структурирует свои запросы/понимает ответы.

У меня есть служба:

<%@ ServiceHost Language="C#" Debug="true" Service="xxx.yyy.WCF.Data.ClientBroker" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"  %>

Это было рекомендовано человеком Rick Strahl, чтобы избежать необходимости определять поведение в Web.config.

Мой интерфейс для службы WCF находится в другой сборке:

namespace xxx.yyy.WCF.Data
{       
    [ServiceContract(Namespace = "yyyWCF")] 
    public interface IClientBroker
    {
        [OperationContract]         
        [WebInvoke(Method="POST",BodyStyle=WebMessageBodyStyle.Wrapped,ResponseFormat=WebMessageFormat.Json)]
        IClient GetClientJson(int clientId);    
    }
}

Конкретный класс сервиса:

namespace xxx.yyy.WCF.Data
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    class ClientBroker : IClientBroker 
    {
        public IClient GetClientJson(int clientId)
        {
            IClient client=new Client();

            // gets and returns an IClient
            return client;
        }
    }
}

My IClient - это класс Entity Framework, поэтому он соответствующим образом украшен атрибутами DataContract/DataMember.

Я пытаюсь вызвать службу WCF, используя методы, описанные в блоге Rick Strahl, в http://www.west-wind.com/weblog/posts/324917.aspx (версия "полный жир" ). Отладчик переходит в режим обслуживания WCF (поэтому мой jQuery/JSON понимается) и получает IClient и возвращает его. Однако, когда я возвращаю ответ, я получаю различные бесполезные ошибки. Ошибки, которые я возвращаю, мало что значит.

Я использую POST.

Можно ли использовать интерфейс вместо конкретного объекта? Поскольку он попадает в службу WCF, он, похоже, является кодировкой результата, который терпит неудачу.

Есть ли у кого-нибудь идеи?

Ответ 1

На первый взгляд есть три проблемы с вашим кодом:

1: вы должны использовать ServiceKnownTypeAttribute, чтобы указать известные типы при экспонировании только базовых типов в ваших контрактах:

[ServiceContract(Namespace = "yyyWCF")]     
public interface IClientBroker
{
    [OperationContract]
    [ServiceKnownType(typeof(Client))]
    [WebInvoke(
        Method="GET",
        BodyStyle=WebMessageBodyStyle.WrappedRequest,
        ResponseFormat=WebMessageFormat.Json)]
    IClient GetClientJson(int clientId);

}

2: вместо WebMessageBodyStyle.Wrapped следует использовать WebMessageBodyStyle.WrappedRequest, потому что последний не совместим с WebScriptServiceHostFactory.

3: IMHO с использованием метода = "GET" будет более RESTful для метода с именем GetClientJson, чем Method = "POST"

Другим советом, который я мог бы дать вам при работе с услугами WCF, является использование SvcTraceViewer.exe в комплекте с Visual Studio. Это отличный инструмент для отладки. Все, что вам нужно, это добавить следующий раздел в ваше приложение /web.config:

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="sdt"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "WcfDetailTrace.e2e" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Затем вызовите веб-метод, и файл WcfDetailTrace.e2e будет создан в корневом каталоге вашего веб-сайта. Затем откройте этот файл с помощью SvcTraceViewer.exe, и вы увидите много полезной информации. Например, он может сказать:

Невозможно сериализовать параметр типа 'MyNamespace.Client' (для работы "GetClientJson", контракт "IClientBroker" ), потому что это не точный тип "MyNamespace.IClient" в подпись метода и не находится в известных типов. Чтобы сериализуйте параметр, добавьте тип к коллекции известных типов для используя ServiceKnownTypeAttribute.

Конечно, вы не должны забывать комментировать этот раздел, прежде чем вступать в производство, или вы можете получить некоторые довольно большие файлы.

Ответ 2

Я на 99% уверен, что вы не можете вернуть интерфейс. Я не думаю, что интерфейсы сериализуемы.

ознакомьтесь с этим thread

Ответ 3

В связи с вопросом, недавно я опубликовал статью в своем блоге, в которой показаны все шаги, необходимые для того, чтобы служба WCF работала вместе с кодом jQuery на стороне клиента:

http://yoavniran.wordpress.com/2009/08/02/creating-a-webservice-proxy-with-jquery/