Wednesday, September 3, 2014

CRM 2013 – Plugin Registration Error

Error: Plug-in assembly does not contain the required types or assembly content cannot be updated.

This error was occurring when I try to update a Plugins assembly using Update Assembly window of the CRM SDK PluginRegistration.exe. I was able to register this same assembly couple of hours ago and now without major changes I’m unable to register it.

Problem turned out to be that another developer has updated the same plugin assembly with extra plugin classes added to the assembly. I was getting this error; since I did not have those extra plugins in the assembly I was trying register.

This is something to note about when registering plugins for the testing purpose in a shared environment without check-in the code.

Full error I got:
Unhandled Exception:
System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Plug-in assembly does not contain the required types or assembly content cannot be updated.
Detail: <OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ErrorCode>-2147204725</ErrorCode>
  <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Plug-in assembly does not contain the required types or assembly content cannot be updated.</Message>
  <Timestamp>2014-09-03T08:17:30.7702502Z</Timestamp>
  <InnerFault>
    <ErrorCode>-2147204725</ErrorCode>
    <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>Plug-in assembly does not contain the required types or assembly content cannot be updated.</Message>
    <Timestamp>2014-09-03T08:17:30.7702502Z</Timestamp>
    <InnerFault i:nil="true" />
    <TraceText i:nil="true" />
  </InnerFault>
  <TraceText i:nil="true" />
</OrganizationServiceFault>

Server stack trace:
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Microsoft.Xrm.Sdk.IOrganizationService.Update(Entity entity)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.UpdateCore(Entity entity)
   at Microsoft.Crm.Tools.PluginRegistration.RegistrationHelper.UpdateAssembly(CrmOrganization org, String pathToAssembly, CrmPluginAssembly assembly, PluginType[] type)
   at Microsoft.Crm.Tools.PluginRegistration.PluginRegistrationForm.btnRegister_Click(Object sender, EventArgs e)

Monday, June 2, 2014

Simple JQuery Tooltip Plugin for SharePoint Page Content Sections – Colortip

Tooltip control is a great way to display additional information in web sites without making the web page larger and improving user experience and usability.

There are so many jQuery plugins that we can find, like in this list. Most of them require us to add supporting file like JS, CSS and images to the developing web site in order to use the tooltip control.

One of the common approaches used in jQuery plugins is to call to a JavaScript function, passing few parameters including tooltip content whenever we want to display a tooltip. Those tooltip plugins won’t much helpful when comes to use them in SharePoint Page Content sections since some html segments like scripts will get striped in page content sections upon saving.

We can use either SharePoint 2013 script editor webpart or Content Editor webpart with a referring text file as an alternative. But neither of them gives the flexibility of editing content as Page Content sections provide.

JQuery plugins like Colortip comes in handy in this type of situation.

Step 1:
Download ColorTip plugin form the tutorialzine site. Upload colortip-1.0-jquery.css and colortip-1.0-jquery.js file to a document library. There are no images to be uploaded.

Step 2:
Add the following script section in the page using a Script Editor webpart or any other mechanism. This includes the references to the plugin resources (update as necessary), popup trigger and additional condition to prevent plugin from running/modifying content in edit mode of the SharePoint page.

<scriptsrc="//code.jquery.com/jquery-1.11.0.min.js"></script>
<scripttype="text/javascript"src="/_catalogs/masterpage/colortip-1.0-jquery.js"></script>
<linktype="text/css"href="/_catalogs/masterpage/colortip-1.0-jquery.css"rel="stylesheet">
 
<script>
$(document).ready( function() {
   var inEditMode = document.forms[MSOWebPartPageFormName].MSOLayout_InDesignMode.value;
   if(inEditMode !="1") {
  $( '.mypopup[title]' ).colorTip({ color: 'blue'});
  }
});
</script>

Step 3:
Include anchor tags where the popup needs to display. Title is the popup text. Class ‘mypopup’ is used to trigger the popup.

Lorem Ipsum is<atitle="Popup on dummy text"class="blue mypopup">simply dummy text</a>of the printing and typesetting industry.

This is how it looks: 



Note: For SharePoint wiki pages, in order to find if the page is in Edit mode from JavaScript, use following condition:

var inEditModeWiki = document.forms[MSOWebPartPageFormName]._wikiPageMode.value;
if(inEditModeWiki =="Edit")
{
  // trigger popup
  $( '.mypopup[title]').colorTip({ color:'blue'});
}

Tuesday, April 22, 2014

MVC 4 WebGrid – Filtering on Selected Columns with DropDownLists in Header

This example demonstrates a MVC 4 WebGrid implementation to display subsets of data filtered using drop-down lists embedded in grid column headers. Example grid has two columns 'Code' and 'Status'.  A filter dropdown list is added in the 'Status' column header, which contains all the unique values within the column. This filter dropdown list is populated using ViewBag and filtering is happening on its item change postback. A postback is forced on onchange event of the drop-down list using jQuery.

WebGrid control header doesn't support inserting HTML directly. Therefore this implementation uses MvcHtmlString class and simple string replace to insert a dropdown control to the header. I use a placeholder called '{StatusFilter}' in the header initially and then replace that with the HTML markup for the dropdown list.

View:

@model hub.Models.MyCampModel

@{
  if (Model != null && Model.MyCampaigns != null 
          && Model.MyCampaigns.Count() > 0)
  {
   using (Html.BeginForm())
   {       
    var grid = new WebGrid();
    grid.Bind(Model.MyCampaigns, rowCount: Model.MyCampaigns.Count());
    grid.Pager(WebGridPagerModes.All);
   
    @MvcHtmlString.Create(grid.GetHtml(
     tableStyle: "main_table_wrapper",
      alternatingRowStyle: "descending",
     rowStyle: "ascending",
     columns: grid.Columns(
      grid.Column("StatusCode", header: "Code"),
      grid.Column("Status", header: "Status {StatusFilter}"))  
    ).ToString().Replace("{StatusFilter}", Html.DropDownList("RequestStatusFilter", ViewBag.ReqStatusOptions as SelectList, "All", new { onchange = "$(this).closest('form').submit();" }).ToString()));
   }   
  } 
}


Post action to get filtered results:

[HttpPost]
public ActionResult CampaignList(string requestStatusFilter = "")
{
  MyCampModel model = new MyCampModel();
  model.MyCampaigns = new List<MyCampaign>();
  var myRecs = db.MyCampaigns.Where(itm => (string.IsNullOrEmpty(requestStatusFilter) || itm.MyCampaignStatus.Name == requestStatusFilter));
  foreach (var rec in myRecs)
  {
    MyCampaign myCamp = new MyCampaign() { StatusCode = rec.Code, Status = rec.MyCampaignStatus.Name };
    model.MyCampaigns.Add(myCamp);
  }
  return View(model);
  ViewBag.ReqStatusOptions = new SelectList( // logic to select statuses.
}

Here the drop-down list is rendered in addition to the header text. Therefore sorting by column headers is also available in the same time.

Wednesday, April 16, 2014

SharePoint 2013 User Welcome Control with Client-Side Scripting

This is an example of using SharePoint 2013 JSOM to get the current logged in user's account information. This example uses SP.UserProfiles.PeopleManager object comes in SP.UserProfiles.js file and greets the currently logged on user saying “Hi, first name, last name [picture]”.

In order to load the profile picture, I used userphoto.aspx page resides in the SharePoint layouts folder. Two parameters passed for that are the picture size and account name (user email address in SharePoint online).

This code looks for a DIV element with the id "userDetails" on the page and will place the generated markup in it.

var TestApp = TestApp || {};

TestApp.UserWelcome = function (TestApp) {
 var context;
 var user;
 var personProperties;

 var getCurrentUser = function () {
  context = SP.ClientContext.get_current();
  user = context.get_web().get_currentUser();
  context.load(user);
  context.executeQueryAsync(getUserProperties, onGetUserFailed);
 };

 var onGetUserFailed = function (sender, args) {
  if ($('#userDetails').length) {
   $get("userDetails").innerHTML = "Get current user failed: " + args.get_message();
  }
 };

 var getUserProperties = function () {
  var targetUser = user.get_loginName();
  var peopleManager = new SP.UserProfiles.PeopleManager(context);
  personProperties = peopleManager.getPropertiesFor(targetUser);
  context.load(personProperties);
  context.executeQueryAsync(onUserPropSuccess, onUserPropFail);
 };

 var onUserPropSuccess = function () {
  var userPhoto = "/_layouts/15/userphoto.aspx?size=s&accountname=" + currentUser.get_email();
  var displayName = personProperties.get_displayName();
  displayName = displayName.replace(/\(.*\)/g, '');

  var detailHtml = '<div>Hi, ' + displayName + '<img src="' + userPhoto + '" /></div>';

  if ($('#userDetails').length) {
   $get("userDetails").innerHTML = detailHtml;
  }
 };

 var onUserPropFail = function (sender, args) {
  if ($('#userDetails').length) {
   $get("userDetails").innerHTML = "Error: " + args.get_message();
  }
 };

 return {
  getCurrentUser: getCurrentUser
 };
}();

$(document).ready(function () {
 var initWelcomeUser = function () {
  TestApp.UserWelcome.getCurrentUser();
 };

 ExecuteOrDelayUntilScriptLoaded(initWelcomeUser, 'SP.UserProfiles.js');
});

Additionally, namespaces are used in this example in order to reduce the number of objects and functions that are added to the global scope of the application.