How to make MS CRM 2011 ADX Studio Customer Portal MultiLingual

I had some issues making the ADX Studio Customer Portal multilingual.
First I tried having a duplicate website with duplicatie site markers and all… this was way too much.

I solved it just a little easier… use as much translations from CRM as possible… since there are a whole load of translations available when you install a language pack.
In this article I use Dutch and English.

First let me show you the markup for a page with a grid view displaying CRM data.

asp:GridView
ID=”GridView1″ runat=”server” CssClass=”cases” AutoGenerateColumns=”False”
>


<Columns>

    <asp:TemplateField
HeaderText=”Study”>

        <HeaderTemplate >

            <asp:Literal
ID=”ltrHeader1″ runat=”server” Text=’<%# GetHeaderText(“cbr_study”) %>‘></asp:Literal>

        </HeaderTemplate>

        <ItemTemplate>

        <asp:HyperLink
ID=”hlUrl” runat=”server” NavigateUrl=’<%# EducationUrl( (Guid)Eval(“cbr_educationid”) ) %>

Text=’<%# Eval(“cbr_study”)%>
/>

        </ItemTemplate>

    </asp:TemplateField>

    <asp:TemplateField
HeaderText=”Institution”>

        <HeaderTemplate >

            <asp:Literal
ID=”ltrHeader2″ runat=”server” Text=’<%# GetHeaderText(“cbr_institutionid”) %>‘></asp:Literal>

        </HeaderTemplate>

        <ItemTemplate>

            <%#
ContentUtility.FormatCrmEntityReference(Eval(“cbr_institutionid”) as
CrmEntityReference) %>

            <%# Eval(“cbr_institute_not_listed”)%>

        </ItemTemplate>

    </asp:TemplateField>

    <asp:TemplateField
HeaderText=”Start Date”>

        <HeaderTemplate >

            <asp:Literal
ID=”ltrHeader3″ runat=”server” Text=’<%# GetHeaderText(“cbr_startdate”) %>‘></asp:Literal>

        </HeaderTemplate>

        <ItemTemplate>

            <%# GetLocalDate(Eval(“cbr_startdate”) as
DateTime?) %>

        </ItemTemplate>

    </asp:TemplateField>

    <asp:TemplateField
HeaderText=”End Date”>

        <HeaderTemplate >

            <asp:Literal
ID=”ltrHeader4″ runat=”server” Text=’<%# GetHeaderText(“cbr_graduationdate”) %>‘></asp:Literal>

        </HeaderTemplate>

        <ItemTemplate>

            <%# GetLocalDate(Eval(“cbr_graduationdate”) as
DateTime?)%>

        </ItemTemplate>

    </asp:TemplateField>

    </Columns>

</asp:GridView>

 

In the code behind of this page, you´ll need the method GetHeaderText… taking the CRM field name as only argument..

In the Session-object I stored MyLanguageCode… holding the 1033 or 1043… whatever the user picked as display language.

 

protected
string GetHeaderText(string crmField)

{

return
ContentUtility.GetLocalizedLabel(XrmContext, crmField, “cbr_education”, (int)Session[“MyLanguageCode”]);

}

 

I add in the ContentUtility class a two methods … GetLocalizedLabel and GetLocalizedPickListValues

 

public
static
string GetLocalizedLabel(XrmServiceContext context, string crmField, string crmEntity, int LanguageCode)

{


RetrieveAttributeRequest CrmAttributeRequest = new
RetrieveAttributeRequest();

CrmAttributeRequest.EntityLogicalName = crmEntity;

CrmAttributeRequest.LogicalName = crmField;

 


RetrieveAttributeResponse response = (RetrieveAttributeResponse)context.Execute(CrmAttributeRequest);

 


if (response.AttributeMetadata.DisplayName.LocalizedLabels.Where(l => l.LanguageCode == LanguageCode).Any() == true)

{


return response.AttributeMetadata.DisplayName.LocalizedLabels.Where(l => l.LanguageCode == LanguageCode).SingleOrDefault().Label;

}

 


// Otherwise return the default label


return response.AttributeMetadata.DisplayName.LocalizedLabels.Single().Label;

}

 

public
static
ListItemCollection GetLocalizedPickListValue(XrmServiceContext context, string crmField, string crmEntity, int LanguageCode)

{


RetrieveAttributeRequest CrmAttributeRequest = new
RetrieveAttributeRequest();

CrmAttributeRequest.EntityLogicalName = crmEntity;

CrmAttributeRequest.LogicalName = crmField;

 


RetrieveAttributeResponse response = (RetrieveAttributeResponse)context.Execute(CrmAttributeRequest);


PicklistAttributeMetadata picklist = (PicklistAttributeMetadata)response.AttributeMetadata;

 


ListItemCollection ddItems = new
ListItemCollection();


string _localizedlabel = string.Empty;

 


foreach (OptionMetadata option in picklist.OptionSet.Options)

{


if (option.Label.LocalizedLabels.Where(l => l.LanguageCode == LanguageCode).Any() == true)

{

_localizedlabel = option.Label.LocalizedLabels.Where(l => l.LanguageCode == LanguageCode).SingleOrDefault().Label;

}


else

{

_localizedlabel = option.Label.LocalizedLabels.Single().Label;

}

 

ddItems.Add(new
ListItem(_localizedlabel, option.Value.ToString()));

}


return ddItems;

}


 

Advertisements

West Coast Trail 2009 Video

By all means about two years overdue… but finished after all.
Great hike, people…! Y’all should embark on a journey like this.

Hell… it was great.. let’s do that again.

 

Next fieldtrip… Larapinta trail … starting from Alice Springs, Australia.
A mere 234 km hike… check out the video’s on www.larapintatrail.com

JQuery Mobile Web Client on SharePoint – The Source Code

After numerous requests of publishing the source code of my demo as showed before in JQuery Mobile Web Client on SharePoint enabled I have decided to do so.
You lucky bastards… from the goodness of my hart… and for the good of community… and for world peace.

Please be aware that the solution has not left the alpha stage.
Download the code here … SharePoint4Mobile… this is a .DOC file, cause WP didn’t allow me to upload an archive.
So …  rename the download from .DOC to .ZIP and you’ll be all set.

Things you wanna know:

  • It was developed against SharePoint 2007 in an BPOS environemnt… so you come across some BPOS specific tag in the ASPX  pages.
  • It is mainly JavaScript, cause of the BPOS SharePoint 2007 restrictions… you can make this work using .NET better and faster I’ll bet.
  • An important component I used was the 2008 SPAPI by Darren Johnstone (http://darrenjohnstone.net).

Good luck and feel free to let me know what the experiences were with this piece of code.
I’m allways open for feedback.

 

You may wonder why I stopped developing futher.
This has a fairly simple reason.

My goal was developing an App that enabled a user on at least iPhone or iPad to not just Open and Edit MS Office files… but Save modified files back to SharePoint.
This last feature … saving changed files back to SharePoint – is not possible with iPhone or iPad.
Read one of many articles stating what Apple had NOT done to to leverage SharePoint functionality with an iPhone or iPad.
http://blog.wortell.nl/jasper/the-ipad-and-sharepoint-%E2%80%93-what-can-and-can%E2%80%99t-you-do-%E2%80%93-part-1/

 

Pass a ListItemId to SharePoint workflow

In SharePoint Designer 2007 open the page where an action is needed.

Right click the control the wher you want to start the workflow from… click Form Actions.

Add Custom Action and click Settings and the Workflow Wizard will start.

Click Variables and add a variable called something like MyListItemId.

Finish the workflow and see that the code around your control will be updated somewhat like this:

<a href=”javascript: {ddwrt:GenFireServerEvent(‘__workflowStart={{FA532C23-6F80-4266-868D-1EBC219A7E11},New,{8F0B8599-4B45-421A-A4A2-9BD2817078DE},}’)}”>
//MyControl//
</a>

 

Here’s what you need to do to pass the variable MyListItemId

<a href=”javascript: {ddwrt:GenFireServerEvent(concat(‘__workflowStart={{FA532C23-6F80-4266-868D-1EBC219A7E11},New,{8F0B8599-4B45-421A-A4A2-9BD2817078DE},MyListItemId=’,@ID, ‘}’))}”>
//MyControl//
</a>

 

EASY AS PIE

The length of the ‘filteringattributes’ attribute of the ‘sdkmessageprocessingstep’ entity exceeded the maximum allowed length of ‘100’

 

While developing a plug-in for CRM 4.0 triggers can be set when the plug-in can be set off using the Plugin Registration Tool.

When too many triggers are selected the following error will occur.

Unhandled Exception: System.Web.Services.Protocols.SoapException: Server was unable to process request.
Detail:

A validation error occurred. The length of the ‘filteringattributes’ attribute of the ‘sdkmessageprocessingstep’ entity exceeded the maximum allowed length of ‘100′.
Platform

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at PluginRegistrationTool.CrmSdk.CrmService.Create(BusinessEntity entity)
at PluginRegistrationTool.RegistrationHelper.RegisterStep(CrmOrganization org, CrmPluginStep step)
at PluginRegistrationTool.StepRegistrationForm.btnRegister_Click(Object sender, EventArgs e)

 

What is de filteringattribute attribute?

While registering a plugin trigger in the CRM database the [<OrganizatioName>_MSCRM].[SdkMessageProcessingStepBase] table is updated.
For every plugin step a record is created in this table.
One of the attributes in this table is

[FilteringAttributes] [nvarchar](256)
NULL

During the registration of the plugin step the MetadataSchema is checked and validated a.o. the MaxLength of this attribute.

SELECT Maxlength
FROM [<OrganizationName>_MSCRM].[MetadataSchema.Attribute]
wHERE name =’filteringattributes’

By default the result of this query will be ‘100’. Strange of course since the database will allow to insert nvarchar strings up to 256 characters.

A solution could be

Update [<OrganizationName>_MSCRM].[MetadataSchema.Attribute
SET Maxlength = 256
where name =’filteringattributes’

If the MaxLength is set to more then 256 a SQL Error may occur since data will be truncated.

Note: After an update IISReset /noforce is required.

Note: Above customization is unsupported and you must take precautionary measure to make sure to avoid any problem with CRM system.

Multiple SSL secured site on IIS7

Let’s say that you have

  • an IIS7 webserver running
  • Microsoft Dynamics CRM is running on your webserver
  • And there’s another site running on the same webserver.
  • And both site are internet facing and need to be SSL secured

IIS Management Console doesn’t give you the possibility to do that.
You used to do this in IIS6 using adsutil.vbs

cscript.exe adsutil.vbs set /w3svc/<replace with your site id>/SecureBindings “:443:www.domain1.com”

IIS7 support is now delivering this option:

C:\Windows\System32\inetsrv>appcmd set site /site.name:”<Replace with your site name>” /+bindings.[protocol=’https’,bindingInformation=’*:443:<replace with your url>’]

Good configin’