Integrating CRM 2011 Online and SharePoint 2013 Online using BCS oData Proxy


Here we will be creating an ASP.NET Data Service and host it in azure. This ASP.NET Data Service will be used to generate BCS Model in SharePoint 2013 online. The service will allow basic CRUD operation on Contact record in CRM 2011 from SharePoint 2013 online.

  • Create a new Windows Azure Cloud Service project in VS 2012

  • Select WCF Service Web Role

  • Remove the System.Data.Services.Client.dll from the References

  • Add a new item ASP.NET Data Service to the WCFServiceWebRole1 project


  • Add a new class to the project

  • Specify the class name in the ASP.NET Data Service class

  • Add references to the following dll’s
  1. Microsoft.crm.sdk.proxy
  2. Microsoft.xrm.sdk
  3. Microsoft.IdentityModel
  • Set Copy Local as true for the Micrsoft.IdentityModel

  • Source Code for CrmContext.cs, for CRUD Operation (we need to implement IUpdatable Interface for CRUD)
</pre>
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;
namespace WCFServiceWebRole1
{
 [DataServiceKey("ContactId")]
 [Serializable]
 public class Contact
 {
 [DataMemberAttribute()]
 public Guid ContactId
 {
 get;
 set;
 }
 [DataMemberAttribute()]
 public string FirstName
 {
 get;
 set;
 }
 [DataMemberAttribute()]
 public string LastName
 {
 get;
 set;
 }
 }

public class CrmContext : IUpdatable
 {
 public static List<Contact> lstContacts;
 public static OrganizationServiceProxy orgProxy = GetOrganizationService();

public static List<Contact> GetContacts()
 {
 List<Contact> lstContact = new List<Contact>();
 QueryExpression queryExpression = new QueryExpression("contact");
 ConditionExpression conditionExpression = new ConditionExpression("statuscode", ConditionOperator.Equal, 1);
 queryExpression.ColumnSet = new ColumnSet(new String[] { "contactid", "firstname", "lastname" });
 EntityCollection contactCollection = orgProxy.RetrieveMultiple(queryExpression);

Contact contactRecord;
 foreach (Entity entity in contactCollection.Entities)
 {
 contactRecord = new Contact();
 contactRecord.ContactId = (Guid)entity.Attributes["contactid"];
 if (entity.Contains("firstname"))
 {
 contactRecord.FirstName = entity.Attributes["firstname"].ToString();
 }
 if (entity.Contains("lastname"))
 {
 contactRecord.LastName = entity.Attributes["lastname"].ToString();
 }

lstContact.Add(contactRecord);
 }

return lstContact;
 }

public IQueryable<Contact> Contacts
 {
 get
 {
 return lstContacts.AsQueryable();
 }
 }

Contact currentEntry;
 bool NewEntry = false;
 bool Delete = false;

#region implemented methods
 object IUpdatable.CreateResource(string containerName, string fullTypeName)
 {
 var objType = Type.GetType(fullTypeName);
 var resourceToAdd = Activator.CreateInstance(objType);
 lstContacts.Add((Contact)resourceToAdd);
 currentEntry = (Contact)resourceToAdd;
 NewEntry = true;
 return resourceToAdd;
 }

void IUpdatable.DeleteResource(object targetResource)
 {
 orgProxy.Delete("contact", ((Contact)targetResource).ContactId);
 lstContacts.Remove(targetResource as Contact);
 Delete = true;
 }

object IUpdatable.GetResource(IQueryable query, string fullTypeName)
 {
 object result = null;
 var enumerator = query.GetEnumerator();
 while (enumerator.MoveNext())
 {
 if (enumerator.Current != null)
 {
 result = enumerator.Current;
 break;
 }
 }
 if (fullTypeName != null && !fullTypeName.Equals(result.GetType().FullName))
 {
 throw new DataServiceException();
 }

return result;
 }

object IUpdatable.GetValue(object targetResource, string propertyName)
 {
 return targetResource.GetType().GetProperty(propertyName).GetValue(targetResource, null);

}

object IUpdatable.ResolveResource(object resource)
 {
 return resource;
 }

void IUpdatable.SaveChanges()
 {
 if (!Delete)
 {
 if (!NewEntry)
 {
 Entity contactNewRecord = new Entity();
 contactNewRecord.LogicalName = "contact";
 contactNewRecord.Attributes["contactid"] = currentEntry.ContactId;
 contactNewRecord.Attributes["firstname"] = currentEntry.FirstName;
 contactNewRecord.Attributes["lastname"] = currentEntry.LastName;
 orgProxy.Update(contactNewRecord);
 }
 else if (NewEntry)
 {
 Entity contactUpdateRecord = new Entity();
 contactUpdateRecord.LogicalName = "contact";
 contactUpdateRecord.Attributes["contactid"] = currentEntry.ContactId;
 contactUpdateRecord.Attributes["firstname"] = currentEntry.FirstName;
 contactUpdateRecord.Attributes["lastname"] = currentEntry.LastName;
 orgProxy.Create(contactUpdateRecord);
 }
 }

}

void IUpdatable.SetValue(object targetResource, string propertyName, object propertyValue)
 {
 Type TargetType = targetResource.GetType();
 PropertyInfo property = TargetType.GetProperty(propertyName);
 property.SetValue(targetResource, propertyValue, null);
 currentEntry = targetResource as Contact;
 }
 #endregion

#region not implemented methods

void IUpdatable.RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
 {
 throw new NotImplementedException();
 }

void IUpdatable.AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
 {
 throw new NotImplementedException();
 }

void IUpdatable.ClearChanges()
 {
 throw new NotImplementedException();
 }
 object IUpdatable.ResetResource(object resource)
 {
 return resource;
 }
 void IUpdatable.SetReference(object targetResource, string propertyName, object propertyValue)
 {
 throw new NotImplementedException();
 }
 #endregion
 public static OrganizationServiceProxy GetOrganizationService()
 {

 IServiceManagement<IOrganizationService> orgServiceManagement =
 ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings["OrganizationService"]));
 AuthenticationCredentials authCredentials = new AuthenticationCredentials();
 authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["UserName"];
 authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["Password"];
 AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
 return new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);

}

}
}
<pre>

Source Code for CRMDataService.svc


using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;

namespace WCFServiceWebRole1
{
 public class CrmContactService : DataService<CrmContext>
 {
 // This method is called only once to initialize service-wide policies.
 public static void InitializeService(DataServiceConfiguration config)
 {
 config.SetEntitySetAccessRule("*", EntitySetRights.All);
 config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
 }

protected override CrmContext CreateDataSource()
 {
 CrmContext.lstContacts = CrmContext.GetContacts();
 return base.CreateDataSource();
 }
 }
}

  • Build and Publish the service to Azure

  • Test the service in browser

  • Create a new SharePoint App project in Visual Studio

  • Right click the App Project and select the option “Content Types for an External Data Source”

  • Specify the URL for the WCF Data Service and give a Data Source Name and select Next

  • Select the Contacts data entity

  • Deploy the app

  • Get the URL where the app is installed

  • Append the External List path to the URL

  • The Contact records will be displayed in the list in SharePoint.

  • The list item also support update and delete operation

Hope it helps.

Get “Sign in as Different User” back in SharePoint 2013


Hi,

Was working on portal in SharePoint 2013, and had to validate few things by signing as a different user. Then realized that the option of “Sign in as Different user” was missing.

Followed these article to get past this issue

http://support.microsoft.com/kb/2752600

http://nickgrattan.wordpress.com/2012/07/23/sign-in-as-different-user-and-sharepoint-2013/

Hope it helps

The server was unable to save the form at this time. Please try again. Error in Document Library (SharePoint 2013)


Hi,

I was getting the following error while trying to edit properties of a document in the document library in SharePoint 2013.

As suggested restarted SharePoint Search Host Controller service. Stopped few services to release some memory. Nothing helped.

Finally followed these steps

  • Create a new Document Library accepting all defaults
  • Add a document to the library
  • Edit the properties of the document and save.
    RESULT: The server was unable to save the form at this time. Please try again.
  • Enable ‘Manage content types’ in the library setting.
  • Add the ‘Link to a document’ content type.
  • Edit the properties of the document and save.
  • RESULT: Fixed

The helpful post

http://www.3guysonsharepoint.com/?p=1476

Hope it helps.

“This content cannot be displayed in a frame” error while hosting SharePoint 2013 pages in CRM


Hi,

I was getting the above error while trying to hosting the SharePoint 2013 online web part page inside an iframe within CRM’s Form.

The following post came to the rescue

http://blogs.msdn.com/b/officeapps/archive/2012/12/12/iframing-sharepoint-hosted-pages-in-apps.aspx

specifically the following tag

<WebPartPages:AllowFraming runat=”server” />

Hope it helps.

Searching SharePoint 2013 online portal from within CRM 2011 online


 

  1. Open the SharePoint Site and create a custom Web Part Page using SharePoint Designer 2013

  1. Edit the created page in Advanced Mode

  1. Add the AllowFraming tag to the web part page to allow the page to be iframed from within CRM’s Form

Select preview in browser

 

 

  1. Select Page à Edit Page

 

 

  1. Add Search Web Parts

 

  • Search Box in the Header
  • Refinement in the Left Column
  • Search Results in the Body

 

  1. Note the url of the Custom Search Page

https://xyz.sharepoint.com/sites/contoso/Search/SitePages/KBSearch.aspx

  1. Now we can use the above url in the Iframe within our CRM. Here k would be the query string parameter to which search keyword would be passed. We can dynamically set the value of the parameter k through JavaScript in the onload of a particular entity’s form to display the corresponding results in the CRM.

     

https://xyz.sharepoint.com/sites/contoso/Search/SitePages/KBSearch.aspx?k=searchTerm

  1. Search page within Case Form in CRM

Hope it helps.

 

 

 

 

The installation of the package failed error while installing SharePoint Designer 2013


Hi,

After downloading the SharePoint Designer 2013 installer on my lab machine and trying to run it I was getting the below error

Right clicking on it and selecting properties showed that it had the Digital Signatures tab missing in it.

Then downloaded the exe on my other machine, and it had the Digital Signatures tab.

Using this new exe on the lab machine I was able to install the Designer.

Hope it helps.