Преобразование службы отдыха WCF CORS из .Net 4.5 в 3.5 приводит к сбою предварительного запроса

1

У меня была служба 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, это процесс, который произошел бы:

  1. AfterReceiveRequest()
  2. Удар по параметрам()
  3. BeforeSendReply()
  4. AfterReceiveRequest()
  5. Начало()
  6. BeforeSendReply()

Теперь в 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, по какой-либо причине?

  • 0
    Какую ошибку вы получаете в 3.5?
  • 0
    @peer Добавил ошибку в конец вопроса.
Теги:
rest
wcf

1 ответ

2
Лучший ответ

Я боюсь, что в версии.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));
    }
}
  • 0
    Спасибо, это намного приятнее, чем использовать *, чтобы поймать все, откуда вы знаете, что это ошибка в .Net 3.5?
  • 0
    @RichardMc это может быть ошибка или просто не поддерживается. Код WebHttpDispatchOperationSelector немного отличается от .net 3.5 до .net 4.0. Когда вы поставите точку останова на моем переопределении метода SelectOperation, вы увидите, что target.SelectOperation (ref message) дает вам действительный результат, когда построено в 4.5, конец пуст, когда построен в 3.5

Ещё вопросы

Сообщество Overcoder
Наверх
Меню