Вызвать сервис в событийном подпроцессе

Всем привет. Кто-нибудь вызывал интеграционный веб-сервис в событийном подпроцессе?
У меня есть сервис, который должен возвращать данные, есть событийный подпроцесс, который срабатывает на ивенте добавления записи в таблицу. 
Вызываю сервис таким образом: 

 

OnInserting() {
 CallService(entity)  
}
 
[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "Contragent/{contragentId}/Communication", BodyStyle = WebMessageBodyStyle.Bare,
           RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public async virtualTask<IntegrationResponseModelV2<AccountCommunicationServiceResponseModel>> 
CallService(entity) {}

Проблема в том, что респонс не долетает до меня при таком вызове сервиса. При дебаге свал происходит на этапе получения хэддеров респонса. Спрашиваю у Вас , так как есть догадки, что метаданные атрибутов не подтягиваются при таком вызове, так как делаю это впервые. 
Если вызывать сервис через постман - ловлю успех 200, данные прилетают.

Также прошу подсказать иные варианты решения вызова веб-сервиса при событии добавления в объект, но только чтобы я мог отловить Entity измененных данных. Спасибо!

Нравится

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

Смогу ли я захендлить сообщение и вызвать свой сервис напрямую используя артибут EntityEventListener?

[EntityEventListener(SchemaName = "AccountCommunication")]

Владислав Киселевич,

Здравствуйте, вам лучше вынести всю логику сбора данных в отдельный Helper который будет реализовывать интерфейс с методом возвращающим нужную структуру данных. А в сервисе через ClassFactory вызывать данный хелпер, его же можно будет и на событийке использовать.  будет что то вроде такого:

public interface IHelper
{	
  UserConnection UserConnection { get; set; }
  public AccountCommunicationServiceResponseModel GetModel(Entity entity);
}
[DefaultBinding(typeof(IHelper))]
public class AccountCommunicationHelper : IHelper
{
  UserConnection UserConnection { get; set; }
  public AccountCommunication(UserConnection userConnection){
   UserConnection = userConnection;
   public AccountCommunicationServiceResponseModel GetModel(Entity entity){
     //TODO
   }
 }
}
[OperationContract] 
[WebInvoke(Method = "POST", UriTemplate = "Contragent/{contragentId}/Communication", BodyStyle = WebMessageBodyStyle.Bare,
           RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public AccountCommunicationServiceResponseModel CallService(entity) {
	var helper = ClassFactory.Get<IHelper>(new ConstructorArguments("userConnection", USerConnection));
	return helper.GetModel(entity)
}
 
[EntityEventListener(SchemaName = "AccountCommunication")]
public class AccountCommunicationEventListener : BaseEntityEventListener {
  OnInserting(object sender, EntityBeforeEventArgs e) {
   base.OnInserting(sender, e)
   var helper = ClassFactory.Get<IHelper>(new ConstructorArguments("userConnection", 
   USerConnection));
   helper.GetModel((Entity)sender);
}
}

 

Нигрескул Алексей,

Благодарю за ответ. Алексей, с маппингом понял, спасибо.
Сервис всегда будет передать коллекцию где collection.count = 1, поэтому реализовал так(прикрепил ниже).  Изначально хотел вызвать сервис методом инжекта своего инстанс класса через интерфейс, но не учел отсутствие DI. нуждаюсь в более детальных объяснениях по-поводу наследования от BaseEntityEventListener. Цепочка вызова методов сервиса также написана через фабрику, где все работает исправно(так показывает вызов сервиса напрямую). Попрошу Вас, если не затруднит, помочь конкретно на моем примере : как именно будет корректно при событии вызвать мой сервис напрямую, а не из событийки чтобы работало все как по маслу. Прикрепляю текущий код ивентХедлера и метод сервиса.

 

 

 public virtual async void OnInserted(ProcessExecutingContext context)
        {
            string accountId = Entity.AccountId.ToString();
            var requestModel = new AccountCommunicationServiceRequestModel();
            var communication = new CommunicationRequestModel
            {
                Id = Entity.PrimaryColumnValue,
                Number = Entity.Number,
                CommunicationTypeId = Entity.CommunicationTypeId,
                TsComment = Entity.TsComment,
                Primary = Entity.Primary,
                Roles = null
            };
            requestModel.Communications.Add(communication);
 
            var accountCommunicationService = new AccountCommunicationService();
			await accountCommunicationService.CreateCommunications(accountId, requestModel);
}

 

 #region Class : AccountCommunicationService
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class AccountCommunicationService : IAccountCommunicationService
    {
        #region Properties : Protected
        protected UserConnection UserConnection
            => HttpContext.Current.Session["UserConnection"] as UserConnection;
        #endregion
 
        #region Methods : Public
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "Contragent/{contragentId}/Communication", BodyStyle = WebMessageBodyStyle.Bare,
            RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public async Task<BusIntegrationResponseModelV2<AccountCommunicationServiceResponseModel>> CreateCommunications(
            string contragentId, AccountCommunicationServiceRequestModel requestModel) 
        {
            var result = new BusIntegrationResponseModelV2<AccountCommunicationServiceResponseModel>();
            try
            {
                IIntegrationWrapperV2<AccountCommunicationServiceRequestModel> wrapper =
                    AccountCommunicationServiceFactory.GetAccountCommunicationIntegrationWrapper(UserConnection);
                result = await wrapper.ExecuteAsync<AccountCommunicationServiceResponseModel>(requestModel, contragentId);
                return result;
            }
 
            catch (AccountCommunicationValidatorException ex)
            {
                result.ErrorInfo = new ErrorInfo
                {
                    ErrorCode = "111",
                    Message = ex.Message,
                    StackTrace = ex.StackTrace
                };
            }
            return result;
        }
        #endregion
    }
    #endregion

 

Владислав, добрый день!

Не рекомендую использовать ваш подход с асинхронностью, так как на данный момент она попросту не поддерживается в системе.

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

1. Если метод синхронный, то не нужно вызывать его асинхронно.

2. Если метод асинхронный, то следует вызывать его синхронно путем добавления конструкции .ConfigureAwait(false).GetAwaiter().GetResult().

Лучше поступить ка предложил Алексей или же полностью избавиться от асинхронности. 

Показать все комментарии