Archive

Archive for the ‘AJAX’ Category

Enabling dual date format output for JSON.NET

May 9, 2012 1 comment

 

By default the JSON.Net library will emit all dates using the ISO Date format e.g "2012-05-09T00:00:00Z", but Microsoft’s JSON formatter for date will emit using Microsoft’s own format “new Date(1234656000000)”

 

Problem comes in when you have previously been using Microsoft’s JSON formatter and now want to use JSON.NET’s implementation. You will then have to decide whether you want to use the new format and change all your existing apps, or use the old format and make it slightly less interoperable.

 

One other alternative which I’m going to suggest below is to emit both date types, and suffix the other date property with a “_js” to differentiate between the 2 dates

image

 

To get this to work, just follow the steps below

  1. Download the latest JSON.NET library at http://json.codeplex.com/
  2. Open the solution and goto the Newtonsoft.Json project
    image
  3. Open JsonSerializerInternalWriter.cs
  4. Search for the following function
    private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract, JsonContainerContract collectionContract)

    This function is the primary function that writes out the JSON output based what you passed in to serialize

  5. The function should look something like
    image
  6. What we are targeting is the last 2 lines of the function i.e

    writer.WritePropertyName(propertyName);
    SerializeValue(writer, memberValue, contract, property, collectionContract, null);

  7. Change these 2 lines of code to

    //Ensure membervalue is not null and is a datetime type

  8. if (memberValue != null && memberValue.GetType() == typeof(DateTime))
    {
        //Default property uses Microsoft Date Format
        writer.WritePropertyName(propertyName);
        writer.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
        SerializeValue(writer, memberValue, contract, property, collectionContract, null);

        //Same property with a _js returns a ISO Date Format
        writer.WritePropertyName(propertyName + "_js");
        writer.DateFormatHandling = DateFormatHandling.IsoDateFormat;
        SerializeValue(writer, memberValue, contract, property, collectionContract, null);
    }
    else
    {
        //Original implementation 
        writer.WritePropertyName(propertyName);
        SerializeValue(writer, memberValue, contract, property, collectionContract, null);
    }

  9. Compile the project and copy the new json.net dll to your server
  10. Test and make sure you see both dates being emitted
Categories: AJAX, ASP.NET

Latest jQuery

March 16, 2012 Leave a comment

For those that always wants to use the latest jQuery, here’s the link

http://code.jquery.com/jquery-latest.min.js

Categories: AJAX, ASP.NET

ASP.NET MVC String Editor Template which handles the StringLength attribute

December 20, 2011 Leave a comment

Interestingly enough I was searching for a way for MVC to automatically handle the stringlength property. Seemed quite straightforward to implement, but somehow there is no available code out there to figure this out. Using the Html.EditorFor just creates a no frills textbox, which is rather irritating.

Logic walkthrough

Basically what the template does is to attempt to find the StringLength attribute from the ModelMetadata, and from there get the validation parameters.

Once it finds the appropriate parameter (in this case max), it will assign this to a string dictionary.

Finally all is wrapped up with a call to Html.Textbox

Usage

to use this ‘custom’ editor template, what you need to do will be

@Html.EditorFor(model => model.strcolumn)

or if you want to specify the width as well

@Html.EditorFor(model => model.strcolumn, new { width = “300px” })

NOTE: This works if you specify Text as the datatype, otherwise you will need to change the top to include the template name

Code Segment (Text.cshtml)

Note that the following code segment is in razor format, but you can easily change that to a webcontrol.

@* Specifies that this is for the string data type *@
@model String
@{
//Create a dictionary to hold all the html attributes to be applied, this follows the requirement for the Html.Textbox last property which requires IDictionary<string, object>
var o = new System.Collections.Generic.Dictionary<string, object>();

//add in the default css class, notice that the @ is not required in this case
o.Add(“class”, “text-box single-line”);

//Attempt to find the validation attribute for maxlength
foreach (var r in ViewData.ModelMetadata.GetValidators(this.ViewContext.Controller.ControllerContext))
{
//What we are looking for is a validator of type StringLengthAttributeAdapter
if (r is StringLengthAttributeAdapter)
{
var attr = (StringLengthAttributeAdapter)r;

var ValidationParameters = attr.GetClientValidationRules().First().ValidationParameters;

//Get the validation parameters, maxlength is a required parameter so it is definately there, but just check in case for some reason it is not there
if (ValidationParameters.ContainsKey(“max”))
{
//add the maxlength property to the dictionary
o.Add(“maxlength”, (int)ValidationParameters[“max”]);
}
}
}

//additional check to see if there is a width property specified
if (ViewData[“width”] != null)
{
o.Add(“style”, “width: ” + ViewData[“width”].ToString());
}

//Finally emit the html for the textbox
@Html.TextBox(“”, ViewData.TemplateInfo.FormattedModelValue, o);
}

Categories: AJAX, ASP.NET, MVC

Customizing the display for AutoCompleteExtender

January 1, 2010 2 comments

The AutoCompleteExtender that came with the Ajax Control Toolkit is great for linear data, but what happens when you want to customize its output, e.g say you want to display the multiple values in a table form?

This is definately possible since at the end of the day, the UI is rendered using Javascript, however you will need to do some tweaking.

WebService

In order to return multiple values, your webservice needs to return an object[] array, or more specifically, a Pair<> array, this is because the client side javascript reading the webservice functions such that if a pair is returned, it will set the whole pair object as the “value” for the item.

[WebMethod]
public object[] GetCompletionList(string prefixText, int count)
{
//demo code
if (count == 0)
{
count = 10;
}

if (prefixText.Equals(“xyz”))
{
return new string[0];
}

Random random = new Random();
var items = new List
>(count);

var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
for (int i = 0; i < count; i++)
{
char c1 = (char)random.Next(65, 90);
char c2 = (char)random.Next(97, 122);
char c3 = (char)random.Next(97, 122);
int id = i;
int age = random.Next(18, 70);
var item = new Pair(id.ToString(), new object[]{prefixText + c1 + c2 +c3, age});
items.Add(item);
}

return items.ToArray();
}

Now that the webservice is returning the data, lets move on to the client side javascripts. What we need to do is to “override” the onClientItemSelected and onClientShowing javascripts 

The below example assumes a HTML table display format.

function OnClientItemSelected(behaviour, args) {
var element = behaviour.get_element();
var control = element.control;

//args._value is the pair object which is returned
if (control && control.set_text)
control.set_text(args._value.First);
else
element.value = args._value.First;
}

function OnClientShowing(behaviour, e) {
var ResultsDiv = behaviour.get_completionList();

for (var i = 0; i < ResultsDiv.childNodes.length; i++) {

var item = ResultsDiv.childNodes[i];

//since the pair object stores the values to display in the second variable, lets get it out to do our own processing
var vals = item._value.Second;

 //remove all child nodes

while (item.childNodes.length > 0)
item.removeChild(item.firstChild);

//create the table
var tbl = document.createElement(“table”);
tbl.setAttribute(“width”, “100%”);
tbl.setAttribute(“border”, “1”);
tbl.setAttribute(“style”, “border: solid 1px black;border-collapse: collapse;”);
tbl._value = item._value;

var tbody = document.createElement(“tbody”);
var tr = document.createElement(“tr”);
tr.setAttribute(“valign”, “top”);
tr._value = item._value;
for (var j = 0; j < vals.length; j++) {
CreateTableCell(tr, vals[j], item._value);
}
tbody.appendChild(tr);
tbl.appendChild(tbody);
item.appendChild(tbl);
}
}

function CreateTableCell(tr, str, value, width) {
td = document.createElement(“td”);
//this is a very important step, if you forget to set the td._value, when onClientSelected triggers, args._value will be null
td._value = value;
td.setAttribute(“width”, width);
td.innerHTML = str;
tr.appendChild(td);
}

Categories: AJAX, ASP.NET

Custom Controls

March 25, 2009 Leave a comment

ASP.NET makes custom controls extremely easy to write, but if you are not careful, hard to manage.

There are 2 ways to create a custom control

  1. Writing your own HTML code
  2. Using the controls property

Writing your own HTML code

Using your own properties, you can easily write HTML code to generate the
output

e.g consider a simple scenario where you take in a text and color input and
render the control.

You can simply create a class and extend it from the WebControl base class to
have the functions available to your custom control.
Thereafter, just create the properties you require and use them inside the
Render function.
Do note that you can render different output when in design mode and actual
rendering, all you need is to check the DesignMode property.
If however you need input boxes, do take note that you need to handle the
postback event and put the value back into the inputs manually.

public class
SimpleControl :
WebControl

{

public
SimpleControl()

{

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string Text

{

get

{

object obj =
this.ViewState[“Text”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Text”]
=
value; }

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string Color

{

get

{

object obj =
this.ViewState[“Color”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Color”]
=
value; }

}

protected
override
void Render(HtmlTextWriter
writer)

{

writer.Write(“<font color='”
+ Color +
“‘>” +
Text +
“</font>”);

//base.Render(writer);

}

}

Using the controls property

The good thing about using the controls property is that you do not need to
care about ViewState (it is handled by the individual control), Postback
inputs handling (handled again by the individual control).

The bad thing is

  1. Have to write your own custom event handlers
  2. Everything needs to be control based, you cannot emit your own html.

public class
LabelExtendedControl
:
Label

{

public
SimpleControl()

{

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string xText

{

get

{

object obj =
this.ViewState[“Text”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Text”]
=
value; }

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string xColor

{

get

{

object obj =
this.ViewState[“Color”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Color”]
=
value; }

}

protected
override
void Render(HtmlTextWriter
writer)

{

this.Text = xText;

this.ForeColor =
System.Drawing.
Color.FromKnownColor(xColor);

base.Render(writer);

}

}

Custom Events

To create your own custom events, you need
to write 3 main items

  1. A readonly object containg the event
  2. A function which will call the Event
  3. The actual event handler itself

private
readonly
object EventCreate =
new
object();

protected
virtual
void OnCreate(EventArgs
e)

{

EventHandler
onCreateHandler = (
EventHandler)Events[EventCreate];

if
(onCreateHandler !=
null)
onCreateHandler(
this,
e);

}

[Category(“Action”),Description(“Raised
when a CommandEvent occurs within an item.”
)]

public
event
EventHandler Create

{

add

{

Events.AddHandler(EventCreate, value);

}

remove

{

Events.RemoveHandler(EventCreate, value);

}

}

Performance Programming with ASP.NET Ajax

February 9, 2009 Leave a comment

At first glance, ajax seems to be a cinch with asp.net 3.5, what with all the updatepanel, timers and such. However behind this ease of development hides a danger which most developers may not notice.

Although updatepanels and timers are easy to use, each update triggers a complete postback and if your viewstate is on the page, its an extremely large form post. On the server side, each event of a normal postback is called, and the whole control tree is generated to handle the ajax form post. This is quite intensive both for the server and for the client.

This can be good or bad depending on how you look at it. Its good because it ensures that the postback is a valid one, and also gives you flexibility on the controls you want to change and to include in any javascript that you need, all these being done on the code behind, without the need to fiddle with all the client side javascript required to perform these actions.

On the flip side, there are also client side apis and scriptmanager service references which gives you complete flexibility to go ahead and program using client side javascript.

Nexus initially went with the first approach (i.e a whole bunch of updatepanels), but the results were less than impressive. Moving onto the second approach required a revamp of the whole source code, but this gave the user a much better experience along with substantially reducing server load.

To reduce the footprint on the server side, i utilized ScriptManager’s ServiceReference parameters

<asp:ScriptManager ID="ScriptManager" runat="server"
      onasyncpostbackerror="ScriptManager_AsyncPostBackError">
<Services>
    <asp:ServiceReference InlineScript="true" Path="JSON.asmx" />
    <asp:ServiceReference InlineScript="true" Path="ProxyAsync.asmx" />
</Services>
</asp:ScriptManager>

ServiceReferences exposes the webservice functions in client side javascript so you can call these webservices without having to write complicated javascript. for example, i have a webservice function called UserFirstLoad(). This function is called the everytime the user logs into Nexus.

[WebMethod]
[ScriptMethod(UseHttpGet = false, XmlSerializeString = true)]
public JSON_Tabs UserFirstLoad()

Instead of writing javascript to interface to this webservice, ScriptManager automatically writes it for you and exposes it nicely as JSON.UserFirstLoad(), a function which i can easily call and have the capability to do error handling if need be.

As i’m not using UpdatePanel, GUI updates are done directly via DOM. Fortunately Ajax ClientScripts provide some global functions which i can use to

  1. Locate the element i want to update ($get)
  2. Add events to the element ($addHandler)

It is also fortunate that Visual Studio 2008 comes with javascript intellisense, which autocompletes your javascript as you type.

As Javascript is OOP, i decided to build my client script scripts around objects and functions. This gives me the flexibility to overwrite functions and have nice clean code which i can then easily debug with VS2008.

Categories: AJAX, ASP.NET, Performance