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:

13 comments:

  1. Папка расшаривается только на определенного пользователя? Или должны ли пересекаться права с MS CRM?

    ReplyDelete
  2. Это действительно узкое место. Папка шарится всем пользователям домена...

    ReplyDelete
  3. В общем еще раз показал, что все возможно было бы желание и с руками порядок :) Придумывай свой аддон, если этот аналог стоит 2 тыщ евро, так почему бы и нет ))

    ReplyDelete
  4. Hello Andriy,
    I have a problem when the integration because when I do a frame, I see the javascript code and just a blank page.

    ReplyDelete
  5. What do you pass to URL of IFrame?

    ReplyDelete
  6. Good! The problem now is that I have a blank page! Nothing is displayed! How do I complete the file "web.config"?
    Especially for lines:

    ReplyDelete
  7. excuse me :
    For value : "E:\DocumentShare"?

    ReplyDelete
  8. <add key="Directory" value="E:\DocumentShare"/>
    This key means directory which is used as a Fil Share Root Directory on your server.

    <add key="BaseDirectory" value="\\YourServer\DocumentShare"/>
    This key means how this directory can be accessed from the network.

    ReplyDelete
  9. I still have a blank page but I think the problem is browser.aspx.cs code.
    At the line:
    string = BaseDirectory ConfigurationSettings.AppSettings ["BaseDirectory"]; DocumentShare.Attributes ["src"] = String.Format ("(0) / (1) / (2)", BaseDirectory, EntityTypeCode, EntityID);

    What is "DocumentShare" here?
    This variable is not declared.

    ReplyDelete
  10. Because this is not Variable. This is control from ASP.Net page:

    <iframe id="DocumentShare" src="" frameborder="0" runat="server" />

    ReplyDelete
  11. It is normal that when I go on the button "file share", it creates a folder "8" in the shared folder on the server?
    I still have a blank page.

    ReplyDelete
  12. Do you know C#. C# code describes everything what is happening when the page is loading.

    I repeat my question one more time:
    How does your code form URL and how it pass this URL to IFRAME?

    ReplyDelete