Вопрос

Добрый день, коллеги! 

Есть задача: сделать веб-сервис, принимающий на вход сложное json-тело.

В ходе реализации столкнулась с двумя проблемами:

1. Не нашла, как описать прием сложного параметра в сервисе, кроме робкого указания на модификаторы [DataContract] и [DataMember]. Подскажите, где-нибудь есть информация об этом? 

2. При вызове из Postman сервис возвращает ответ "403 - Вы не имеете разрешения на просмотр этого каталога пли страницы." (скриншот ниже). Нужно ли где-то отдельно прописывать права на доступ к сервисам?

 

Скриншот ошибки:

Листинг пример json тела запроса.

{
"scoring_events" : [
		{
			"type" : "pageview",
			"page_url" : "https://bpmonline.com/",
			"datetime_utc" : "2018-08-08 12:00:12",
			"responsible_user" : {
				"name" : "Иван Иванов",
				"email" : "i.ivanov@yandex.ru",
				"type" : "user"
			},
			"partner" : {
				"name" : "ООО Ромашка"
				"bpm_id" : "783967ef-c629-4f1d-8cd4-3b3dba955ffc",
				"contact_email" : "n.ivanova@yandex.ru"
			}
		},
		...
		{
			...
		}
	]
}

 

листинг сервиса:

namespace Terrasoft.Configuration.WScoringService
{
	using System;
<...>
#region Class: WScoringService 
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class WScoringService : BaseService
	{
        private WScoringServiceResponse wScoringServiceResponse;

        #region Methods: Public
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
        ResponseFormat = WebMessageFormat.Json)]
        public string AddScoringEvent(List<ScoringEvent> scoring_events)
        {
            if (scoring_events.IsEmpty()) wScoringServiceResponse = new WScoringServiceResponse(true, "empty");
            else wScoringServiceResponse = new WScoringServiceResponse(true, scoring_events[0].ToString());
            return wScoringServiceResponse.ToJsonString();
        }
        #endregion
        #region  DataContract
	    [DataContract]
	    public class ScoringEvent
	    {
	    	[DataMember]
	        public string type;
	        [DataMember]
	        public string page_url;
	        [DataMember]
	        public string datetime_utc;
	        [DataMember]
	        public ResponsibleUser responsible_user;
	        [DataMember]
	        public Partner partner;
	        public override string ToString()
	        {
	            string result;
	            result = "type=" + type + ";";
	            result += "page_url=" + page_url + ";";
	            result += "datetime_utc=" + datetime_utc + ";";
	            result += "responsible_user_name=" + responsible_user.name + ";";
	            result += "partner_name=" + partner.name + ";\n";
	            return result;
	        }
	    }
	    [DataContract]
	    public struct ResponsibleUser
	    {
	    	[DataMember]
	        public string name;
	        [DataMember]
	        public string email;
	        [DataMember]
	        public string type;
	    }
	    [DataContract]
	    public struct Partner
	    {
	    	[DataMember]
	        public string name;
	        [DataMember]
	        public string bpm_id;
	        [DataMember]
	        public string contact_email;
	    }
	    #endregion
    }
    #endregion

    #region Class: WScoringServiceResponse
    public class WScoringServiceResponse
    {
        private bool success;
        private string message;
        public WScoringServiceResponse() { }
        public WScoringServiceResponse(bool success, string message = null)
        {
            this.success = success;
            this.message = message;
        }
        public string ToJsonString()
        {
            string result = "{\"status\":\"";
            if (success) result += "ok\",";
            else result += "error\",";
            result += "\"message\":\"" + message+ "\"}";
            return result;
        }
    }
    #endregion
}

 

У меня такой же вопрос

1 комментарий

Примеры сервисов можно найти в конфигурации. Например, [DataContract] и [DataMember] применяют в CurrentUserService так:

[DataContract]
public class UserCultureInfo
{
	[DataMember(Name = "timeZoneCode")]
	public string TimeZoneCode { get; set; }
 
	[DataMember(Name = "timeZoneName")]
	public string TimeZoneName { get; set; }
 
	[DataMember(Name = "timeZoneId")]
	public Guid TimeZoneId { get; set; }
 
	[DataMember(Name = "cultureId")]
	public Guid CultureId { get; set; }
 
	[DataMember(Name = "cultureName")]
	public string CultureName { get; set; }
 
	[DataMember(Name = "cultureLanguage")]
	public string CultureLanguage { get; set; }
 
	[DataMember(Name = "dateTimeFormatId")]
	public Guid DateTimeFormatId { get; set; }
 
	[DataMember(Name = "dateTimeFormatName")]
	public string DateTimeFormatName { get; set; }
}

По поводу 403, такое бывает, если при отправке запроса к сервису не передать CSRF-токен.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Подскажите, как корректно добавить блок behaviorExtensions в конфиг системы.

Добавил блок 

<behavior>

<log4net />

</behavior>

И в блоке RestServiceBehavior добавил log4net

<behavior name="RestServiceBehavior">
            <errorHandler/>
            <matchAllMessage/>

            <log4net />
            <threadContextInitializer/>
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true"  />
        </behavior>

в файл behaviours.config

В Web.config в Terrasoft.WebApp.

<extensions>

<behaviorExtensions>

<add name="log4net"

type="Integration.Log4NetBehaviorExtensionElement, Integration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

</behaviorExtensions>

</extensions>

Класс Log4NetBehaviorExtensionElement также определил в Integration.

После чего возникают ошибки при попытке залогиниться в систему с сервисом. Подскажите как корректно настроить конфиги.

У меня такой же вопрос

5 комментариев

Добрый день.

<behaviorExtensions> нужно прописывать в Extensions.config (там же написаны некоторые рекомендации). Ваш класс должен наследоваться от абстрактного класса «BehaviorExtensionElement» (namespace System.ServiceModel.Configuration). Проверьте ваш класс на доступность в БП или сервисе пред его записью в behaviorExtensions.

VladKapitanchyk,

 

Влад, добрый день!
Подскажите, пожалуйста, что значит:
<!-- Значения атрибутов type изменяются при автосборке. При добавлении/удалении/изменении содержимого оповестить ответственного за автосборку! -->
Каким образом необходимо уведомить ответственного за автосборку?

Тетиков Дмитрий Владимирович,

Добрый день.

На этот комментарий можете не обращать внимание, это относится к старой логике. Посмотрите на версию вашего extension, там указывается версия сборки, возьмите такую же, как и в предыдущих extensions.

VladKapitanchyk, 

Влад, сделал согласно рекомендациям. Первоначально была ошибка 
Exception Message: Не удалось загрузить тип "ArdsinBankCode.Integration.Log4NetBehaviorExtensionElement, ArdsinBankCode.Integration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", зарегистрированный для расширения "log4net". (D:\TSroot\ArdshinBank7102-2\Terrasoft.WebApp\ServiceModel\http\behaviors.config line 29)
Exception Type: System.Configuration.ConfigurationErrorsException
Exception Source: System.Configuration в логах Application.

После правки версии ошибки не возникает, однако ошибка вызова сервиса при авторизации осталась. 

Класс при вызове из БП доступен.
Подскажите, какие еще могут быть нюансы, пожалуйста.

<extensions>
  <behaviorExtensions>
    <!-- Делать разрывы строк внутри атрибута type запрещено! -->
    <!-- Значения атрибутов type изменяются при автосборке. При добавлении/удалении/изменении содержимого оповестить ответственного за автосборку! -->
    <add name="errorHandler" type="Terrasoft.Web.Common.ServiceModel.ErrorHandlerElement, Terrasoft.Web.Common, Version=7.10.2.1416, Culture=neutral, PublicKeyToken=edaadfbc3b0bb879" />
    <add name="matchAllMessage" type="Terrasoft.Web.Common.ServiceModel.MatchAllMessageElement, Terrasoft.Web.Common, Version=7.10.2.1416, Culture=neutral, PublicKeyToken=edaadfbc3b0bb879" />
    <add name="threadContextInitializer" type="Terrasoft.Web.Common.ServiceModel.ThreadContextInitializerElement, Terrasoft.Web.Common, Version=7.10.2.1416, Culture=neutral, PublicKeyToken=edaadfbc3b0bb879" />
	<add name="log4net" type="ArdsinBankCode.Integration.Log4NetBehaviorExtensionElement, ArdsinBankCode.Integration, Version=7.10.2.1416, Culture=neutral, PublicKeyToken=edaadfbc3b0bb879" />
  </behaviorExtensions>
</extensions>
 
<behavior name="RestServiceBehavior">
			<errorHandler/>
			<matchAllMessage/>
			<log4net/>
			<threadContextInitializer/>
			<serviceMetadata httpGetEnabled="true" />
			<serviceDebug includeExceptionDetailInFaults="true"  />
		</behavior>

 

Попробуйте выполнить следующее:

1) Проверить логи windows на сервере, там должна быть более детальная информация об ошибке (это будет либо error, либо warning)

2) Если после выполнения первого пункта ситуация не прояснится, можно настроить трассировку wcf сервисов

https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/tracing-a…

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Доброе утро, коллеги.

Есть вопрос.

Сделал тестовый вэб-сервис , по примеру из http://www.community.terrasoft.ru/forum/topic/9811 , но у меня что-то не сработал.
В логах результат:

При выполнении запроса возникла ошибка  статус ответа: 404 (Not Found) url запроса: [url]/0/rest/RegistrationService/TestServiceMethod метод: POST данные запроса: test data1

all-combined.js:462:345
.log() all-combined.js:462
.error() all-combined.js:462
.logResponseError() all-combined.js:722
.validateResponse() all-combined.js:723
.request/a.callback() all-combined.js:721
.callback() all-combined.js:1
.onComplete() all-combined.js:1
.onStateChange() all-combined.js:1
Ext.Function.bind/

Код регистрационного сервиса:

namespace Terrasoft.Configuration.CommandLineService
{
  using System;
  using System.Collections.Generic;
  using System.Security;  
  using System.ServiceModel;
  using System.ServiceModel.Activation;
  using System.Web;
  using Newtonsoft.Json;
  using Terrasoft.Common;
  using Terrasoft.Web.Common;
  using Terrasoft.Configuration.RegistrationHelper;
  using Terrasoft.Core;
  using Terrasoft.Core.Configuration;
  using Terrasoft.Core.DB;
  using Terrasoft.Core.Scheduler;
  using System.CodeDom.Compiler;
  using System.ServiceModel;
  using System.ServiceModel.Web;
  using Terrasoft.Core.Entities;
  using Terrasoft.Core.Store;
  using System.Data;
  using System.Collections.Generic;

  #region Class: RegistrationService
 
  [ServiceContract]
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
  public class RegistrationService{

    [OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    public string TestServiceMethod(string data) {
      var userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];
      string key = string.Format("ExportFilterKey_{0}", Guid.NewGuid());
      userConnection.SessionData[key] = data;
      return key;
    }
  }

  #endregion
}

код запроса к нему, на клиенте:

// тест
Terrasoft.AjaxProvider.request({
  url: Terrasoft.workspaceBaseUrl + "/rest/RegistrationService/TestServiceMethod",
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  method: 'POST',
    jsonData:  'test data',
    callback: function(request, success, response) {
    if (success) {
      console.log(response.responseText);
    }
  },
  scope: this
});

У меня такой же вопрос

2 комментария

Мой промах, забыл опубликовать. Сделал публикацию и получил теперь:

POST [url]/0/rest/RegistrationService/TestServiceMethod 400 (Bad Request)

Здравствуйте, Евгений!

Такая ситуация связана с тем, что по умолчанию веб-сервис требует авторизции. Можно реализовать ее в клиеннтском приложении или создать сервис, доступный без авторизации. Информацию о том, как это сделать добавляю во вложение.

Также обратите внимание, что в большинстве случаев для обмена данными с системой удобнее использовать не веб сервис, а протокол Odata.

Средства интеграции bpm'online достаточно подробно описаны в документации по разработке, раздел "Примеры решения типовых задач" - "Рекомендуемые средства интеграции".

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день Коллеги!!!
У меня возникла проблема, хотел одебажыть веб сервис таким способом но не попадает брейкпоинт при исполнении, хоть он выполняется (есть респонс)

У меня такой же вопрос

6 комментариев

Здравствуйте.
А отладить обычные процессы на этом приложении получается?

"Репко Артём" написал:

Здравствуйте.
А отладить обычные процессы на этой приложении получается?


да

"Ильюша Сергей Николаевич" написал:
Репко Артём пишет:

Здравствуйте.
А отладить обычные процессы на этой приложении получается?

да


А breakpoint "активный" в студии?
Какой ответ от сервиса (success)?

"Бондаренко Александр Сергеевич" написал:А breakpoint "активный" в студии?
Какой ответ от сервиса (success)?

А breakpoint "активный" в студии - да активный сразу
Какой ответ от сервиса (success) - true, сервис работает хорошо и выдает все что нужно

Извеняюсь проблема была в студии, после переустановки начало отлавлевать breakpoint's

"Ильюша Сергей Николаевич" написал:

Извеняюсь проблема была в студии, после переустановки начало отлавлевать breakpoint's


Сергей, спасибо за ответ.
Если у Вас возникнут дополнительные вопросы по web-сервисам, пожалуйста, обращайтесь.

Войдите или зарегистрируйтесь, чтобы комментировать