У меня была служба WCF, использующая CORS, размещенную на консольном приложении, которое отлично работало в.Net 4.5. теперь приложение должно работать в.Net 3.5, а запрос предварительной предварочной проверки теперь не выполняется для любого запроса POST
Вот интерфейс для служб:
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
BiometricCaptureResponse Start(BiometricCaptureRequest biometricRequest);
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void Options();
Фактическое обслуживание:
public BiometricCaptureResponse Start(BiometricCaptureRequest biometricRequest)
{
//Stuff and things
}
public void Options()
{
return;
}
Поведение для CORS, которое применяется к запросам и ответам
public string clientOrigin;
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
HttpRequestMessageProperty requestProperty = request.Properties[HttpRequestMessageProperty.Name]
as HttpRequestMessageProperty;
if (requestProperty != null && requestProperty.Headers.AllKeys.Contains("Origin") && !string.IsNullOrEmpty(requestProperty.Headers["Origin"]))
{
clientOrigin = requestProperty.Headers["Origin"];
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
HttpResponseMessageProperty httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
if (httpHeader != null)
{
httpHeader.ApplyCrossOriginSupport(clientOrigin);
}
}
public static void ApplyCrossOriginSupport(this HttpResponseMessageProperty message, string origin)
{
message.Headers.Add("Access-Control-Allow-Origin", origin);
message.Headers.Add("Access-Control-Allow-Method", ConfigurationManager.AppSettings["Access-Control-Allow-Method"]);
message.Headers.Add("Access-Control-Allow-Headers", ConfigurationManager.AppSettings["Access-Control-Allow-Headers"]);
}
это все работает в 4.5, это процесс, который произошел бы:
Теперь в 3.5 служба Ooptions не пострадает, что приведет к сбою всего запроса. Есть ли что-то, что мне не хватает, чтобы получить эту работу за 3.5?
Ошибка, которую я получаю с консоли Chrome:
OPTIONS http://localhost:8502/testservice.svc/rest/Start net::ERR_CONNECTION_RESET
может ли это иметь какое-либо отношение к атрибуту WebInvoke? Эта страница MSDN описывает это как 4.5/3.5 Client tech, в то время как я использую только.Net 3.5.
UPDATE: изменение следующего атрибута службы параметров для использования всех методов
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
[WebInvoke(Method = "*", UriTemplate = "*")]
разрешил запросы на выбор, чтобы попасть в службу, приложение может работать так функционально, но это все еще не оптимальное решение, поскольку оно не является специфическим для запроса OPTIONS, по какой-либо причине?
Я боюсь, что в версии.Net 3.5 WebHttpDispatchOperationSelector есть небольшая ошибка.
Опция Method в комбинации с * UriTemplate не распознается селектором.
В качестве обходного пути вы можете заменить стандартное WebHttpBehavior на пользовательскую версию.
public class CorsWebHttpDispatchOperationSelector : WebHttpDispatchOperationSelector
{
private WebHttpDispatchOperationSelector target;
private ServiceEndpoint endpoint;
OperationDescription optionOperation;
public CorsWebHttpDispatchOperationSelector(ServiceEndpoint endpoint, WebHttpDispatchOperationSelector target)
{
this.target = target;
this.endpoint = endpoint;
foreach (var item in this.endpoint.Contract.Operations) {
var webInvoke = item.Behaviors.OfType<WebInvokeAttribute>().FirstOrDefault();
if (webInvoke != null && webInvoke.Method.Equals("options",StringComparison.OrdinalIgnoreCase) && webInvoke.UriTemplate == "*") {
optionOperation = item;
break;
}
}
}
#region IDispatchOperationSelector Members
protected override string SelectOperation(ref Message message, out bool uriMatched)
{
var result = target.SelectOperation(ref message);
var matched = message.Properties["UriMatched"] as bool?;
message.Properties.Remove("UriMatched");
message.Properties.Remove("HttpOperationName");
uriMatched = matched.HasValue && matched.Value;
var httpRequest = message.Properties["httpRequest"] as HttpRequestMessageProperty;
var cond = string.IsNullOrEmpty(result) &&
httpRequest != null &&
httpRequest.Method.Equals("options",StringComparison.OrdinalIgnoreCase);
if (cond && optionOperation != null) {
result = optionOperation.Name;
uriMatched = true;
}
return result;
}
#endregion
}
public class CorsWebHttpBehavior : WebHttpBehavior {
protected override WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
{
return new CorsWebHttpDispatchOperationSelector(endpoint, base.GetOperationSelector(endpoint));
}
}