Monday, September 21, 2009

File Repository for Microsoft Dynamics CRM 4.0

I've read this question and decided to develop this functionality.



Steps:
1. Share some folder.
2. Create custom aspx page with IFrame in it which creates folder for some record and then shows it.
3. ISV customization which adds new element in navigation bar.

1. Sharing a folder:




2. Custom aspx page:

Browser.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Browser.aspx.cs" Inherits="Browser" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Document Browser</title>
</head>
<body bgcolor="#d6ebff" onload="OnResizeComplete();" onresize="OnResizeComplete();">
<iframe id="DocumentShare" src="" frameborder="0" runat="server" />
<script type="text/javascript">
function OnResizeComplete()
{
var fr = window.document.getElementById('DocumentShare');
if (fr != null)
{
var wwidth=(window.innerWidth)?window.innerWidth:
((document.all)?document.body.offsetWidth:null);
fr.style.width = wwidth + 'px';

var wheight=get_wh();
fr.style.height = wheight;
}
}

function get_wh()
{
var frameHeight = window.screen.height;
if (self.innerHeight)
frameHeight = self.innerHeight;
else if (document.documentElement && document.documentElement.clientHeight)
frameHeight = document.documentElement.clientHeight;
else if (document.body)
frameHeight = document.body.clientHeight;
return frameHeight - 30;
}
</script>

</body>
</html>


Browser.aspx.cs:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;

public partial class Browser : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
string RealDirectory = ConfigurationSettings.AppSettings["Directory"];
string EntityTypeCode = Request.QueryString["type"];
string EntityId = Request.QueryString["id"].Replace("{", "").Replace("}", "");

RealDirectory = Path.Combine(RealDirectory, EntityTypeCode);

if (!Directory.Exists(RealDirectory))
Directory.CreateDirectory(RealDirectory);

RealDirectory = Path.Combine(RealDirectory, EntityId);

if (!Directory.Exists(RealDirectory))
Directory.CreateDirectory(RealDirectory);

string BaseDirectory = ConfigurationSettings.AppSettings["BaseDirectory"];
DocumentShare.Attributes["src"] = string.Format("{0}/{1}/{2}",BaseDirectory, EntityTypeCode, EntityId);
}
catch { }

}
}


Web.config:

<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="Directory" value="E:\DocumentShare"/>
<add key="BaseDirectory" value="\\YourServer\DocumentShare"/>
</appSettings>
<connectionStrings/>
<system.web>
<httpModules>
<add name="MapOrg" type="Microsoft.Crm.MapOrgEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="CrmAuthentication" type="Microsoft.Crm.Authentication.AuthenticationEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
<identity impersonate="true"/>
<compilation debug="true">
</compilation>
</system.web>
</configuration>


3. ISV Config (for account):

<ImportExportXml version="4.0.0.0" languagecode="1033" generatedBy="OnPremise">
<Entities>
</Entities>
<Roles>
</Roles>
<Workflows>
</Workflows>
<IsvConfig>
<configuration version="3.0.0000.0">
<Root />
<Entities>
<Entity name="account">
<NavBar ValidForCreate="0" ValidForUpdate="1">
<NavBarItem Icon="/_imgs/ico_18_debug.gif" Url="/ISV/DocumentShare/Browser.aspx" Id="navItem" PassParams="1">
<Titles>
<Title LCID="1033" Text="File Share" />
</Titles>
</NavBarItem>
</NavBar>
</Entity>
<Entity name="contact" />
<Entity name="lead" />
<Entity name="opportunity" />
<Entity name="list" />
<Entity name="campaign" />
<Entity name="campaignactivity" />
<Entity name="campaignresponse" />
<Entity name="incident" />
<Entity name="quote" />
<Entity name="salesorder" />
<Entity name="invoice" />
</Entities>
<!-- Microsoft Customer Relationship Management Service Management Customization -->
<ServiceManagement>
<AppointmentBook>
<SmoothScrollLimit>2000</SmoothScrollLimit>
<TimeBlocks>
<!-- All CSS Class mapping for Service activities -->
<TimeBlock EntityType="4214" StatusCode="1" CssClass="ganttBlockServiceActivityStatus1" />
<TimeBlock EntityType="4214" StatusCode="2" CssClass="ganttBlockServiceActivityStatus2" />
<TimeBlock EntityType="4214" StatusCode="3" CssClass="ganttBlockServiceActivityStatus3" />
<TimeBlock EntityType="4214" StatusCode="4" CssClass="ganttBlockServiceActivityStatus4" />
<TimeBlock EntityType="4214" StatusCode="6" CssClass="ganttBlockServiceActivityStatus6" />
<TimeBlock EntityType="4214" StatusCode="7" CssClass="ganttBlockServiceActivityStatus7" />
<TimeBlock EntityType="4214" StatusCode="8" CssClass="ganttBlockServiceActivityStatus8" />
<TimeBlock EntityType="4214" StatusCode="9" CssClass="ganttBlockServiceActivityStatus9" />
<TimeBlock EntityType="4214" StatusCode="10" CssClass="ganttBlockServiceActivityStatus10" />
<!-- All CSS Class mapping for Appointments -->
<TimeBlock EntityType="4201" StatusCode="1" CssClass="ganttBlockAppointmentStatus1" />
<TimeBlock EntityType="4201" StatusCode="2" CssClass="ganttBlockAppointmentStatus2" />
<TimeBlock EntityType="4201" StatusCode="3" CssClass="ganttBlockAppointmentStatus3" />
<TimeBlock EntityType="4201" StatusCode="4" CssClass="ganttBlockAppointmentStatus4" />
<TimeBlock EntityType="4201" StatusCode="5" CssClass="ganttBlockAppointmentStatus5" />
<TimeBlock EntityType="4201" StatusCode="6" CssClass="ganttBlockAppointmentStatus6" />
</TimeBlocks>
</AppointmentBook>
</ServiceManagement>
</configuration>
</IsvConfig>
<EntityMaps />
<EntityRelationships />
<Languages>
<Language>1033</Language>
</Languages>
</ImportExportXml>


And the result: