Category: MS CRM Dynamics

Multiple views inside a tab on CRM dashboard

Multiple views inside a tab on CRM dashboard

In this blog, we’re going to implement multiple views inside a tab with the help of web resource.

we are showing Active Accounts, Active Contacts, and Open Opportunities views into a tab of a dashboard.

for this, I used Javascript Tabifier library, you can download JS and CSS from below link

Javascript Tabifier library

let’s upload and publish Tabbler.js and their CSS on our CRM Organization.we can use XrmToolbox for maintaining CRM web resources.

create a new HTML web resource i.e. MultiViews. Inside this, we’ll write our code for showing three different views in a web resource.

crmweb.PNG

For showing views in Iframe we need views URL’s.For more info about how to get URL please refer below link

Copy the URL for a View

email

Here is code for HTML page

<!DOCTYPE html>

<html lang=”en” xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<meta charset=”utf-8″ />
<title></title>
http://../../ClientGlobalContext.js.aspx
http://../content_/js/tabber_minimized.js
<link rel=”stylesheet” href=”../content_/css/example.css” type=”text/css” media=”screen”>

/* Optional: Temporarily hide the “tabber” class so it does not “flash”
on the page as plain HTML. After tabber runs, the class is changed
to “tabberlive” and it will appear. */

document.write(‘.tabber{display:none;}’);

</head>
<body>

Note: Iframe tag is not supported as a text in WordPress so please download the source code from here

In the above code, we’re using Active Accounts, Active Contacts, and Open Opportunities views URL.Now let just add this web resource on dashboard or use a web resource whatever.

m1.PNG

tabbler

That’s it . Now we can see multiple views inside a single web resource.

Here is the link for source code

https://1drv.ms/f/s!AvWbcg6Nl97LiU1kl6GQg1snKfgr

Thanks for visiting my blog.

CRM Web Portal with Token Based authentication -Part 1

CRM Web Portal with Token Based authentication -Part 1

Sometime we have a requirement to make a web portal with using CRM as back end e.g. ticket management portal. A portal is a custom application that allows external users to access and edit data that is stored in Microsoft Dynamics CRM (a.k.a CRUD – Create, Read, Update and Delete operations). A CRM portal application can be developed with different technologies along with the Dynamics CRM Web Services for data access.

In this article we’ll discuss how we can implement token based authentication in CRM web portal.I’ll divided this article into two parts

  1. CRM Web Portal with JWT authentication -Part 1
  2. Intregate CRM web portal with AngularJS-Part 2(coming soon..)

Token Based Authentication

As I stated before we’ll use token based approach to implement authentication between the front-end application and the CRM API, as we all know the common and old way to implement authentication is the cookie-based approach were the cookie is sent with each request from the client to the server, and on the server it is used to identify the authenticated user.

1. Create a web application (webapi) project in visual studio with no authentication.

create_new_project

create_new_project1

create_new_project2

2.Remove Global.asax from our project and add owin starup class i.e. startup.cs

using System;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Security;
using System.Web.Http;
using System.Web.Routing;
using System.Web.Mvc;
using System.Net.Http.Headers;
using Microsoft.AspNet.Identity.Owin;

[assembly: OwinStartup(typeof(MSCRMjwtAuth.Startup))]

namespace MSCRMjwtAuth
{
public class Startup
{

public void Configuration(IAppBuilder app)
{
HttpConfiguration httpconfig = new HttpConfiguration();
WebApiConfig.Register(httpconfig);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.UseWebApi(httpconfig);
httpconfig.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(“text/html”));

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
}
}
}

3.After that install below nuget packages

Install-Package Microsoft.AspNet.WebApi.Owin

Install-Package Microsoft.Owin.Host.SystemWeb

Install-Package Microsoft.Owin.Security.OAuth

Install-Package Microsoft.AspNet.Identity.Owin

Install-Package Microsoft.CrmSdk.CoreAssemblies

In this blog we’re authenticating user with contact entity, emailaddress1 field as username and custom attribute am_password  for password and we also store password in encrypted format.

4.Create a new solution i.e. JWTaunthentication for all our schema customization.

create_solution

5. CRMHelper class

CRMhelper class contains functions that check user and password from our existing CRM contact records on behalf of input that user provided.

/// <summary>
/// This class contains all crm functions
/// </summary>
public class CRMHelper
{
//Variable
public IOrganizationService _orgService;

//CRM dynamics Connection
CrmConnection connection = CrmConnection.Parse(ConfigurationManager.ConnectionStrings[“CRMConnectionString”].ConnectionString);

public CRMHelper()
{
_orgService = new OrganizationService(connection);
}

/// <summary>
/// Login Function for parent
/// </summary>
/// <param name=”arry”>array of login id and password</param>
/// <returns>Datacollection of contact entity</returns>
public DataCollection<Entity> tryLogin(string[] arry)
{
try
{
QueryExpression parentQuery = new QueryExpression()
{
EntityName = “contact”,
ColumnSet = new ColumnSet(“firstname”, “lastname”),
Criteria =
{
Filters =
{
new FilterExpression(LogicalOperator.And)
{
Conditions={
new ConditionExpression(“emailaddress1”,ConditionOperator.Equal,arry[0].ToString()),
new ConditionExpression(“am_password”,ConditionOperator.Equal,StringCipher.Encrypt(arry[1].ToString()))
}
}
}
}
};
return _orgService.RetrieveMultiple(parentQuery).Entities;
}
catch (Exception ex)
{
throw;
}
}

/// <summary>
/// Get all Cases related to logged in user
/// </summary>
/// <param name=”customerid”>Contact Entity guid</param>
/// <returns>Datacollection of Incident Entity</returns>
public DataCollection<Entity> getCases(Guid customerid)
{
try
{
// Instantiate QueryExpression QEincident
var QEincident = new QueryExpression(“incident”);

// Add columns to QEincident.ColumnSet
QEincident.ColumnSet.AddColumns(“title”);

// Define filter QEincident.Criteria
QEincident.Criteria.AddCondition(“customerid”, ConditionOperator.Equal, customerid);
return _orgService.RetrieveMultiple(QEincident).Entities;
}
catch (Exception ex)
{

throw;
}
}

}

5. OAuth Bearer Tokens Generation

Add a new class i.e. ApplicationOAuthProvider.cs in our web application that support for OAuth Bearer Tokens Generation.

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
CRMHelper helper = new CRMHelper();
if (context.UserName != null && context.Password != null)
{
var collection = helper.tryLogin(new string[] { context.UserName, context.Password });
if (collection.Count > 0)
{
context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { “*” });
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Email, context.UserName));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
}

}
//return base.GrantClientCredentials(context);
}
}

6. Encryption and Decryption class

public static class StringCipher
{
// This constant string is used as a “salt” value for the PasswordDeriveBytes function calls.
// This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be
// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array.
private static readonly byte[] initVectorBytes = Encoding.ASCII.GetBytes(“tu89geji340t89u2”);

// This constant is used to determine the keysize of the encryption algorithm.
private const int keysize = 256;
private const string passPhrase = “contact”;
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
}

public static string Decrypt(string cipherText)
{
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
}

7. Create CRM contact record

Also create a record for contact entity in CRM with amankothari@outlook.com as Email and ChHTqB6783q4J/b5BHD7vQ==  as Password (we stored password in encrypted form).

ContactForm.png

8. Add secured controller for Incident

[RoutePrefix(“api/cases”)]
public class CasesController : ApiController
{
CRMHelper helper = new CRMHelper();
[Authorize]
[HttpGet]
[Route(“”)]
public DataCollection<Entity> Getcases()
{
try
{
var identity = (ClaimsIdentity)User.Identity;
foreach (var a in identity.Claims)
{
if (a.Type == “contactid”)
{
return helper.getCases(new Guid(a.Value));
}}
return null;

}
catch (Exception ex)
{
return null;
}
}
}

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/cases&#8221; you will receive HTTP status code 401 unauthorized because the request you send till this moment doesn’t contain valid authorization header.

9.Modified our startup.cs code for support for OAuth Bearer Tokens.

using System;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Security;
using System.Web.Http;
using System.Web.Routing;
using System.Web.Mvc;
using System.Net.Http.Headers;
using Microsoft.AspNet.Identity.Owin;

[assembly: OwinStartup(typeof(MSCRMjwtAuth.Startup))]

namespace MSCRMjwtAuth
{
public class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public void Configuration(IAppBuilder app)
{
HttpConfiguration httpconfig = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(httpconfig);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.UseWebApi(httpconfig);
httpconfig.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(“text/html”));

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString(“/oauth/token”),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
AllowInsecureHttp = true,
};

// Token Generation
app.UseOAuthBearerTokens(OAuthOptions);
}
}
}

Assuming that you saved the username “amankothari@outlook.com”  with password “ChHTqB6783q4J/b5BHD7vQ==” (123456) in CRM. In the step below, we’ll use the same username to generate token, so to test this out open your favorite REST client application in order to issue HTTP requests to generate token for user “amankothari@outlook.com”. For me I’ll be using PostMan.

Now we’ll issue a POST request to the endpoint http://localhost:57205/oauth/token the request will be as the image below:

Postman1.PNG

If the username and password are not same then we sent bad request in response.

invalid_token_postman

If all is correct we’ll receive HTTP status 200 along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

Casescaseresponse

Now our back-end API is ready to be consumed from any front end application or native mobile app.

In my next blog we’ll consumed this API with angularJS application.

Below are the links of solution and web project code respectively.

https://1drv.ms/u/s!AvWbcg6Nl97LiUsVexaWI0gZV2TP

https://1drv.ms/u/s!AvWbcg6Nl97LiUyciNWPn4ehGpNH

 

 

 

 

 

Response type ‘token’ is not enabled for the application

Response type ‘token’ is not enabled for the application


Recently I faced problem when I was trying to build client-side app with CRM and Azure.

I was able to login to my APP and adal.js successfully acquired a token for my webApi and injected it into a request.

Then token acquisition for webApi stopped working with error:

“response_type ‘token’ is not enabled for the application”

Here is the steps that resolved my problem.

Note: If we’re building client-side app, so we need to enable Implicit flow from the application manifest.

How?

1. Select the Configure tab of your application’s entry in the Azure Management Portal.

2. Using the Manage Manifest button in the drawer, download the manifest file for the application and save it to your computer.

2

3. Open the manifest file with a text editor. Search for the oauth2AllowImplicitFlow property. By default it is set to false; change it to true and save the file.

3

4.Using the Manage Manifest button, upload the updated manifest file.

4

Logout and Login with again with you app and it’ll work like a charm.

For more info about OAuth Flow please refer below links

Looking at the Different OAuth2 Flows Supported in AzureAD for Office 365 APIs

v2.0 Protocols – SPAs using the implicit flow

An Introduction to OAuth 2

Hope it’ll help someone.

Thanks for visiting my blog.

Create log in Plug-in using Custom Entity

Create log in Plug-in using Custom Entity

Sometime we want to know what is going on in our plugin code. When the plugin code is very large then we need to write the code for every step which is executed successfully or not.

For Debugging a Plugin we can –

  • Use ITracingService
  • Attach Plugin Registration Tool with VS and debug it.

For more info please refer the below links.

To review more options for external logging, you can also go through the below link.

Author by Salim Adamon

Error Logging Options in CRM

https://community.dynamics.com/crm/b/salimadamondynamicscrm/archive/2013/08/14/error-logging-options-in-crm

In this Blog, we’ll talk about creating log in plug-in using custom entity.

Let’s create an entity i.e. am_log in our CRM.

1

and create attributes which are required for this entity like

am_status ,  am_errordescription.

2

As we all know that creating a record in CRM is very easy but If you are writing logs in a failing transaction of Plugin, then the entire transaction will be rolled back including creation of logging records.

To avoid this roll back of logging records we can use ExecuteMultipleRequest.

For more info about ExecuteMultipleRequest refer to below link

https://msdn.microsoft.com/en-in/library/jj863631.aspx

In this process first we create a plugin, here named as LoggingUsingCustomEntity.

First we need to Create object for ExcuteMultipleRequest and assign settings that define execution behavior  i.e.

ContinueOnError =false,

ReturnResponse=true

ex

exmultiple

Lets say before creating a new account we need to count all Accounts(or any other business requirement) that already present in CRM that create success log in our Log Entity.

success

Now we write invalid expression for creating new account that generate error log in our Log entity.error

According above code log records will create two times,  one for getting all accounts successfully and other for error that is Account doesn’t contain “Name” attribute.

Let’s we deployed this plugin code on Account Create Message and see what will be generates in Log entity.

last.PNG

It created successfully what we expected 🙂

It won’t be created and also roll backed if we use normal create request here.

here is the link of  Plugin complete code.

http://1drv.ms/1MZBBzi

 

Thanks for visiting my blog.

Do some creative stuff in CRM  !!!  🙂

 

 

 

MS CRM dynamics with Firebase(using c#)

MS CRM dynamics with Firebase(using c#)

In my previous blog I wrote about how we can use firebase with CRM Dynamics in client side.
Here is the link MS CRM dynamics with Firebase (Using JS)

Today I am going to explain, how we can use Firebase with Plugin or Custom workflow in CRM using C#.

Let’s create a class library and add a class FirebaseWithCRM.cs

For communicate from CRM plugin to Firebase, we use FireSharp. It is a .net library for Firebase Rest Api.

c1

Next we add CRM core assemblies in our Class library project.

c2

We register this plugin on pre-operation event of Account Entity and on create Message ,so whenever new Account is create it ‘ll modify/add Account data in Firebase.

c3

Add new file as FirebaseHelper.cs that contain Push function

c4

c5

But our code is depends on some other DLL like Firesharp, Newtonsoft.Json , System.Net.Http , Microsoft.Threading.Task etc.

So Need to Merge all Dll’s into single one.

c6

What is ILMerge ?

ILMerge is a utility for merging multiple .NET assemblies into a single .NET assembly. It works on executables and DLLs alike and comes with several options for controlling the processing and format of the output.

For info refer this link

http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx

 

For Merging Dll’s there is a Nuget Package MSBuild.ILMerge.Task so using this package we can merge all DLL’s.

You can also refer this article for more understanding about DLL’s Merge by Nicolas Niwonski.

 

c7

 

c8

After Merging we can deployed this DLL using Plugin Registration tool on pre-operation event for Account Entity and on Create Message.

You can also register on Post-operation event by this we get Guid of account entity and store it in Firebase.

c11.PNG

That’s it Now we can test. 🙂

c9

C10

Now when we create New account it created in Firebase under Accounts Node.

For more synchronous and asynchronous function for Firesharp, please refer below link

https://github.com/ziyasal/FireSharp/wiki/v1-Docs

 

 

Thanks for visiting my blog.

Do some creative stuff in CRM  !!!  🙂

 

MS CRM dynamics with Firebase(using JS)

MS CRM dynamics with Firebase(using JS)

Real-time applications provide so much functionality across so many different types of applications. There’s Google Drive real-time editing, Twitter showing new tweets and so many more.

It’s always good to learn how to make these types of techniques by learning things like socket.io

Today I am going to tell how we can use firebase with MS dynamics CRM and make real time notification model for mobile\web users.

Like status Change ,Create ,Update or some other useful requests that we performed in CRM , we can easily integrate Firebase in all that condition and Sync important data with users .

What is Firebase?

Firebase is an API service to store and sync data in real-time. What this means is that you don’t have to worry about the backend server, database, or real-time component (socket.io). All of that is handled for you by Firebase.

Just grab data from Firebase, save data to Firebase, and Firebase will worry about saving, and also syncing across all connected devices/sites. Piece of cake!

firebase

Let’s integrate firebase in CRM  !!

Before writing any code first we need to make firebase API.

AppName

After successful creating of App we get one URL like https://XXXXXX.firebaseio.com 

For more info about firebase configuration and security Please refer this link

https://www.firebase.com/docs/

What we want is to receive notifications whenever the status of case records changed.

We are using https://mscrmdynamics.firebaseio.com/Cases AppUrl for all firebase operation.For demo you can also use it.

Let write some client side code(JS) on Save Event of Case Form.

Make new Web resource type Jscript and inside it write the code which communicate with firebase on Save Event of case form.

1

In above code I used RequireJs for Injecting Firebase and underscore Scripts. we can also use downloaded files and add them in form.

Whenever status changed we send a json body with Incident(case) attributes like Incident Id, Title, Status ,Owner to Firebase and save it.

We check all case (https://xxxxxx.firebaseio.com/Cases) snapshots on our Apps that sync with our system or mobile Phones. After getting data we made our logic for showing information through notifications.

OK let’s move to the next step, we’ll call the function when record updated with Event mode value  1 or 2 or 70.

For more Information about Save Event Argument please refer Below link

https://msdn.microsoft.com/en-us/library/gg509060.aspx

Before adding/creating new case, we need to check the existance of that case in firebase that this case is not already present and if it exist then we need to update it’s status only.

2.PNG

That’s it. Now we can Sync Case record status with firebase and we can use it’s data for many purposes of sales/services/marketing.

Lets save case with status On Hold .That reflects in firebase, show in below screens

4

5

On changing status of case, it’ll immediately reflects in firebase.

6

7

Here is the link for complete code and video.

http://1drv.ms/1UpKKXo

 

Thanks for visting my blog.

Do some creative stuff in CRM  !!!  🙂

 

 

Add Form Library on CRM Form using C# or javascript

Add Form Library on CRM Form using C# or javascript

Hello Everyone, Today I am going to tell how we can add form library on CRM form using C# or  JavaScript.

We want to add library on account form so for that I created one JavaScript web resources e.g.  am_sample for our demo purpose or you can add existing JS from CRM.

2

After that we add alert functionality inside this so we’ll found ourselves that our code is executed on onload of account form. We put our code inside self invoking function so it will show alert dialog on load of account form.(By using self invoking function we don’t need to define any function in Event Handlers)

here is demo link for self invoking function in JavaScript.

http://embed.plnkr.co/TSEL09/

1

3

In below screen we don’t see any library added on account form let’s write some code for adding file here 🙂

4

 

C# Code :

First we add one function for get form xml in which we passes logical name of Account entity as its parameter.

 

public Entity GetForm(string EntityLogicalname)
{
try
{
QueryExpression query = new QueryExpression(“systemform”)
{
Distinct = false,
ColumnSet = new ColumnSet(new[] { “name”, “formxml”, “objecttypecode” }),
Criteria =
{
Filters =
{
new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression(“objecttypecode”, ConditionOperator.Equal, EntityLogicalname),
new ConditionExpression(“type”, ConditionOperator.Equal, 2),
new ConditionExpression(“iscustomizable”, ConditionOperator.Equal, true),
new ConditionExpression(“formactivationstate”, ConditionOperator.Equal, 1)
}
}
}
}
};
return Service.RetrieveMultiple(query).Entities.FirstOrDefault();
}
catch (Exception)
{
throw;
}
}

This function return Entity with formxml attribute.

After that we need to add one more function that change current formxml of Account entity (which return from above function) with new JS that we need to add.

Below is the description of what we’re going to perform in our next funtion :

  • First we select Form node, and formLibraries inside it.
  • If formLibraries not found then we’ll create formLibraries xml node.
  • If formLibraries found then we’ll create Library element inside it with name, libraryUniqueId attributes.
  • After that we append this Library tag into formLibraries and update formxml attribute of Entity.

 

public void AddLibrary(Entity form, string libraryName, bool addFirst)
{
var formXml = form.GetAttributeValue<string>(“formxml”);
var formDoc = new XmlDocument();
formDoc.LoadXml(formXml);
var formNode = formDoc.SelectSingleNode(“form”);
if (formNode == null)
{
throw new Exception(“Expected node \”formNode\” was not found”);
}
var formLibrariesNode = formNode.SelectSingleNode(“formLibraries”);
var eventLibrary = formNode.SelectSingleNode(“events”);
if (formLibrariesNode == null)
{
formLibrariesNode = formDoc.CreateElement(“formLibraries”);
formNode.AppendChild(formLibrariesNode);
}
if(libraryName!=null)
{
var libraryNode = formLibrariesNode.SelectSingleNode(string.Format(“Library[@name='{0}’]”, libraryName));
if (libraryNode != null)
{
Console.WriteLine(“This library is already included in this form”);
}
var nameAttribute = formDoc.CreateAttribute(“name”);
var libraryUniqueIdAttribute = formDoc.CreateAttribute(“libraryUniqueId”);
nameAttribute.Value = libraryName;
libraryUniqueIdAttribute.Value = Guid.NewGuid().ToString(“B”);
libraryNode = formDoc.CreateElement(“Library”);
if (libraryNode.Attributes != null)
{
libraryNode.Attributes.Append(nameAttribute);
libraryNode.Attributes.Append(libraryUniqueIdAttribute);
}
if (formLibrariesNode.ChildNodes.Count > 0 && addFirst)
{
formLibrariesNode.InsertBefore(libraryNode, formLibrariesNode.FirstChild);
}
else
{
formLibrariesNode.AppendChild(libraryNode);
}
}
form[“formxml”] = formDoc.OuterXml;
Service.Update(form);
}

 

After that we’ll publish Account Entity.

public void PublishForm(Entity en)
{
var request = new PublishXmlRequest { ParameterXml = String.Format(“<importexportxml><entities><entity>{0}</entity></entities></importexportxml>”, en.GetAttributeValue<string>(“objecttypecode”)) };
Service.Execute(request);
}

 

Here is calling code

CrmConnection con = CrmConnection.Parse(“Url = https://xxxx.crm5.dynamics.com; Username=xyz@abc.onmicrosoft.com; Password=xyzxyz”);
IOrganizationService Service = new OrganizationService(con);
ScriptManage sc = new ScriptManage(Service);
var EntityName = sc.GetForm(“account”);
sc.AddLibrary(EntityName,”am_sample”, false);
sc.PublishForm(EntityName);

Now you can see JS file is added on account form!! 🙂

For more info about C# code, go through below link.

https://github.com/MscrmTools/XrmToolBox/blob/master/Plugins/MsCrmTools.FormRelated/FormLibrariesManager/AppCode/FormManager.cs

 

 

 

5

8

JS Code :

For using below code we need to add these file references.

  1. ClientGlobalContext.js.aspx
  2. jquery.min.js
  3. Sdk.Soap.min.js
function Getformxml  (EntityLogicalname) {
Sdk.jQ.setJQueryVariable($);
var SystemForm = new Sdk.Query.QueryExpression(“systemform”);
SystemForm.getDistinct();
SystemForm.addColumn(“name”);
SystemForm.addColumn(“formxml”);
SystemForm.addColumn(“objecttypecode”);
Sdk.Query.FilterExpression(Sdk.Query.LogicalOperator.And);
SystemForm.addCondition(“systemform”, “objecttypecode”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Strings([EntityLogicalname]))
SystemForm.addCondition(“systemform”, “type”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Ints([2]))
SystemForm.addCondition(“systemform”, “iscustomizable”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Booleans([true]))
SystemForm.addCondition(“systemform”, “formactivationstate”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Ints([1]))
FormxmlQuery = SystemForm;
return Sdk.jQ.retrieveMultiple(SystemForm).then(
function (ec) {
formRequestSuccesscall(ec);
})
new ErrorHandler(“An error occured “).getError(err);
}
function formRequestSuccesscall  (data) {
var $xml, $formtagxml, x = true, xml2 = ”;
if (data.getEntities().getCount() > 0) {
data.getEntities().forEach(function (n, i, arr) {
if (n.view().attributes[‘formxml’])
$xml = $($.parseXML(n.view().attributes[‘formxml’].value));
$formtagxml = $xml.find(“formLibraries”);
$($formtagxml).find(‘Library’).each(function () {
$.each(this.attributes, function (i, attrib) {
if (attrib.name == “name”) {
if (attrib.value == “Content_/scripts/wfHover.js”) {
console.log(‘already add on form!!’);
x = false;
}
}
});
});
if (x) {
if ($formtagxml.length == 0) {
xml2 += ‘<formLibraries><Library name=“am_sample” libraryUniqueId=”‘ + guid() + ‘” /></formLibraries>’;
$formtagxml = $($.parseXML(xml2)).find(“formLibraries”);
$xml.find(“form”).append($($.parseXML(xml2)).find(“formLibraries”));
} else {
$formtagxml.append(‘<Library name=“am_sample” libraryUniqueId=”‘ + guid() + ‘” />’)
}
var oSerializer = new XMLSerializer();
//clone.attributes[‘formxml’].value = oSerializer.serializeToString($xml[0]);
n.setValue(“formxml”, oSerializer.serializeToString($xml[0]));
Sdk.jQ.update(n).then(
function (id) {
// console.log(id);
publishXML(entityLogicalname);
})
}
})
}
}
function publishXML (entityName) {
var context = Xrm.Page.context;
var serverUrl = (context.getServerUrl) ? context.getServerUrl() : context.getClientUrl();
var Publishxml = “”;
Publishxml += “<s:Envelope xmlns:s=\”http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\”>”;
Publishxml += ” <s:Body>”;
Publishxml += ” <Execute xmlns=\”http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts\/Services\” xmlns:i=\”http:\/\/www.w3.org\/2001\/XMLSchema-instance\”>”;
Publishxml += ” <request i:type=\”b:PublishXmlRequest\” xmlns:a=\”http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts\” xmlns:b=\”http:\/\/schemas.microsoft.com\/crm\/2011\/Contracts\”>”;
Publishxml += ” <a:Parameters xmlns:c=\”http:\/\/schemas.datacontract.org\/2004\/07\/System.Collections.Generic\”>”;
Publishxml += ” <a:KeyValuePairOfstringanyType>”;
Publishxml += ” <c:key>ParameterXml<\/c:key>”;
Publishxml += ” <c:value i:type=\”d:string\” xmlns:d=\”http:\/\/www.w3.org\/2001\/XMLSchema\”>&lt;importexportxml&gt;&lt;entities&gt;&lt;entity&gt;” + entityName + “&lt;\/entity&gt;&lt;\/entities&gt;&lt;\/importexportxml&gt;<\/c:value>”;
Publishxml += ” <\/a:KeyValuePairOfstringanyType>”;
Publishxml += ” <\/a:Parameters>”;
Publishxml += ” <a:RequestId i:nil=\”true\” \/>”;
Publishxml += ” <a:RequestName>PublishXml<\/a:RequestName>”;
Publishxml += ” <\/request>”;
Publishxml += ” <\/Execute>”;
Publishxml += ” <\/s:Body>”;
Publishxml += “<\/s:Envelope>”;
var req = new XMLHttpRequest();
req.open(“POST”, serverUrl + “/XRMServices/2011/Organization.svc/web”, true);
// Responses will return XML. It isn’t possible to return JSON.
req.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
req.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
req.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute&#8221;);
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status === 200) {
}
} else {
alert(“An error occurred ” + req.statusText);
}
}
req.send(Publishxml);
}

here is caling code for JS

Getformxml  (“account”);

 

Hope you will like this blog and Thank you for visiting my blog 🙂