How to replace plain URLs with links? (C# and Javascript)

Idea: In Suppo project we want to replace URLs in chat conversations by HTML links. Yes the first thing was to use google to find some recommendations or regular expressions BUT: On stackoverflow in article http://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links is written:

“First off, rolling your own regexp to parse URLs is a terrible idea. You must imagine this is a common enough problem that someone has written, debugged and tested a library for it, according to the RFCs. URIs are complex  … and there is multiple recommended libraries in Javascript (expect similar libraries in C#) like linkifyjs, anchorme.js, autolinker.js … OK so where is the problem?

The problem for me is that all of this libraries are huge … >30KB minified.

Why?

Because we are developing livechat window (Suppo) which is attached to every page of our clients and +30KB of javascript code is not acceptable when our solution has 63KB at all (included the core of jQuery library)

So what next?

Back to beginning and compose simple regular expression (is not so important to work on every URLs … suffice many of them)

C#:

public static string Linkify(this string text)
{
    // www|http|https|ftp|news|file
    text = Regex.Replace(
        text,
        @"((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9-]+\.[a-z0-9\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])",
        "<a href=\"$1\" target=\"_blank\">$1</a>",
        RegexOptions.IgnoreCase)
        .Replace("href=\"www", "href=\"http://www");

    // mailto
    text = Regex.Replace(
        text,
        @"(([a-zA-Z0-9_\-\.])+@[a-zA-Z\ ]+?(\.[a-zA-Z]{2,6})+)",
        "<a href=\"mailto:$1\">$1</a>",
        RegexOptions.IgnoreCase);

    return text;
}

Javascript:

// www|http|https|ftp|news|file
text = text.replace(
    /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9-]+\.[a-z0-9\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])/gim,
    '<a href="$1" target="_blank">$1</a>');

// mailto
text = text.replace(
    /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim,
    '<a href="mailto:$1">$1</a>');

It’s simple: first part of code find www|http|https|ftp|news|file and replace it by <a href=”http(s):// and second part find email address and replace it by <a href=”mailto::.
That is all and it's less than 1KB of code.

Error 404 for .axd files (WebResource.axd & ScriptResource.axd)

If you’ve got a similar error as on following image:

ScriptResource.axd error 404

that your script resources related with components like UpdatePanel or ScriptManager are not working correctly, think about routing. It may by caused by many other reasons as wrote on similar blog post across the web e.g. wrong version of related System.Web.Extensions.dll or wrong IIS configuration or incorrect handlers defined in web.config. BUT when you are working in hybrid ASP.NET application where are .aspx + .chtml pages together (old Web Forms and new MVC) the problem will probably be routing.

Check and correct your RouteConfig.cs as on following image:

Ignore .axd Resources in RouteConfig.cs

public static void RegisterRoutes(RouteCollection routes)
{
	routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
	
	// Default MVC routing
    routes.MapRoute(
       name: "D1",
       url: "{controller}/{action}/{id}",
       defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
    );
}

 

Enjoy!

Suppo.biz – testovacia prevádza spustená

Doménu Suppo.biz už nejaký ten mesiac máme obsadenú, no len pred pár týždňami sme spustili testovaciu prevádzku pre vybraných zákazníkov na subdoménach ako: turingion.suppo.biz, fincentrum.suppo.biz … no až teraz sme updatli stránku turingion.com, konkrétne časť o produkte eShop, kde už LiveChat nie je ako plánovaná novinka (vo vývoji), ale je plne funkčný a pripravený pre nových zákazníkov v balíčku Business. Samozrejmosťou je doplnenie tejto funkcionality všetkym existujúcim zákazníkom, ktorý o tento skvelý nástroj budú mať záujem. Jeden ScreenShot z aplikácie:

image

Customizácia jQuery.Validate pre bootstrap

Názov tohto príspevku som prepisoval snáď 10 krát. Pravdepodobne nie je podľa neho jasné o čo pôjde, tak to skúsim objasniť: Ak chcete validovať formulárové prvky v ASP.NET MVC a na ich design používate Bootstrap, a súčasne na validáciu na klientskej strane používate javascriptovú knižnicu jQuery.Validate tak sa určite dostanete do rovnakej situácie ako ja. jQuery Validate pridáva css triedy s názvom “input-validation-error” a “valid” priamo do input elementu (alebo iných elementov formulára) čo je síce pekné, ale nechce sa mi dizajnovať niečo, čo už bootstrap vyriešil za mňa. Ak chceme použiť korektne knižnicu bootstrap, tak tá to potrebuje mať povedané v inom formáte. (Formát validného/nevalidného prvku nájdete na bootstrap stránke v sekcii Validation states). Čo s tým? ideálne toto:

jQuery.validator.setDefaults({
    highlight: function (element, errorClass, validClass) {
        if (element.type === 'radio') {
            this.findByName(element.name).addClass(errorClass).removeClass(validClass);
        } else {
            $(element).addClass(errorClass).removeClass(validClass);
            $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
        }
    },
    unhighlight: function (element, errorClass, validClass) {
        if (element.type === 'radio') {
            this.findByName(element.name).removeClass(errorClass).addClass(validClass);
        } else {
            $(element).removeClass(errorClass).addClass(validClass);
            $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
        }
    }
});

Upraviť metódy highligh a unhighligh uvedeným spôsobom. (aby pridávali triedy has-success a has-error do nadradeného DIV elementu s triedou form-group).

Microsoft Dynamics CRM 2015 – Javascript API – Utility

Piata časť zo série Microsoft Dynamics CRM – Javascript API zaoberajúca sa prácou s dialógmi entít – in english as all posts in this category.

These functions are available in every application page that supports scripting. You can use them in form scripts or in ribbon commands. For HTML web resources, they are available when you include the ClientGlobalContext.js.aspx page (full specification you can find on msdn network):

1. Dialogs - There are two types of dialogs: alertDialog and confirmDialog. These are included for use with scripts that will work with Microsoft Dynamics CRM for tablets. CRM for tablets will not allow the use of JavaScript functions that block the flow of code such as window.alert and window.confirm. Use these methods in place of those methods in case you need to display a message to the user. They key difference is that these methods will not block code until a user closes them. They contain a callback function parameter to indicate what code should be executed depending on the user’s response. This method is only available in Update mode.

Xrm.Utility.alertDialog('message', onCloseCallback);

Xrm.Utility.confirmDialog('message', yesCloseCallback, noCloseCallback);

 
2. Entity Form - Opens an entity form for a new or existing entity record using the options you set as parameters.

Xrm.Utility.openEntityForm(name, id, parameters, windowOptions);

Examples:

Xrm.Utility.openEntityForm("account");
Xrm.Utility.openEntityForm("account","A85C0252-DF8B-E111-997C-00155D8A8410");
var parameters = {};
parameters["formid"] = "b053a39a-041a-4356-acef-ddf00182762b";
parameters["name"] = "Test";
parameters["telephone1"] = "(425) 555-1234";
Xrm.Utility.openEntityForm("account", null, parameters);
var windowOptions = {
 openInNewWindow: true
};
Xrm.Utility.openEntityForm("account",null,null,windowOptions);

 
3. Quick Create Form - For Microsoft Dynamics CRM Online 2015 Update 1 or later use this function to open a new quick create form. You can use this function to set default values using attribute mappings or for specific attributes. If the user saves the record, you can capture a reference to the record created.

Xrm.Utility.openQuickCreate(callback,entityLogicalName,createFromEntity,parameters);

Example:

var thisAccount = {
 entityType: "account",
 id: Xrm.Page.data.entity.getId()
};
var callback = function (lookup) {
 console.log("Created new " + lookup.entityType + " named '" + lookup.name + "' with id:" + lookup.id);
}
var setName = { name: "Child account of "+ Xrm.Page.getAttribute("name").getValue()};
Xrm.Utility.openQuickCreate(callback, "account", thisAccount, setName);


4. Web Resource - Opens an HTML web resource.

Xrm.Utility.openWebResource(webResourceName,webResourceData,width, height)

Examples:

Xrm.Utility.openWebResource("new_webResource.htm");
Xrm.Utility.openWebResource("new_webResource.htm", null, 300,300);
var customParameters = encodeURIComponent("first=First Value&second=Second Value&third=Third Value");
Xrm.Utility.openWebResource("new_webResource.htm",customParameters);
Xrm.Utility.openWebResource("new_webResource.htm?typename=account&userlcid=1033");

Microsoft Dynamics CRM 2015 – Javascript API – Section

Štvrtá časť zo série Microsoft Dynamics CRM – Javascript API zaoberajúca sa prácou so sekciami na formuláry – in english as all posts in this category.  

The CRM javascript API contains methods to manage how it appears as well as accessing the tab that contains the section. Here is most usefull methods (full specification you can find on msdn network) :

1. Section – sections is sub-collection under tab object as describes following code:

var tabObj = Xrm.Page.ui.tabs.get('tabName');

var sectionObj = tabObj.sections.get('sectionName');


2. Label - Use the getLabel and setLabel methods to retrieve or change the label for the section.

sectionObj.getLabel()
sectionObj.setLabel(string)


3. Visibility - Use the getVisible and setVisible methods to check whether the section is visible or hide and show the section.

sectionObj.getVisible()
sectionObj.setVisible(boolean)

Microsoft Dynamics CRM 2015 – Javascript API - Tab

Tretia časť zo série Microsoft Dynamics CRM – Javascript API zaoberajúca sa prácou s tabmi na formuláry – of course in english as all posts in this category.

The CRM javascript API for manipulation with the form’s tab is represented by namespace called Xrm.Page.ui.tabs. Tabs is collection which contains all tab objects on the form. Here is most usefull methods for manipulation with tabs (full specification you can find on msdn network) :

1. Tab – Particular tab object you can obtain by following code:

var tabObj = Xrm.Page.ui.tabs.get('tabName');


2. Display state - Use the getDisplayState and setDisplayState methods to determine whether the tab is collapsed or to collapse and expand the tab.

tabObj.getDisplayState()
tabObj.setDisplayState(state)

Valid state argument values are : 'collapsed' and 'expanded'.

3. Label - Use the getLabel and setLabel methods to determine the label for the tab or to hide and show the tab label.

tabObj.getLabel()
tabObj.setLabel(string)


4. Focus - Sets the focus on the tab.

tabObj.setFocus()


5. Visible - Use the getVisible and setVisible methods to determine the tab is visible or to hide and show the tab.

tabObj.getVisible()
tabObj.setVisible(boolean);


6. Sections - The sections collection provides access to sections within the tab. See Collections (client-side reference) for information about methods to access the sections in the collection. About manipulation with sections we will write next post, but here is simple code for obtaining specific section in specific tab:

tabObj.sections.get('sectionName')

Microsoft Dynamics CRM 2015 – Javascript API - Form

Druhá časť zo série Microsoft Dynamics CRM – Javascript API zaoberajúca sa prácou s prvkami formulára. Táto téma by po správnosti mala predchádzať prvej kapitole o práci s kontrolkami, pretože ide o náhľad na metody pracujúce s celkovo formulárom resp. entitou – of course in english as previous post.

The CRM javascript API for manipulation with the entity’s form (ribbon) is represented by namespace called Xrm.Page.ui. It contains properties and methods to retrieve information about the user interface as well as collections for several subcomponents of the form. Here is top 5 usefull methods (full specification you can find on msdn network) :

1. Close - Method to close the form.

Xrm.Page.ui.close()


2. Current Control - Method to get the control object that currently has focus on the form. Web Resource and IFRAME controls are not returned by this method.

Xrm.Page.ui.getCurrentControl()

 
3. Form Type - Method to get the form context for the record.

Xrm.Page.ui.getFormType()

Method returns the number value from following table lists:

Value Form Type

0

Undefined

1

Create

2

Update

3

Read Only

4

Disabled

5

Quick Create (Deprecated)

6

Bulk Edit

11

Read Optimized (Deprecated)

 
4. Form Notification - Use setFormNotification to display form level notifications and clearFormNotification to remove notifications.

Xrm.Page.ui.clearFormNotification(messageId)

Use this method to display form level notifications. You can display any number of notifications and they will be displayed until they are removed using clearFormNotification. The height of the notification area is limited so each new message will be added to the top. Users can scroll down to view older messages that have not yet been removed.

Xrm.Page.ui.setFormNotification(message, level, messageId);

Level is string variable with following values :

  • ERROR : Notification will use the system error icon.
  • WARNING : Notification will use the system warning icon.
  • INFO : Notification will use the system info icon.


5. Refresh Ribbon - Method to cause the ribbon to re-evaluate data that controls what is displayed in it.

Xrm.Page.ui.refreshRibbon()


Little tip to the end: Specify constants to your code (in base or common Javascript library) for the Form Types. Example: FormType_Create = 1.

Microsoft Dynamics CRM 2015 – Javascript API - Controls

Prvá časť zo série Microsoft Dynamics CRM – Javascript API zaoberajúca sa prácou s kontrolkami resp. vlastnosťami entít – in english for search engines.

The CRM javascript API for manipulation with the controls is represented by namespace called Xrm.Page. The control object provides methods to change the presentation or behavior of a control and identify the corresponding attribute. You can access controls using the following collections: Xrm.Page.ui.controls, but the most usefull shortcut method to access the specific control/attribute is Xrm.Page.getControl(‘attributeName’) method. Under the selected control, you can use folowing methods (we are specifiing only most common/usefull methods; full specification you can find on msdn network):

1. Disabled - Enable or disable the control:

Xrm.Page.getControl('attributeName').setDisabled(bool)


2. Attribute - Returns the particular attribute value – usefull for lookup attribute :

Xrm.Page.getControl('attributeName').getAttribute()


3. Label - Get or change the label for a control using the getLabel and setLabel methods.

Xrm.Page.getControl('attributeName').getLabel()
Xrm.Page.getControl('attributeName').setLabel(label)

 
4. Notification - Use setNotification to display a notification about the control and clearNotification to remove it. Display a message near the control to indicate that data isn’t valid. When this method is used on Microsoft Dynamics CRM for tablets a red "X" icon appears next to the control. Tapping on the icon will display the message.

Xrm.Page.getControl('attributeName').setNotification(message, messageId)
Xrm.Page.getControl('attributeName').clearNotification(messageId)


5. OptionSet - Use the addOption, clearOptions, and removeOption methods to manipulate options available for OptionSet controls.

Xrm.Page.getControl('attributeName').addOption(option, [index])

Option is little object with text and value properties.

Xrm.Page.getControl('attributeName').clearOptions()
Xrm.Page.getControl('attributeName').removeOption(option.value)


6. Refresh - Refreshes the data displayed in a subgrid.

Xrm.Page.getControl('attributeName').refresh()


7. Focus - Sets the focus on the control.

Xrm.Page.getControl('attributeName').setFocus()


8. Time - specify whether a date control should show the time portion of the date.

Xrm.Page.getControl('attributeName').setShowTime(bool)


9. Visible - Determine which controls are visible and show or hide them using the getVisible and setVisible methods.

Xrm.Page.getControl('attributeName').setVisible(bool)


10. IFrame - Use these methods to interact with web resource and IFRAME controls.

Xrm.Page.getControl('subGridName').getData()

Returns the value of the data query string parameter passed to a Silverlight web resource.

Xrm.Page.getControl('subGridName').setData(string)

Sets the value of the data query string parameter passed to a Silverlight web resource.

Xrm.Page.getControl('subGridName').setSrc(string)

Sets the URL to be displayed in an IFRAME or web resource.


Little tip to the end: If you want to manipulate with control in the header of the form, specify prefix “header_” before property name. Example : Xrm.Page.getControl(‘header_attributeName’).