Tuesday, July 14, 2009

CRM 4.0 Logging user login information


Following is a simple example on how-to log a user interaction with CRM. The sample uses a simple plug-in that references the System.Web assembly. Once you create a reference to this assembly you’re able to read the HttpContext and consequently read the information you wish to log.

The plug-in hooks into the execute message which in most cases is the first event to fire (grid event). The plug-in also writes a cookie back to the browser to mark the logging operation so it only happens once while the main crm application is opened.

In the example I also create a simple logInfo entity with fields I’m interested in logging.

Please not that while reading information from the httpcontext and other objects like Request might be considered supported, reading information that CRM uses like httpcontext.items[“organizationName”] or writing information to a cookie might break your support. So when you write values back to the browser make sure you’re using a well defined naming convention that will always stay unique. And instead of reading the orgname from the items collection get it from the request url.


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using System.Web;

namespace GI.SandBox
{
public class LoginHandler : IPlugin
{
#region IPlugin Members

public void Execute(IPluginExecutionContext context)
{
if (context.MessageName != "Execute")
{
return;
}

if (context.Stage != MessageProcessingStage.BeforeMainOperationOutsideTransaction)
{
return;
}

if (!(context.CallerOrigin is ApplicationOrigin))
{
return;
}

HttpContext webContext = HttpContext.Current;
HttpCookie logInfo = webContext.Request.Cookies.Get("loginfo");

if (logInfo == null)
{
DynamicEntity logInfoEntry = new DynamicEntity();
logInfoEntry.Name = "gi_loginfo";

logInfoEntry.Properties.Add
(
new StringProperty
(
"gi_userhostaddress",
webContext.Request.UserHostAddress
)
);

logInfoEntry.Properties.Add
(
new StringProperty
(
"gi_useridentity",
webContext.User.Identity.Name
)
);

logInfoEntry.Properties.Add
(
new StringProperty
(
"gi_starturl",
webContext.Request.Path
)
);

logInfoEntry.Properties.Add
(
new StringProperty
(
"gi_hostname",
webContext.Request.Url.Host
)
);

if (webContext.Items["organizationName"] != null)
{
logInfoEntry.Properties.Add
(
new StringProperty
(
"gi_userhostaddress",
webContext.Items["organizationName"].ToString()
)
);
}

logInfoEntry.Properties.Add
(
new CrmDateTimeProperty
(
"gi_datetime",
new CrmDateTime(webContext.Timestamp.ToString())
)
);

TargetUpdateDynamic targetRecord = new TargetUpdateDynamic();
targetRecord.Entity = logInfoEntry;

UpdateRequest updateRequest = new UpdateRequest();
updateRequest.Target = targetRecord;

context.CreateCrmService(true).Execute(updateRequest);

logInfo = new HttpCookie("loginfo");
logInfo.Value = DateTime.Now.ToString();
webContext.Response.Cookies.Add(logInfo);
}
}

#endregion
}
}

6 comments:

Ravi said...

Kats,

My observations below:

. I hope this plugin will be triggered on every execute request.
So might impact on Performance.
. This plugin should be registered on synchronous mode and will not work asynchronously.
. Doesn't record logout time.


Is there any way to get the signout time?

Adi Katz said...

1. Yes
2. What Impact?
3. A possible solution is to enqueue synchronously and dequeue Asynchronously.
4. True - no easy way of doing that in a stateless environment

Tomek said...

Thanks for this nice piece of code.

After registering the assembly what will be the next steps to get this running ??

Thank you.

Anonymous said...

Hi Adi,
i´ve registered the Plugin as execute - none / none - sychronous... I Also created the entity LogInfo! What will be the next steps to get this running... I dont get any results in LogInfo!

Regards

Adi Katz said...

Once registered this should work immediately. You should however ensure:
1. All users have create rights on the new custom entity.
2. Plug-in was deployed correctly. Copy the plug-in assembly to the server\bin\assembly folder if you deployed the plug-in On Disk. restart the services...

Kevin said...

Question about this solution, will this solution work for logging mobile views? Everytime a user logs into CRM with the mobile application?