WCF JSONP возвращает пустой / пустой документ при возврате NULL

#.net #wcf #null #jsonp

#.net #wcf #нулевой #jsonp

Вопрос:

Я использую образцы JSONP, предоставленные Microsoft. http://msdn.microsoft.com/en-us/library/cc716898 (v= против 90).aspx

JSONPEncoderFactory JSONPBindingExtension JSONPBindingElement JSONPBehavior

Все работает нормально, за исключением случаев, когда возвращается значение null. Вместо того, что я хочу, а именно: обратный вызов (null); Он возвращает пустой документ, который вызывает ошибку в большинстве фреймворков JSONP, таких как

 jQuery.ajax({jsonp:"callback"}); 
 

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

 public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
 

Самое близкое, к чему я подошел к поиску решения, — это просто предположение. Я подумал, что, возможно, у класса WebServiceHost может быть метод, который я могу переопределить для создания ожидаемой функциональности, но пока я пришел с пустыми руками.

Я хотел также упомянуть, что я не использую класс WebScriptServiceHostFactory из-за следующей проблемы:

 Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.
 

Если я использую эту фабрику, возврат null вызывает функциональность, которую я ищу. Однако тогда я не могу использовать TemplateUri, и я использую их для шифрования HMAC. Поскольку я не могу использовать заголовки в JSONP, запросы форматируются как

 /Service/Action/publicKey-signature?params
 

Я попытался найти стандарт для HMAC по запросу типа JSONP, но ничего не смог найти. Это было самое чистое, что я мог придумать. В качестве подписи используется параметр Params.

Обновить:

Вещи, которые мне не хватало при попытке использования приведенного ниже решения, заключались в том, что вы должны убедиться, что в вашем web.config вы создаете webHttpBinding, который имеет crossDomainScriptAccessEnabled=»true». Кроме того, вы должны убедиться, что не используете это поведение. Также не используйте WebScriptServiceHostFactory. Вы можете использовать WebServiceHostFactory, но тогда вы должны иметь это в web.config (или сделать это для одной службы через привязку):

 <system.serviceModel>
    <standardEndpoints>
        <webHttpEndpoint>
            <standardEndpoint crossDomainScriptAccessEnabled="true" />
        </webHttpEndpoint>
    </standardEndpoints>
</system.serviceModel>
 

Комментарии:

1. Используете ли вы .NET Framework 3.5 или 4.0? В версии 4.0 поддержка JSONP встроена в классы, поэтому вам не нужно иметь кодировщик, как показано в примере.

2. Я использую 4.0. Я объясняю, что происходит, когда вы пытаетесь использовать JSONP со встроенными классами. Вы не можете использовать TemplateUri. Если у вас нет способа разрешить это?

Ответ №1:

Платформа 4.0 имеет встроенную поддержку JSONP и поддерживает шаблоны URI, как показано в примере ниже. Вам нужно будет включить поддержку в WebHttpBinding классе (или в конфигурации, если вы предпочитаете).

 public class StackOverflow_7974435
{
    [ServiceContract]
    public class Service
    {
        [WebGet(UriTemplate = "/Sum?x={x}amp;y={y}")]
        public int Add(int x, int y)
        {
            return x   y;
        }
        [WebGet(UriTemplate = "/Data?isNull={isNull}")]
        public string GetData(bool isNull)
        {
            return isNull ? null : "Hello world";
        }
    }
    public static void Test()
    {
        string baseAddress = "http://"   Environment.MachineName   ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        WebHttpBinding binding = new WebHttpBinding { CrossDomainScriptAccessEnabled = true };
        WebHttpBehavior behavior = new WebHttpBehavior { DefaultOutgoingResponseFormat = WebMessageFormat.Json };
        host.AddServiceEndpoint(typeof(Service), binding, "").Behaviors.Add(behavior);
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        Console.WriteLine("Not a JSONP call");
        Console.WriteLine(c.DownloadString(baseAddress   "/Sum?x=6amp;y=8"));

        Console.WriteLine("A JSONP call");
        Console.WriteLine(c.DownloadString(baseAddress   "/Sum?x=6amp;y=8amp;callback=MyFunction"));

        Console.WriteLine("A JSONP call returning string");
        Console.WriteLine(c.DownloadString(baseAddress   "/Data?isNull=falseamp;callback=MyFunction"));

        Console.WriteLine("A JSONP call returning null");
        Console.WriteLine(c.DownloadString(baseAddress   "/Data?isNull=trueamp;callback=MyFunction"));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
 

Обновление: добавлена также другая операция, которая возвращает null, и вызовы к ней. В первом вызове (возвращающая строка) служба возвращает MyFunction("Hello world"); , а во втором случае она возвращает корректно MyFunction(null); . Как я упоминал в комментариях, если вы не используете ASP.NET Фреймворк AJAX, не используйте WebScriptEnablingBehavior , так как он не предназначен для использования в других фреймворках.

Комментарии:

1. Используете ли вы фабрику в службе?

2. Я все еще получаю ту же ошибку: конечные точки, использующие ‘UriTemplate’, не могут использоваться с ‘System. ServiceModel. Описание. WebScriptEnablingBehavior».

3. Если я сниму фабрику, я просто получу 400 плохих запросов

4. Даже образец из: msdn.microsoft.com/en-us/library/ee834511.aspx Ошибки при попытке использовать UriTemplate.

5. blogs.msdn.com/b/justinjsmith/archive/2008/02/15 /… «Затем, вместо использования поведения enableWebScript, используйте WebHttpBehavior. Вы потеряете связь с ASP.NET Клиентский стек AJAX (и прокси-сервер JS), но у вас есть URI, который вы ищете «.