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

ASP.NET- Simple localization with free tool (Zeta Resource Editor)

When we are writing every application (software), we are localizing the resources. Every text information writing to the .resx files as follows :

Text resources in .resx filesCommonly we are using 2 languages (English as default and Slovak as optional, because Slovak is our motherly language). So in this case we need 2 resource files for as follows:

Two resource files

And what was the issue? The issue is effectiveness of translating from one language to another. This issue is in visual studio little bit complicated, because you need to synchronize every keys from one file to another. And for this purpose we are using cool tool called Zeta resource editor. Look at the following picture:
Zeta resource editor in action

Zeta resource editor provide you edit values for particular key very confortable on one screen (on one line). And the best feature is the finding of missing keys. You can easily add new value for particular missing key.
Zeta resource editor - missing keys

Is really useful in situations, when your resource files are not sync. and some keys missing in both files.

ASP.NET MVC - the value set on the field does not correspond to the value in the Model - what’s wrong?

While developing our brand new LiveChat called ”Suppo.biz”, I noticed interesting behaviour, what I never noticed before. In the functions like @Html.EditorFor, @Html.TextBoxFor … or @Html.TextArea, @Html.TextBox … When you do AJAX “postback” of your form like this:

			@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "Post", InsertionMode = InsertionMode.Replace, UpdateTargetId = "FormAjaxContainer" }))
			{
				@Html.AntiForgeryToken()
				
				<div id="FormAjaxContainer">

					<div class="form-group">
						@Html.LabelFor(model => model.WidgetThemeColor, htmlAttributes: new { @class = "control-label col-md-2" })
						<div class="col-md-10">
							@Html.ValidationMessageFor(model => model.WidgetThemeColor, "", new { @class = "text-danger" })
							<div class="input-group BGColorPicker">
								<span class="input-group-addon"><i></i></span>
								@Html.EditorFor(model => model.WidgetThemeColor, new { htmlAttributes = new { @class = "form-control" } })
							</div>
						</div>
					</div>

				</div>
			}

with value “A” on property WidgetThemeColor and on the server you change the value to value “B” you still see on the input field the value “A”. Its caused by interesting behaviour of the helper function of all controls like @Html.EditorFor, @Html.TextBox …
They first use the value of the POST request and after that the value in the model. This means that even if you modify the value of the model in your controller action if there is the same variable in the POST request your modification will be ignored and the POSTed value will be used. When you want to apply your new value from controller, you need to do this:
 
ModelState.Clear();

Or for particular property by this statement :
ModelState.Remove("WidgetThemeColor");

And the POSTed value will be ignored while rendering of the View or PartialView.