wcf REST Services и JQuery Ajax Post: метод не разрешен

Кто-нибудь знает, что с этим не так? Я не могу получить ответ json от моей службы отдыха wcf.

Jquery



$.ajax({
  type: 'POST',
  url: "http://localhost:8090/UserService/ValidateUser",
  data: {username: 'newuser', password: 'pwd'},
  contentType: "application/json; charset=utf-8",
  success: function(msg) {
   alert(msg);
  },

  error: function(xhr, ajaxOptions, thrownError) {
   alert('error');
  }

});


Услуга



  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class UserService: IUserService
    {
        private readonly IUserRepository _repository;

        public UserService()
        {
            _repository = new UserRepository();
        }

        public ServiceObject ValidateUser(string username, string password)
        {
           //implementation
        }
    }

    [ServiceContract]
    public interface IUserService
    {
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
        [OperationContract]
        ServiceObject ValidateUser(string username, string password);
    }


веб-конфигурация



 <system.serviceModel>

    <!--Behaviors here.-->
    <behaviors>
      <endpointBehaviors>
        <behavior name="defaultEndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--End of Behaviors-->

    <!--Services here-->   
   <services>
      <service name="MyWcf.Services.UserService">
        <endpoint address="UserService" behaviorConfiguration="defaultEndpointBehavior"
          binding="webHttpBinding" contract="MyWcf.Services.IUserService" />
      </service>
    </services>

    <!--End of Services-->

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name=""
                          helpEnabled="true"
                          automaticFormatSelectionEnabled="true"
                          defaultOutgoingResponseFormat ="Json"
                          crossDomainScriptAccessEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>



person h3n    schedule 09.07.2011    source источник


Ответы (3)


Я вижу несколько проблем в вашем коде:

405 означает, что метод не разрешен - это может означать, что вы отправляете данные не на тот ресурс. Вы уверены, что ваш адрес правильный? Как вы представляете услугу? Это .svc файл или ServiceRoute? Если это .svc файл, адрес будет UserService.svc/UserService/ValidateUser

  • UserService.svc, потому что это точка входа для вашей службы (если вы используете ServiceRoute, вы можете переопределить это
  • UserService, потому что вы определяете этот относительный адрес в конфигурации конечной точки
  • ValidateUser, потому что это точка входа по умолчанию для вашей операции.

Теперь ваш запрос JSON совершенно неверный, как и ваша подпись метода. Подпись метода в вашем сервисном контракте должна ожидать один объект JSON = это должен быть один контракт данных, например:

[DataContract]
public class UserData
{
    [DataMember]
    public string UserName { get; set; }

    [DataMember]
    public string Password { get; set; }
}

и подпись операции будет:

[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
ServiceObject ValidateUser(UserData userData);

В запросе JSON нет элемента-оболочки, поэтому вы должны использовать Bare. Также нет необходимости устанавливать формат ответа, потому что вы установите его на уровне конечной точки (кстати, вы также должны установить формат запроса, если вы этого не сделаете).

После того, как вы определили контракт данных для своего запроса, вы должны правильно определить сам запрос ajax:

$.ajax({
  type: 'POST',
  url: "UserService.svc/UserService/ValidateUser",
  data: '{"UserName":"newuser","Password":"pwd"}',
  contentType: "application/json; charset=utf-8", 
  success: function (msg) {
    alert(msg);
  },

  error: function (xhr, ajaxOptions, thrownError) {
    alert('error');
  }

});

Объект JSON представляет собой строку! а также все его участники!

Для последнего измените свою конфигурацию на:

<system.serviceModel>
  <services>
    <service name="UserService.UserService">
      <endpoint address="UserService" kind="webHttpEndpoint" contract="UserService.IUserService" />
    </service>
  </services>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  <standardEndpoints>
    <webHttpEndpoint>
      <standardEndpoint helpEnabled="true" automaticFormatSelectionEnabled="true" />
    </webHttpEndpoint>
  </standardEndpoints>
</system.serviceModel>

Если вы хотите использовать standardEndpoint, вы должны использовать kind в определении конечной точки, и вам не нужно указывать поведение (это часть стандартной конечной точки). Кроме того, вы не используете междоменные вызовы, поэтому вам не нужно их включать, и вам не нужен формат по умолчанию, поскольку он разрешается автоматически.

person Ladislav Mrnka    schedule 09.07.2011
comment
Я следил за вашей модификацией, и когда я попробовал ее, она говорит: операция «ValidateUser» контракта «IUserService» указывает несколько параметров тела запроса, которые должны быть сериализованы без каких-либо элементов-оболочек. Не более одного параметра body можно сериализовать без элементов-оболочек. Либо удалите дополнительные параметры тела, либо задайте для свойства BodyStyle в WebGetAttribute/WebInvokeAttribute значение Wrapped. - person h3n; 11.07.2011
comment
Итак, вы не следовали моим изменениям, потому что мой ValidateUser не имеет нескольких параметров тела запроса. - person Ladislav Mrnka; 11.07.2011
comment
Я изменил параметр на UserData, и когда я его запустил, метод не разрешен. В Global.asax ставлю ff и работает: HttpContext.Current.Response.AddHeader(Access-Control-Allow-Origin,*); HttpContext.Current.Response.AddHeader (Access-Control-Allow-Methods, GET, POST); HttpContext.Current.Response.AddHeader (Access-Control-Allow-Headers, Content-Type, Accept); HttpContext.Current.Response.End(); - person h3n; 13.07.2011
comment
Есть ли способ опубликовать данные в службе, ничего не делая с Global.asax? - person h3n; 21.07.2011
comment
Да, есть способ, потому что я протестировал именно те изменения, которые я описал на странице .aspx, используя jquery, а также страницу и службу, размещенную на моем локальном IIS, и это работало без каких-либо проблем и без необходимости изменять заголовки. - person Ladislav Mrnka; 21.07.2011

Я считаю, что Иван на правильном пути!

Вы вызываете свой сервис из javascript в браузере, верно?

Находится ли html-страница с этим javascript в том же домене, что и служба wcf?

Если они не находятся в одном домене, я бы сказал, что это проблема межсайтового скриптинга. Я считаю, что GET разрешены кросс-сайты, а POST - нет. http://en.wikipedia.org/wiki/JSONP будет решением, если оно поддерживается на стороне сервера (по WCF)

person Joakim    schedule 09.02.2012
comment
Вы упомянули, что POST не разрешен в междоменном вызове WCF REST JQuery Ajax. Можете ли вы дать мне источник для него? Потому что только из вашего поста я узнал, что POST не поддерживается для междоменного доступа. Я хотел использовать POST из соображений безопасности, но это не работает. - person Firnas; 21.05.2013
comment
Это довольно хорошо объясняется на en.wikipedia.org/wiki/Same_origin_policy, но если вы ищете для ответов вы можете найти ряд предложений здесь, на SO, например stackoverflow.com/questions/298745/ - person Joakim; 22.06.2013

Вы тестировали на одном домене, я полагаю, что автор пытается позвонить с другого домена. Это может быть невозможно из-за междоменных вызовов.

person Ivan    schedule 25.07.2011