Wednesday, September 21, 2011

How we create ISV Site in MS Dynamics CRM 4.0 for Hosted Model

Step1: Create a new Web Application in Visual Studio 2010
Step2: Create "WSDL" folder and download CrmService.asmx and MetadataService.asmx from CRM hosted URL and save then into "WSDL" folder.

Step3: Get CrmDiscoveryService.wsdl from SDK and save into "WSDL" folder.
Step4:
Add web reference for all three webservices in the project.
Step5: Create a "Dashboard.aspx" page into project
<html>
<head id="Head1" runat="server">
<title>Untitled Page</title>
<style type="text/css">
BODY
{
background-image: url(/_imgs/app_back.gif);
background-repeat: repeat-x;
border-top: 1px solid #6693cf;
font-family: Tahoma;
font-size: 11px;
height: 100%;
margin: 0;
padding: 0;
}
#MainDiv
{
margin: 5px;
padding: 5px;
border: 1px solid #6893CF;
background-color: #eaf3ff;
display: table;
text-align: center;
}
DIV.ContentDiv
{
height: 150px;
width: 98%;
text-align: center;
border: 1px solid #6893CF;
background-color: #F3F8FF;
overflow: auto;
}
table
{
width: 90%;
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #6893CF;
}
th
{
font-size: 7pt;
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,
StartColorStr=#DBEBFF, EndColorStr=#FFFFFF; ) background-image:url(/_imgs/nav_header_back.gif);
background-repeat: repeat-x;
padding: 3px;
border-top: 1pxsolid#ffffff;
border-bottom: 1pxsolid#DDECFF;
}
th, td
{
border-left: 1px solid #DDECFF;
}
td
{
padding-top: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #DDECFF;
}
.MainRow
{
background-color: #edf4fc;
}
.AltRow
{
background-color: #ffffff;
}
.TableHeader
{
font-size: 7pt;
font-weight: bold;
padding-top: 10px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="MainDiv">
<div>
&nbsp;
<div id="LeadDiv" class="ContentDiv">
<div class="TableHeader">
Top 5 Most Recent Open Leads</div>
<asp:Table ID="LeadTable" runat="server" CellPadding="0" CellSpacing="0">
<asp:TableHeaderRow>
<asp:TableHeaderCell>Full Name</asp:TableHeaderCell>
<asp:TableHeaderCell>Phone</asp:TableHeaderCell>
<asp:TableHeaderCell>City</asp:TableHeaderCell>
<asp:TableHeaderCell>Lead Source</asp:TableHeaderCell>
<asp:TableHeaderCell>Created On</asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</div>
&nbsp;
<div id="ActivityDiv" class="ContentDiv">
<div class="TableHeader">
Top 5 Activities Due this Week</div>
<asp:Table ID="ActivityTable" runat="server" CellPadding="0" CellSpacing="0">
<asp:TableHeaderRow>
<asp:TableHeaderCell>Activity Type</asp:TableHeaderCell>
<asp:TableHeaderCell>Subject</asp:TableHeaderCell>
<asp:TableHeaderCell>Priority</asp:TableHeaderCell>
<asp:TableHeaderCell>Start Date</asp:TableHeaderCell>
<asp:TableHeaderCell>Due Date</asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</div>
&nbsp;
<div id="OpportunityDiv" class="ContentDiv">
<div class="TableHeader">
Top 5 Most Recent Opportunities</div>
<asp:Table ID="OpportunityTable" runat="server" CellPadding="0" CellSpacing="0">
<asp:TableHeaderRow>
<asp:TableHeaderCell>Topic</asp:TableHeaderCell>
<asp:TableHeaderCell>
Potential Customer
</asp:TableHeaderCell>
<asp:TableHeaderCell>Est. Close Date</asp:TableHeaderCell>
<asp:TableHeaderCell>Probability</asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</div>
</div>
&nbsp;
</div>
</form>
</body>
</html>

Step6: Write following code on Dashboard.aspx.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ISVHostedModel.WSCRMService;
using ISVHostedModel.WSMetaDataService;
using ISVHostedModel.WSDiscoveryService;
using System.Net;
using Microsoft.Win32;
using System.Xml;

namespace ISVHostedModel
{
    public partial class Dashboard : System.Web.UI.Page
    {
        #region CRMServiceAuthentication
        public CrmService GetCRMService(string orgname, string User, string Password, string Domain)
        {
            CrmDiscoveryService disco = new CrmDiscoveryService();
            disco.Url = "http://" + orgname + ".hostingdomain:port/MSCRMServices/2007/SPLA/CrmDiscoveryService.asmx";
            disco.Credentials = new NetworkCredential(User, Password, "exchange");

            //Retrieve a list of available organizations from the CrmDiscoveryService Web service.
            RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();

            // Substitute an appropriate domain, username, and password here.
            orgRequest.UserId = Domain + "\\" + User;
            orgRequest.Password = Password;
            RetrieveOrganizationsResponse orgResponse = (RetrieveOrganizationsResponse)disco.Execute(orgRequest);

            //Find the target organization.
            OrganizationDetail orgInfo = null;

            foreach (OrganizationDetail orgdetail in orgResponse.OrganizationDetails)
            {
                if (orgdetail.OrganizationName.ToUpper().Equals(orgname.ToUpper()))
                {
                    orgInfo = orgdetail;
                    break;
                }
            }

            // Check whether a matching organization was not found.
            if (orgInfo == null)
                throw new Exception("The specified organization was not found.");

            //Retrieve a CrmTicket from the CrmDiscoveryService Web service.
            RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
            ticketRequest.OrganizationName = orgInfo.OrganizationName;
            ticketRequest.UserId = Domain + "\\" + User;
            ticketRequest.Password = Password;

            RetrieveCrmTicketResponse ticketResponse =
                (RetrieveCrmTicketResponse)disco.Execute(ticketRequest);

            //Create the CrmService Web service proxy.
            WSCRMService.CrmAuthenticationToken sdktoken = new WSCRMService.CrmAuthenticationToken();
            sdktoken.AuthenticationType = 2;
            sdktoken.OrganizationName = orgInfo.OrganizationName;
            sdktoken.CrmTicket = ticketResponse.CrmTicket;

            CrmService service = new CrmService();
            service.CrmAuthenticationTokenValue = sdktoken;
            service.Url = orgInfo.CrmServiceUrl;
            service.Credentials = new NetworkCredential(User, Password, Domain);
            return service;
        }
        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            CrmService service = GetCRMService("organization", "username", "password", "domain");
            WhoAmIRequest request = new WhoAmIRequest();
            WhoAmIResponse response = (WhoAmIResponse)service.Execute(request);

            PopulateLeadTable(service, response.UserId);
            PopulateActivityTable(service, response.UserId);
            PopulateOpportunityTable(service, response.UserId);
        }

        private void PopulateLeadTable(CrmService crmService, Guid userId)
        {
            BusinessEntityCollection bec;
            QueryExpression leadQuery = new QueryExpression();
            leadQuery.EntityName = EntityName.lead.ToString();

            ColumnSet leadColumns = new ColumnSet();
            leadColumns.Attributes = new string[] { "fullname", "telephone1", "address1_city", "leadsourcecode", "createdon" };

            leadQuery.ColumnSet = leadColumns;

            ConditionExpression ownerCondition = new ConditionExpression();
            ownerCondition.AttributeName = "ownerid";
            ownerCondition.Operator = ConditionOperator.Equal;
            ownerCondition.Values = new object[] { userId };

            FilterExpression filter = new FilterExpression();
            filter.Conditions = new ConditionExpression[] { ownerCondition };
            filter.FilterOperator = LogicalOperator.And;

            leadQuery.Criteria = filter;

            OrderExpression order = new OrderExpression();
            order.AttributeName = "createdon";
            order.OrderType = OrderType.Descending;

            leadQuery.Orders = new OrderExpression[] { order };

            bec = crmService.RetrieveMultiple(leadQuery);

            // add the top 5 leads
            for (int i = 0; i < bec.BusinessEntities.Length; i++)
            {
                lead crmLead = (lead)bec.BusinessEntities[i];

                string rowClass = "MainRow";
                if (i % 2 == 1)
                    rowClass = "AltRow";

                TableRow tr = new TableRow();
                tr.CssClass = rowClass;

                TableCell fullNameCell = new TableCell();
                fullNameCell.Text = crmLead.fullname;

                tr.Cells.Add(fullNameCell);

                TableCell phoneCell = new TableCell();
                phoneCell.Text = crmLead.telephone1;

                tr.Cells.Add(phoneCell);

                TableCell cityCell = new TableCell();
                cityCell.Text = crmLead.address1_city;

                tr.Cells.Add(cityCell);

                TableCell leadSourceCell = new TableCell();
                if (crmLead.leadsourcecode != null)
                    leadSourceCell.Text = crmLead.leadsourcecode.name;

                tr.Cells.Add(leadSourceCell);

                TableCell createdOnCell = new TableCell();
                createdOnCell.Text = crmLead.createdon.Value;

                tr.Cells.Add(createdOnCell);

                this.LeadTable.Rows.Add(tr);

                if (i == 4)
                    break;
            }
        }

        private void PopulateActivityTable(CrmService crmService, Guid userId)
        {
            string fetchResults, fetchXml;
            fetchXml = String.Format(@"<fetch mapping='logical'>
                                        <entity name='activitypointer'>
                                            <attribute name='activitytypecode' />
                                            <attribute name='subject' />
                                            <attribute name='scheduledstart' />
                                            <attribute name='scheduledend' />
                                            <attribute name='prioritycode' />
                                            <attribute name='createdon' />

                                            <filter type='and'>
                       <condition attribute='ownerid' operator='eq' value='{0}' />
                       <condition attribute='scheduledend' operator='this-week' />
                       <condition attribute='statecode' operator='eq' value='0' />
                                            </filter>

                                            <order attribute='createdon' />
                                        </entity>
                                    </fetch>", userId);

            fetchResults = crmService.Fetch(fetchXml);

            XmlDocument fetchResultDoc = new XmlDocument();
            fetchResultDoc.LoadXml(fetchResults);

            XmlNodeList resultNodes = fetchResultDoc.DocumentElement.SelectNodes("result");

            for (int i = 0; i < resultNodes.Count; i++)
            {
                string activityType = String.Empty;
                string subject = String.Empty;
                string scheduledStart = String.Empty;
                string scheduledEnd = String.Empty;
                string priorityCode = String.Empty;

                activityType = resultNodes[i].SelectSingleNode("activitytypecode").Attributes["name"].Value;

                subject = resultNodes[i].SelectSingleNode("subject").InnerText;

                XmlNode scheduledStartNode = resultNodes[i].SelectSingleNode("scheduledstart");

                if (scheduledStartNode != null)
                    scheduledStart = scheduledStartNode.Attributes["date"].Value;

                XmlNode scheduledEndNode = resultNodes[i].SelectSingleNode("scheduledend");

                if (scheduledEndNode != null)
                    scheduledEnd = scheduledEndNode.Attributes["date"].Value;

                priorityCode = resultNodes[i].SelectSingleNode("prioritycode").Attributes["name"].Value;

                string rowClass = "MainRow";

                if (i % 2 == 1)
                    rowClass = "AltRow";

                TableRow tr = new TableRow();
                tr.CssClass = rowClass;

                TableCell activityTypeCell = new TableCell();
                activityTypeCell.Text = activityType;

                tr.Cells.Add(activityTypeCell);

                TableCell subjectCell = new TableCell();
                subjectCell.Text = subject;

                tr.Cells.Add(subjectCell);

                TableCell priorityCell = new TableCell();
                priorityCell.Text = priorityCode;

                tr.Cells.Add(priorityCell);

                TableCell scheduledStartCell = new TableCell();
                scheduledStartCell.Text = scheduledStart;

                tr.Cells.Add(scheduledStartCell);

                TableCell scheduledEndCell = new TableCell();
                scheduledEndCell.Text = scheduledEnd;

                tr.Cells.Add(scheduledEndCell);

                this.ActivityTable.Rows.Add(tr);

                if (i == 4)
                    break;
            }
        }

        private void PopulateOpportunityTable(CrmService crmService, Guid userId)
        {
            BusinessEntityCollection bec;
            QueryExpression opportunityQuery = new QueryExpression();
            opportunityQuery.EntityName = EntityName.opportunity.ToString();

            ColumnSet opportunityColumns = new ColumnSet();
            opportunityColumns.Attributes = new string[] { "name", "customerid", "estimatedclosedate", "closeprobability" };

            opportunityQuery.ColumnSet = opportunityColumns;

            ConditionExpression ownerCondition = new ConditionExpression();
            ownerCondition.AttributeName = "ownerid";
            ownerCondition.Operator = ConditionOperator.Equal;
            ownerCondition.Values = new object[] { userId };

            FilterExpression filter = new FilterExpression();
            filter.Conditions = new ConditionExpression[] { ownerCondition };
            filter.FilterOperator = LogicalOperator.And;

            opportunityQuery.Criteria = filter;

            OrderExpression order = new OrderExpression();
            order.AttributeName = "createdon";
            order.OrderType = OrderType.Descending;
            opportunityQuery.Orders = new OrderExpression[] { order };

            bec = crmService.RetrieveMultiple(opportunityQuery);

            for (int i = 0; i < bec.BusinessEntities.Length; i++)
            {
                opportunity crmOpportunity = (opportunity)bec.BusinessEntities[i];

                string rowClass = "MainRow";

                if (i % 2 == 1)
                    rowClass = "AltRow";

                TableRow tr = new TableRow();
                tr.CssClass = rowClass;

                TableCell topicCell = new TableCell();
                topicCell.Text = crmOpportunity.name;

                tr.Cells.Add(topicCell);

                TableCell customerCell = new TableCell();
                if (crmOpportunity.customerid != null)
                    customerCell.Text = crmOpportunity.customerid.name;

                tr.Cells.Add(customerCell);

                TableCell closeDateCell = new TableCell();
                if (crmOpportunity.estimatedclosedate != null)
                    closeDateCell.Text = crmOpportunity.estimatedclosedate.Value;

                tr.Cells.Add(closeDateCell);

                TableCell probabilityCell = new TableCell();
                if (crmOpportunity.closeprobability != null)
                    probabilityCell.Text =
                                  crmOpportunity.closeprobability.Value.ToString();

                tr.Cells.Add(probabilityCell);

                this.OpportunityTable.Rows.Add(tr);

                if (i == 4)
                    break;
            }
        }
    }
}


Step7: Add new Web Deployment Project in the solution

Step8: Rebuild All Solution

Step9: Give that Deployment Package to your CRM Hosting Service Provider for deploy the project into CRM "ISV" folder.

Step10: After successful deployment your Hosting Service Provider will provide you a link.

Step11: Export and modify the SiteMap.xml (add provided link) into any group code and update SiteMap.xml file.


Step13: Import SiteMap.xml customization in your hosting environment and enjoy...