Using .resx Strings in Javascript

February 7, 2014

If you output a string in ASP.Net MVC using @ (Razor) or <%: %> (aspx), the string will automatically get HTML-encoded.

So if you reference a resource string (.resx) in Javascript,

<script type="text/javascript">
var x = "@resx.StringId";
</script>

AND the string contains characters the HTML-encoded (such as “&” => “&amp;”, umlauts, accented characters, etc.), you’ll end up with a lot of ampersands.

The way I solved this problem in a recent project was to define an HtmlHelper extension like this:

public static IHtmlString JsString<TModel>(this HtmlHelper<TModel> html, string s)
{
  return html.Raw(HttpUtility.JavaScriptStringEncode(s));
}

The string is first Javascript-encoded, and then written to the response stream unchanged using HtmlHelper.Raw().


Retrieving the data() Value of Multiple JQuery Objects

August 29, 2013

I have a web page with a (generated) list of checkboxes, each representing a database record

                <input type="checkbox" data-oid="<%= record.OID %>" />

After checking the desired check boxes, the concatenated values of the data- attribute should be posted to the server.

Since this selector

$("input[type='checkbox']:checked")

would return all the checked checkboxes, I expected the expression

$("input[type='checkbox']:checked").data("oid")

to return all data- values as an array. But NO:

Store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.

says the jQuery documentation quite unexpectedly.

I need a map(), I thought, and after a couple of tries convinced the JS interpreter to let me have my map():

$("input[type='checkbox']:checked")
    .map(function(i,el) { return $(this).data("oid"); })

Great. This returns something that looks like an integer array, e.g.

[82, 86]

but it is not, since I cannot join() it:

TypeError: Object [object Object] has no method ‘join’

and the Chrome Developer Tool claims it looks more like a stack than an array. Make it so!

$("input[type='checkbox']:checked")
    .map(function() { return $(this).data("oid"); })
    .toArray()

The result not only looks like an array, it really seems to be an array, and

$("input[type='checkbox']:checked")
    .map(function() { return $(this).data("oid"); })
    .toArray()
    .join(",")

finally returns a string of concatenated integer values:

"82,86"

WCF WebGet JSON DateTime.MinValue => “Connection Reset”

July 9, 2013

I created a WCF web service that implements a method that returns an object containing a DateTime value (not nullable, according to spec, don’t ask).

The web service worked fine, and I wanted to add GET support using the WebGet attribute and some web.config magic. Still worked fine.

Then I tried out some failure scenarios (if you have a status query that tries to connect to a database which happens to be offline, or misconfigured, you want to know how your status query behaves), and suddenly the only response I got from the browser was “connection reset”.

After switching on WCF tracing, the failing WCF call generated a 168kB XML file containing 160 lines of stack trace for a single call!

Despite its size, the information in the file is quite useful, as it pointed to an internal exception:

System.Runtime.Serialization.SerializationException

DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON.

   at System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTime(DateTime value)
   at WriteTimestampTOToJson(XmlWriterDelegator , Object , XmlObjectSerializerWriteContextComplexJson , ClassDataContract , XmlDictionaryString[] )
   at System.Runtime.Serialization.Json.JsonClassDataContract.WriteJsonValueCore(XmlWriterDelegator jsonWriter, Object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
   at System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.SingleParameterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
   at System.ServiceModel.Channels.JsonMessageEncoderFactory.JsonMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
   at System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
   at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message)
   at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
   at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
   at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc&amp;amp; rpc)

with an internal exception of type System.ArgumentOutOfRangeException:

Specified argument was out of the range of valid values.
Parameter name: value

and many more stack traces.

Back to my code: If there is an error connecting to the database, I return an object that contains a field set to DateTime.MinValue.

It seems that MinValue causes problems when converted to or from UTC, or at least the subsequent JSON serialization does, even though the ECMA Date range is greater than the .Net DateTime range.

Whatever the causes of this boundary problem are, returning DateTime.MinValue.AddDays(1) solved the problem.


Inserting and Updating List Items with ASP.Net MVC and JQuery

May 16, 2013

In ASP.Net MVC you can display lists of data either as a grid with paging, just as in ASP.Net, or, as I prefer most often, using Infinite Scrolling.

Editing and item or adding an item to the list needs a different approach in Infinite Scrolling as opposed to the paging grid: after adding or updating, you do not want the user to have to scroll back to the original location of the record inside the grid.

Let’s have a look at how Infinite Scrolling can be implemented:

$.get("/More/Items/" + page /* + other options, such as sort order */ , 
  function(data) {    if (data != "") {
      $("#myList").append(data);
    }
  }
);

So we need a controller method returning a partial view filled with the data model of the list.

To support adding a newly created record, or displayed an updated record in the list, we split the list’s partial view into an enumeration part and an item part

List.ascx:

<table><thead><tr><th>.....</th></tr></thead><tbody>
<% 
  foreach(var item in Model.Items) {
    Html.RenderPartial("ListItem", item);
  }
%>
</tbody></table>

The ListItem.ascx then contains the record inside a <tr>:

<tr><td>.....</td>....</tr>

Easy.

Next. we want to support adding and editing records. Personally I prefer jQuery UI’s $.dialog() to open a form for editing the record, and upon closing the dialog, the data is stored using an Ajax or Web service request, and finally the list item is updated:

var tbl = $("#myTable tbody");

$.get('Ajax/GetInsertedRecord?id=' + data.Id
  function (data) {
    tbl.prepend(data);    // insert as first record in list
  }
);

where data is the record returned from the Ajax call to insert the data.

Analogously for updating the edited record, use

var tr = hl.parent().parent();  // retrieve the <tr> of the Edit button

$.get('Ajax/GetUpdatedRecord?id=' + data.Id,
  function (data) {
    tr.replaceWith(data);
  }
);

This in-place adding and updating just require 2 controller methods, and the record partial view extracted from the original list view! Both controller methods return the same partial view as the one referenced in the list partial view.


What is ‘this’? Confusion in JavaScript and Typescript

December 23, 2012

Since Typescript supports “true” object-oriented programming using the ‘class’ and ‘interface’ keywords, there seems to be an expectation that the semantics of JavaScript is suspended and replaced by Something Completely New. This is not the case!

Remember, Typescript is a syntactic extension of JavaScript and compiles to JavaScript. The underlying concepts remain unchanged. (Un)fortunately (depending on your point of view and your expectations), this is also true for the ‘this’ keyword.

Let’s have a look at some StackOverflow questions regarding the meaning of ‘this’:

The questions assume that a callback function passed to another function will be executed in the context of the original object, therefore retaining the semantics of ‘this’ identified the original object:

myFoo(){
    otherFoo.otherBar(this.myBar);
}

In JavaScript, however, the function myBar is executed with ‘this’ referring, depending on the implementation of otherBar, to the otherBar function, or something completely different.

Do not despair, though, there are a couple of possible solutions:

 

 


Typescript Support for JavaScript Libraries such as jQuery

November 15, 2012

Most JavaScript code relies on functionality implemented by the numerous JavaScript libraries and frameworks available, such as jQuery.

To use these libraries from Typescript, you can either create so-called ambient definitions for the JS library manually, or use existing Typescript definition files (extension .d.ts).

The TypeScript source code repository contains a jquery.d.ts in the /bin directory, and a definition file for jquery.ui can be found in /samples/warship. However, those samples need not cover the respective library completely.

This question on SO points us to the github repository DefinitelyTyped

TypeScript type definitions repository for popular JavaScript libraries.

The project aims to provide high quality definitions for the most popular libraries out there.

which lists about 50 definition files covering major JS libraries and frameworks.


Installing TypeScript in Visual Studio 2010

November 9, 2012

After my lengthy introduction on how I finally got interested in developing in JavaScript and in the promises of TypeScript, here is how to install TypeScript in Visual Studio 2010.

The TypeScript homepage only refers to installing TypeScript in VS 2012, and the MS download page states

TypeScript for Visual Studio 2012 will install when Visual Studio 2012 is not installed, and provide the TypeScript compiler.

However, this answer on SO indicates a solution for VS2010:

  • Download the installer package (most current is TypeScriptSetup.0.8.0.msi)
  • Run the installer package to install the TypeScript compiler
  • Extract the .msi using 7zip
  • Copy or rename the extracted TypeScriptLS.vsix_File to TypeScriptLS.vsix
  • Run the .vsix file
  • The installer states it will install TypeScript support for VS 2010
  • (Close and) Open Visual Studio 2010

After successful installation, Visual Studio provides:

  • a new project type named “HTML Application with TypeScript”
  • a new item type named “TypeScript File”

If you do not find the new types immediately, simply type “Type” in the search box of the Add New dialog.


JavaScript Love Hate

November 8, 2012

I have to admit: in all those years of web development, I was quite reluctant to write any JavaScript code.

In the early days of ASP.Net, JS was either not required or not (easily) possible to implement the functionality we know today. This changed with the arrival of the Ajax Control Toolkit that simply injected pre-built pieces of JavaScript code into a page using server-side controls, or by manually typing a couple lines of code.

The main reason for me, though, was that you cannot compile JavaScript.

You have no idea whether your piece of code actually works – you need to run it to see whether it’s ok. Combine this with the typical behavior of IE on a dev machine, popping up a message box whenever a JS error occurs, or different parsers with different sensitivities to well- and mal-formedness of code in different browsers (missing a semicolon, adding a comma too much), and it’s easy to see that for people used to compiling code there was a lot to dislike.

Also, until quite recently, there were simply too many JavaScript libraries available to make a sensible choice between jQuery, prototype, ext-js, and several others. Fortunately (or unfortunately, depending on your preferences), this has changed, as illustrated in this chart.

But the times, they are a-changing. Today’s web applications are inconceivable without proper client-side functionality and asynchronous server communication, all implemented in Javascript. As Scott Hanselman cited more than a year ago, “JavaScript is Assembly Language for the Web“.

Why do I write all this? Well, I finally brought myself to write my first JavaScript application. The ASP.Net MVC project is essentially just the container for JS code, and also implements the Ajax backend using Controllers that return JsonResults.

While programming in JavaScript “for real”, I got quite fascinated about the things that are possible in JavaScript, and the project soon reached 2000 lines of code. However, as it goes with first projects, the code soon became unmanageable and needed a cleanup. The code implemented various dialogs with partially dynamic fields and validation, a hierarchical database browser and a web directory browser, but it was a mess.

The first restructuring was to avoid global variables as much as possible, encapsulate the Ajax calls in a static object, and each dialog in one function, with the event handlers implemented as local function variables.

But all this code with its anonymous parameters and asynchronous callbacks passing untyped (in JavaScript, but typed in C#) parameters to the success() functions is still difficult to understand (“write-only”).

The latest innovation that gave me a prospect of typed, compilable, and modular programming is called TypeScript, an extension to the JavaScript language that compiles to JavaScript (CodePlex). It installs as new project type and item type in Visual Studio, and its support for typical IDE functionality such as Intellisense, Go to Definition, Find References, etc. is quite good, judging from first glance.

Finally, a couple of links to introductory news articles that drew my interest for TypeScript:

Give it a try!


Selecting an OpenID Selector

August 2, 2012

As soon as you get started with OpenID, you face the question of which OpenID Selector to choose. There are so many!

Project Latest Version Comments
openid-selector 11-02-10 ~10.000 downloads
openid-ps 10-01-10 imitates StackOverflow UI, only 200 downloads
jQuery OpenID plugin 09-02-10 “inspired” by openid-selector, openid-realselector
openid-realselector 09-04-29 no downloadable .zip

Now that I collected the data, the choice seems clear: use openid-selector, and check the modifications included in the openid-ps project.


Left-to-Right Tab Order in CRM 2011 Form

July 25, 2012

Looking for a solution to set the tab order in a CRM 2011 Form to tab horizontally (rather than vertically), I found a couple of solutions (such as here and here).

The solutions, however, were not complete, and required a bit of tweaking:

  • including the tabs for headers inside a form
  • setting the tabIndex higher than the navigational tab indexes

Finally, my function looks like this:

function TabOrderLefttoRight() {
    for (var i = 0; i < crmForm.all.length; i++) {
        var element = crmForm.all[i];
        if (element.tabIndex && element.tabIndex != "0") {
            if (element.className == 'ms-crm-Hidden-NoBehavior') 
                continue;
            if (element.tagName == 'A') {
                if (element.className != 'ms-crm-InlineTabHeaderText') 
                    continue;
            }

            element.tabIndex = 10000 + (i * 10);
        }
    }
}

Simply add a call to TabOrderLeftToRight() in your form’s onLoad event.


Follow

Get every new post delivered to your Inbox.

Join 65 other followers