Question

Correct way to get UserConnection in Word Macro IExpressionConverter?

What is the correct way to get a UserConnection for a Word printable macro using IExpressionConverter?

If I use the following it works when the user runs the printable:

var userConnection = (UserConnection)System.Web.HttpContext.Current.Session["UserConnection"];

However, this fails if the printable is run from Process File element in a process (because the session is unavailable/null).

Is there some other way to get the UserConnection in a Word macro that will work when run from a process?

Like 2

Like

6 comments

Hi Ryan,



In this case you can use SystemUserConnection instead of UserConnection: 

https://academy.terrasoft.ru/api/netcoreapi/7.11.0/index.html#Terrasoft.WebApp.Loader~Terrasoft.WebApp.Loader.Authentication.AuthEngine~SystemUserConnection.html

var systemUserConnection = appConnection.SystemUserConnection;



Best Regards,

Tetiana Bakai 

Tetiana Bakai,

How would I get the AppConnection in order to get the SystemUserConnection from it? The only way I know how to get that is from the session, which will have the same problem. In a custom macro that is used in a printable that is generated from the Process File element in a process (that is run from a timer etc), the HttpContext.Current is null, so there is no session to get the AppConnection from.

Is there some other way to get an AppConnection without getting it from the session?

Ryan

Ryan Farley,

 

The only possible way to extract UserConnection when the business process is started is inside the script task of this process and you can work with it further (as far as I remember timer business processes are executed under the user specified in the "System operations user" system setting (by default it's Supervisor so you can extract the Supervisor user connection in the context of the process execution)). Then you can specify the extracted value as a parameter of this process and use it somewhere else (like send a request using Web-service call process element or send a request using another script task).

 

Also try the following approach maybe it will help:

 

1) Override ExpressionConverterHelper so that the constructor could receive UserConnection:

 

this:

var expressionConverter = (IExpressionConverter)Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
    macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

should be changed to this:

dynamic expressionConverter = Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
	PropertyInfo propertyInfo = expressionConverter.GetType().GetProperty("UserConnection");
	if (propertyInfo != null) {
		propertyInfo.SetValue(expressionConverter, UserConnection, null);
	}
	macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

2) In the ReportService class modify this string:

 

var expressionConverterHelper = new ExpressionConverterHelper();

to

var expressionConverterHelper = new ReplacedExpressionConverterHelper(UserConnection);

3) Specify this at the beginning of the macros:

private UserConnection _userConnection;
public UserConnection UserConnection {
    get {
	    if (_userConnection == null) {
		    _userConnection = (UserConnection)HttpContext.Current?.Session["UserConnection"];
	    };
	    return _userConnection;
	}
    set => _userConnection = value;
}

And try extracting AppConnection after that.

 

Best regards,

Oscar

Oscar Dylan,

I suppose I could try this as a workaround, but this is how it should work out of the box to provide a UserConnection to a macro without the need for a workaround. It would be great for the out of the box ExpressionConverterHelper to look for a UserConnection property in the macro class and set if exists. As it is now, the Process File process element only works in some cases when the selected printable doesn't have a macro and the process is only executed in certain scenarios.

Ryan

It would be very helpful to have a general way to get a SystemUserConnection from C# for when it's called from a Business Process running in background mode or other times when things just need to run as the system user. I've come across the same issue, and can't pass the UserConnection in as far as I can tell with the BP being started by a timer - at what point is the UserConnection actually existent in the BP to do so? Does it have to go in the BP's Methods section or something? And if so, how are we supposed to store the UserConnection value to a BP parameter to pass it into the C# code?

For anyone who was searching for a solution to this for calling C# code from a BP script task where that BP could be running in background mode like with a timer or if the BP is called by another BP in background mode (and so simply using UserConnection in the script task doesn't work) this post helped me: https://community.creatio.com/questions/establish-connection-3rd-party-…

 

In the script task, what you want to do is

var userConn = Get<UserConnection>("UserConnection"); 

to get the UserConnection to pass to the C# method/constructor, instead of using what I'd seen before, which was just to pass UserConnection directly to the C# method. The direct passing method works for foreground operation, but breaks for background running, whereas the Get method works for both.

Show all comments