<b>Requirement:</b><br>
The requirement is to make a transaction through a BAPI
using the username and password
of the user everytime, who calls a BAPI function,
so that the transactions are logged by the user, not by the
test/development username. This user activity/transaction
will differ from other user.
<b>Details:</b><br>
a) We're using .NET connector (to call BAPIs) in a webservice call.
<br>
i) sapnco.dll (ver: 3.0.0.42)<br>
ii) sapnco_utils.dll (ver: 3.0.0.42)<br>
b) The username & password will be sent as arguments in a web-method.
<b>Approach:</b><br>
Our approach was to make new registration (RegisterDestinationConfiguration)
everytime we call the BAPI function.
But this approach is not recommended by senior members
(like Markus Tolksdorf & Hynek Petrak) on the SCN forum.
They say to register once.
We followed an example mentioned in the link below, but it doesn't work
(the comment with the 'AddOrEditDestination' example):
http://scn.sap.com/thread/3674375
We'll need to un-Register the previous 'registration'
(using the exact username and password as was used during its registration),
to then register a new one. To do this we will need to keep a record
(in a separate table) of the users
who have called the BAPI.
But we will need to check for concurrency of the resource.
i.e. Handle issue when two users register at the same time.
<b>Q: Is there a simpler way and/or better than the one mentioned above?</B>
- - - - - - - - - - - - - - - - - -
Here's the code, we use:
- - - - - - - - - - - - - - - - - -
[WebMethod]
public bool authenticateUser(string un, string pw)
{
bool result = false;
InMemoryDestinationConfiguration objDestConfig = new InMemoryDestinationConfiguration();
try
{
#region "Register/Unregister Destination Configuration"
if (!(RfcDestinationManager.IsDestinationConfigurationRegistered()))
RfcDestinationManager.RegisterDestinationConfiguration(objDestConfig);
objDestConfig.AddOrEditDestination("mySAP", 15, un, pw, "EN", "50", "100.170.14.59", "03", "DEVELOPER");
#endregion
RfcDestination dest = RfcDestinationManager.GetDestination("mySAPdestination");
dest.Ping();
objDestConfig.RemoveDestination("mySAP");
result = true;
}
catch (Exception ex)
{
// log Error using user made function
logError(ex.ToString(), "authenticateUser()");
}
return result;
}
/* - - - - - - - - - - - - - - */
/* AddOrEditDestination Code: */
/* - - - - - - - - - - - - - */
public class InMemoryDestinationConfiguration : IDestinationConfiguration
{
Dictionary<string, RfcConfigParameters> availableDestinations;
RfcDestinationManager.ConfigurationChangeHandler changeHandler;
public InMemoryDestinationConfiguration()
{
availableDestinations = new Dictionary<string, RfcConfigParameters>();
}
public RfcConfigParameters GetParameters(string destinationName)
{
RfcConfigParameters foundDestination;
availableDestinations.TryGetValue(destinationName, out foundDestination);
return foundDestination;
}
//our configuration supports events
public bool ChangeEventsSupported()
{
return true;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged
{
add
{
changeHandler = value;
}
remove
{
//do nothing
}
}
//removes the destination that is known under the given name
public void RemoveDestination(string name)
{
if (name != null && availableDestinations.Remove(name))
{
//Console.WriteLine("Successfully removed destination " + name);
//Console.WriteLine("Fire deletion event for destination " + name);
changeHandler(name, new RfcConfigurationEventArgs(RfcConfigParameters.EventType.DELETED));
}
}
//allows adding or modifying a destination for a specific application server
public void AddOrEditDestination(string name, int poolSize,
string user, string password, string language, string client,
string applicationServer, string systemNumber, string systemID)
{
//in productive code the given parameters should be checked for validity, e.g. that name is not null
//as this is not relevant for the example, we omit it here
RfcConfigParameters parameters = new RfcConfigParameters();
parameters[RfcConfigParameters.Name] = name;
//parameters[RfcConfigParameters.MaxPoolSize] = Convert.ToString(poolSize);
//parameters[RfcConfigParameters.IdleTimeout] = Convert.ToString(1); // we keep connections for 10 minutes
parameters[RfcConfigParameters.User] = user;
parameters[RfcConfigParameters.Password] = password;
parameters[RfcConfigParameters.Client] = client;
parameters[RfcConfigParameters.Language] = language;
parameters[RfcConfigParameters.AppServerHost] = applicationServer;
parameters[RfcConfigParameters.SystemNumber] = systemNumber;
parameters[RfcConfigParameters.SystemID] = systemNumber;
RfcConfigParameters existingConfiguration;
//if a destination of that name existed before, we need to fire a change event
if (availableDestinations.TryGetValue(name, out existingConfiguration))
{
availableDestinations[name] = parameters;
RfcConfigurationEventArgs eventArgs = new RfcConfigurationEventArgs(RfcConfigParameters.EventType.CHANGED, parameters);
//MessageBox.Show("Fire change event " + eventArgs.ToString() + " for destination " + name);
changeHandler(name, eventArgs);
}
else
{
availableDestinations[name] = parameters;
}
//MessageBox.Show("Added application server destination " + name);
}
}