#.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, который вы ищете «.