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.

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.

 

 

 

 

Cannot connect to the SharePoint site. Make sure that this is a valid URL and the SharePoint site is running on the local computer. If you moved this project to a new computer or if the URL of the SharePoint site has changed since you created the project, update the Site URL property of the project.


Hi,

I have always find it difficult to figure out the place where I need to change the Site URL property for a SharePoint solution, a web part in this case, for deployment.

To change the Site URL property , Select the SharePoint project then àgo to View à Properties Window

We’d find the property there. Update it.

Happy Deploying.

Adding Rating as a refiner in Refinement Web Part in SharePoint 2013 online


Hi,

I was recently asked to add Rating refiner for the Search Results in SharePoint 2013 online site. The way we can achieve this is

Go to Search Administration à Manage Search Schema

Search for ows_AverageRating crawled property

Click on ows_AverageRating property

Map it to any of the RefinableDecimal properties

Edit the Refinement Web Part à Choose Refiners à Add the RefinableDeciaml00 property

The end result à

Hope it helps.