Bi-directional Dictionary implementation
There were several times, during my short development career, that I’ve
used Dictionary<TKey, TValue>. It may not be on most cases, but I’m sure
in many of them, I needed to find a dictionary item by it’s value whereas
the dictionary’s values were unique as well as it’s keys.
This led me to the motivation of developing a dictionary that will support
bi-directional access.
What were the requirements?
1. Access dictionary[value] will return it’s key the same way dictionary[key]
return it’s value.
2. Performance will be effected only by a constant (O(1) to get and set dictionary item
the same as in regular Dictionary<TKey, TValue>)
3. The bidirectional dictionary will implement all interfaces that Dictionary<TKey, TValue>
does.
Implementation:
The requirements listed above have led me to use Dictionary<TKey, TValue> qualities by
using an internal two dictionaries. One will act as Dictionary<TKey, TValue> and the other
will be the other way around (Dictionary<TValue, TKey>).
I’ve set two indexers (one for each direction). The add / remove methods calls their
corresponding methods on their internal dictionaries.
When trying to add the same value twice (with different keys) an exception is thrown.
Limitations:
When using the bi-directional dictionary with key and value having the same type, there
is an ambiguity when calling dictionary[key] and dictionary[value].
I’ve had two choices – Change the whole interface of the opposite direction access and
having all “by value” access be explicit, or removing the support for same type. On that
case, I’ve preferred keeping the same interface for by-key and by-value access and
therefore removed support for the same type.
My implementation can be downloaded here (don’t forget to change the extension to .cs)
Another implementation that does support same type dictionary I’ve found on a
StackOverflow forum thread here .
This class can run on Framework 2.0 and above
Code snippet for control wrapping properties
Hello everyone.
many of us, I’m sure, needed to wrap inner controls of a user\custom control
with public properties. That’s in order to have their control encapsulated,
and to add some code flexibility (If the control is changing, all I need to do is
change the code of my property and the rest remains intact.
Therefore I’ve made a code snippet for myself that allow me to write these kind
of properties easily, and figured why not let everyone use it.
I hope you’ll find it useful.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Control Property</Title>
<Shortcut>propctrl</Shortcut>
<Description>Code snippet for property with get and set accessors
that wraps an inner control</Description>
<Author>Ran Wahle</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>name</ID>
<Default>PropName</Default>
<ToolTip>Property name</ToolTip>
</Literal>
<Literal>
<ID>controlName</ID>
<Default>ctrlName</Default>
<ToolTip>Control Name</ToolTip>
</Literal>
<Literal>
<ID>controlInnerProperty</ID>
<Default>Text</Default>
<ToolTip>Control Inner property</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[
/// <summary>
/// Put summary for $name$
/// </summary>
public $type$ $name$
{
get
{
return $controlName$.$controlInnerProperty$;
}
set
{
$controlName$.$controlInnerProperty$ = value;
}
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
This post comes as an extension to a post by Shlomo Goldberg (in Hebrew) that talks
about how to work with session variable in a safer way than plain strings.
Shlomo Goldberg has suggested that instead of strings we should work with enum entries.
This way is more efficient for developers who can simply find all the uses of a certain session
variable and can find all reference to it.
As you can see from the code attached to that post, it uses indexer with SessionParam
enum using a private method called RetrieveFromSession, which calls it’s overloading
method that accepts the good old string parameter (using the enum.ToString method).
This one, of course holds some performance penalty because it’s use of the ToString method
call for enum. Here’s another approach:
As an extension for this suggestion one might suggest the use of properties that envelopes
the session variable within.
All properties are in a singleton class (The same as in the class suggested by Shlomo Goldberg)
A property of such can look like that:
1: public UserInfo DelegatingUser
2: {
3: get
4: {
5: return Session != null ? (UserInfo)Session[DELEGATING_USER] : null;
6: }
7: set
8: {
9: if (Session != null)
10: {
11: Session[DELEGATING_USER] = value;
12: }
13: }
14: }
Where Session is also a property envelopes HttpContext.Current.Session
and the DELEGATING_USER is a string constant
What do we gain from it?
1. Type safety. Use of this kind of properties will prevent override one type of an object by
another without the compiler will notify.
2. We don’t have to use the enum.ToString anymore and therefore gain our performance
back almost fully.
3. We can add logic to the properties.
There are two (or more) downsides however:
1. This class may be coupled to the project’s data model, you cannot simply put it on another
project because it won’t compile.
2. You cannot add session variables through this class form another files. Adding new session
variables requires adding new properties to the class.
You can download the class in here. (Note – it won’t compile because it is coupled to
my project’s data model)
Accessibility: Using WAVE extension for Firefox
Two issues I came across regarding developing web apps that supports accessibility
are knowing the guidelines along with lack of tools that can check the actual
page generated by our application and provide as with meaningful information
on how to fix accessibility errors.
Visual Studio validation disabilities
Visual studio has, since it’s 2005 version, a tool for accessibility check on web pages.
however, it cannot discover errors caused by HTML generated in our code behind,
in our or 3rd party’s custom controls and of course not on elements generated in
JavaScript using DOM manipulations or any other technique on client side.
Accessibility toolbars
There is a variety of accessibility toolbars for Internet Explorer, Firefox, Opera and more.
These toolbars are great tools and include features like stripping page from it’s
CSS / pictures / JavaScript (viewing in text-only mode) , sending the page to be
validated on various web accessibility and W3C compliance validators and so on.
WAVE toolbar for Firefox
WAVE toolbar for Firefox contains all those features and one, very significant, more.
In the following screenshot you can see the “Error, Features and alert” . Here, by pressing
a button, you can see all accessibility faults on your page:
As you can see in the on the picture above, there are little icons added near some elements.
The red ones are for errors, the yellow for alerts and the green ones are displaying the
accessibility features on the page.
Going with your mouse over each icon tells us what the error / alert / feature is about as
a tooltip.
What does it give us?
1. The “Errors, Features and Alerts” button does it’s validation on the client side.
Meaning that it is good for offline pages, pages on enterprise’s intra-net and
sites requires log-in.
2. Even if you are not familiar with the accessibility guidelines you can easily learn
what your mistakes are by simply press the “Icon key” button. The explanations
and recommendations on that page are simple.
Summary
Accessibility is something to keep in mind when designing our web application’s UI.
Visual Studio’s accessibility checks is not profound enough because it’s limitations
in discovering issues caused by our code-behind or ours / third party’s custom controls.
WAVE accessibility toolbar may come in handy with it’s “Error / Features and Alerts”
feature that helps us find our accessibility issues easily. It check’s our page with it’s
final output (including elements created on client side) and does it locally. It also
contains the same features as other toolbars such as disabling CSS / scripts
and sending the page’s URL for validating in various validating sites.
You may download latest version here (open the downloaded file with Firefox)
Accessibility presentation at SRL
On Tuesday, January 6th, I held a presentation on the monthly SRL .Net developer
meeting. The theam was accessibility which is n area I've become aware about
just recently.
We've heard a site in screen reader, talked about accessibility in general, what
is it good for? for whom? What are the main things to take not account while
building an accessible application or making old one accessible, and presented
some testing tools at the end.
You can download my presentation (PDF format) from here
Post by my friend and colleague Gil Fink, has reveled one of the difficulties of our project.
A legacy system, poorly designed and implemented and our need of rewriting some of
it's code in order to make it easier for us to extent it with more features as demanded
by our users.
Another aspect of our legacy system was pages with lots of controls, almost each and every
one of them has server-side event (click, textChanged, selectedIndexChanded, etc.) while
best practice is to divide the page into units of User Controls while the page acts as a router
between them and between them and the business layer.
So, How can we change the existing situation to be closer to the desired one?
Here we have a long and risky process, I'll try and give it's details:
"Before you begin" stage
1. Make the time to work on it. It is long process and you can fall into many
holes along the way. If you have the time to work on it continuously it's you
can proceed, if not - ask for the time. If it is very much needed, you'll be given
the time to do so.
"Begin" stage
2. Cut all markup belongs to the user control which you need to divide into a new
User control. Do not transfer any code-behind at this stage! Put the new
User control inside the page where the transferred markup used to be.
Compilation Errors correction stages
3. look at all compilation errors. Courtesy of VS2008 SP 1 you'll see it all without
compiling, given that your changed page is open. The compilation errors will
mostly be the absence of the controls transferred to the new user control.
For each control being transferred, make a property represents it's data . By all
means, do not expose any inner control as public property . Here you can also
change the data type (which is string most of the time, to the type needed ,
and put all parsing code inside the property).
After doing so, whenever the page's code behind takes data you can replace
the controls by the user control's data properties you've created.
Note - this should be done with caution because data type changing are risky
4. There are still compilation errors, these errors refers to the control's state, style
etc. Here you have no choice but to move this code to the user control.
Make small methods in the user control, corresponding to the methods on
the page's code behind, transfer the lines referring to the internal controls
and call these methods from the original methods.
For example : if you have a method call SetUIState containing lines referring
to the inner control,make a public or an internal method inside the user
control, call it SetUIState, transfer the relevant lines into it and call it
from the original method.
Runtime exceptions correcting stages
5. By now, all compilation errors should be corrected, however our control
won't work mainly because it doesn't contains the event handlers to
handle it's inner controls evens. Therefore we do the following:
For each event of the inner control we make public event of the user
control, a protected event handler that will only invoke the event
recently created.
6. On the page's markup we should add all events created on step 5 and
for each event we associate the event handler to the old event handler was
for the inner control while being on the page. That's how we won't
change server side behavior of our page.
Client code handling
7. Now, that all runtime exceptions should be behind us, it's time to
handle client errors that might occur. Client errors may occur if there
is JavaScript code referring to the control's ID hard coded, and where
there is client scripting referring to the internal controls with server
code islands, which will cause runtime errors.
Here you have to do the following:
A. Take all client code referring to the internal controls to the
user control's markup.
B. Whenever there is reference to the internal control ID's in client
script, you should change it to <%=YourInternalControl.ClientID %>
That's because whenever a control is put inside composite control
(or user control for that meter) it changes it's ClientID.
Summery: This was a long post mainly because the process is long. The goal
is to gain more encapsulation and code clarity for our system without changing
it's functionality. However, this is just the first step. You soon will see
that you have a little bit clearer code and but this is only the first step
of a long journey of making it better.
Behind The Scene - Control ID's in ASP.Net
We all familiar with the terms of ID, ClientID and UniqueID which are
properties of Control class. In this post I'll dive into the way the last two
read-only properties values are being set and when.
The difference between ClientID and UniqueID
Let's go to the basic HTML form. The form's inputs (I.E text-boxes,
Checkboxes, DropdownLists, RadioButtons) has two basic HTML attributes
called id and name (in small letters which is the standard for HTML attribute) .
The "id" attribute is used by client scripting code to access the element (hopefully
you're using document.getElementById or $get and not accessing it like an inner
property of the form or document.all which are not standard).
The "name" attribute is used as a key in the data being sent to the server when submitting
the form.
On simple form you see that both attributes are the same. However when using a master page,
Field inside User control / CompositeControl / other controls implementing INamingContainer
you see the character of "_" inside the ID attribute and the "$" inside the name attribute.
Note: On ASP.Net 1.1 or sites migrated from it, you may see the ":" seperator on the "name"
attribute instead of the "$" sign. You can set the option of the legacy rendering by changing
the XhtmlConformanceMode on your web.config file.
The HTML attribute of ID corresponds to the server property of ClientID while the Name HTML
attribute corresponds to the UniqueID . One common mistake I've seen is developers confusing
between the two. Internet Explorer will forgive you for binding the UniqueID to client code,
however browser of another kind will issue a script error because it won't find the HTML element.
How both properties are set
Both properties have get accessor only. First, let's have a look of Control.UniqueID property:
(with courtesy of RedGate Reflector)
As you can see, it uses _cachedUniqueId for caching (it also clears when the ID is changing).
However, the main logic of the accessor is assemble the UniqueID with the string returns
from namingContainer.GetUniqueIDPrefix(). This method is recursive while each NamingContainer
calls it's own NamingContainer (The first control that implements INamingContainer contains
this control, not necessarily it's parent) and assemble the UniqueID
of <Container>$<Container>$<Container>$<Container>$...$<ID>.
The CientID is simpler. It simply replaces the seperators. Let's have a look at the code:
In conclusion:
1. UniqueID is the property corresponds to the input's name on client side.
In order to get it's value from the Request object wee need to call
Request[<control>.UniqueID]
2. ClientID corresponds to the input "id" on client side. we need it to bind
to the client code when accessing the HTML element rendered from the
control on the client side.
3. UniqueID is assembled from the control's naming container ID prefix
and the control ID. It is also cached. Therefore it is recommended not
to change the control's ID more than once.
4. The UniqueID won't necessarily contain the parent of the control.
If you have a custom control consists of some controls it is better to
use CompositeControl or any other control implements INamingContainer
than using WebControl or other.
5. After doing so, no need to change the ID property to more than an identifier
to the control itself. Placing an ID of "<parentid>_<controlId>" will cause the
parent id to be chained twice.
AJAX and Dates
While AJAX in general, and Data-Services in particular
becomes more and more in use, you may encounter a
problem of sending / receiving dates when you don't
usually share the same Time Zone settings.
Dates between services
When sending dates over soap the date is serialized
with the date and it's time zone
(The GMT +/- # part which comes straight after
the date itself).
When consuming a service through .Net application you won't notice
any difference, That's mainly because it is being translated to your local time.
What's happens "behind the scene" is that the universal time is being sent
with the "Kind" property of "Utc", then it is being translated to your local time
according to your machine's time zone settings.
And what about your browser?
That's not exactly the situation when the service consumer is your browser.
On some browsers, when receiving dates through JSON, the date sometimes
keep it's original settings of date + time zone. displaying the hour with
date.format("HH:mm") can cause the hour not to be displayed according
to your time zone. I've encountered browsers of the same kind and version
that treat dates differently on different computers so you really cannot determine
what each browser will do.
How to determine what is the client treatments for dates?
Using the getTimezoneOffset() method of JavaScript date object
can be helpful, you can determine the client's time zone by using it
for a date created on client side, you can compare it with the server's
time zone in many ways : Sending the time-zone offset to the server
and compare the server's time zone there, You can send the time zone offset
along with the date from the server to the client and make your comparison
there. It is all depend on where the date object is in, posted date or response.
Just remember - the getTimezoneOffset returned in minutes and with the opposite
sign (meaning - date with Jerusalem standard time will return the result of -120).
What do you want to do with the date?
After you have this information you have to decide what you want to do with
it. If you want to display your dates according to your time zone, determine what
your browser is doing by comparing the getTimezoneOffset() with the actual time zone
on the server. Then, you might want to set you date according to your policy by using
the setMinutes method .When deciding, you might take into account that on the client
side what you most of the time is displaying, and if you didn't use AJAX you would probably
display the dates according to the server's time zone.
Some Code examples in JavaScript
In here - the server sends the time zone offset inside the response (TimeZoneOffsetInMinutes):
var tzGap = resopnse.Date.getTimezoneOffset() * (-1) - response.TimeZoneOffsetInMinutes;
if (tzGap != 0)
{
//Change the date to the server's time zone
response.Date.setMinutes(response.Date.getMinutes() - tzGap);
}
Note: What I did was actually changing the date, I cannot change the date's time zone offset
in JavaScript so the date in here is different from the date on the server.
Anyway - you have to omit time zone effect when sending the date to the server.
Summary:
Dealing with dates with web services was always tricky because of different time-zone settings.
It became evenmore tricky when the client is our browser (on AJAX) and we have to use some
good-old JavaScript tricks to overcome this issue. When sending dates from your client,
it's back to .Net code again and the date being sent is of "Utc" kind
(meaning that you can extract the client's time zone easily).
You can read about it in my "AJAX and DST difference" post.
SRL, the company I work for, for the past two years, is saying goodbye to it's old hours reporting system.
The old system, which was developed long before I've started working there
and served SRL employees ever since, will continue serve SRL payroll staff
(untill we move all management interfaces to the new system)but all other workers
are going to use the new one.
Usually this news it's not very exciting, not enough to write about, however
in this case, I was the one who developed it.
It has all started on my first week on the job. No Internet access at work
(It's alright I have one now) and non-windows OS at home has prevented
me from filling my hours report on this system which supports IE only.
A simple mail to my manager asking her to make a few adjustments in the system's
JavaScript to make it cross browser, has led me to complete replacement of the
hours reporting interface.
It took a great deal of studying new stuff for me, along with investigating the old system's
database and code. A great help in interface design and graphics from
my College Irena Chernov and receiving recommendations and remarks
from an endless list of colleges whom I've
recruited to the pilot team.
The development involved Lot's of AJAX, no Update panel, meaning that
the UI changes was almost solely on client side (Table created on JavaScript after data
received from an AJAX enabled web service ), and a DAL adjusted to work with
the existing system's DB schema.
This has allowed as to have both old and new systems working
side by side so our payroll stuff can still work with their management
screens (that wasn't rewritten for the new system), along with employees
ability to enjoy a faster, cross browser and with some new features (Jewish
holidays built in the hours reporting table).
Needless to say that there were some problems along the way. Working
directly with clients outside our office raised DST setting difference
problem. The time needed to work on the system couldn't be on
working hours (because I work at a customer's site) which caused
the development process take much longer than expected, however
working on the new system was fun even so.
This is the opportunity to thank SRL staff for their trust,
Although the market is full with these kind of products and although these
kind of systems are considered critical I was allowed to build one for SRL.
I want to thank all people who helped me along the way and to those who'll
suffer some bugs (hope not many and no critical ones).
And now for the next project...
Before Visual Studio 2008 there wasn't many decent client debugging tools.
One of the tools that were already (and for free) was the Firebug extension
for Firefox.
Firebug provides, among it's many features an in-browser script debugger
which consists some basic debugging features such as break points, step
into functions, watches of local and global variables, automatic variables
and so on...
Script debugging
Like in VS-2008, you can actually debug your client scripts. the main difference is
that you can stay on the browser and not even have to open Visual Studio for
that meter. All you have to do is go to the script tab, click on the script
resource being debug (third tab on the top).
and reveal the list of scripts. Clicking the selected row will reveal the client
script produced there.
There clicking on a row will create a breakpoint, from there on - you can go with
the usual F10, F11 and F5 buttons we al familiar with...
Error counter
Moreover, one of it's best debugging features, provided also out of the Firefox
Error-Console
is the client error list. It displays an error counter and provide
links to the relevant line by clicking on the specific error.
Net transport
Like Fiddler tool, Firebug provides also a list of all page related requests with the raw data being
sent and received from the server. The difference between these two tools is that
Firebug provides only page-related requests, meaning that the list is being cleared on
every page replacement.
You can press the expand button (from this tab and from the console tab)and see headers, parameters or post data, and response:

Note: In order to see that response you'll have to press a button, that's because firebug didn't
want the performance penalty of processing each response on the browser and on firebug.
Client script profiling
One of it's latest services is the script profiler, all you have to do is click "Profile" at the top and
click it once more to stop profiling. When you've first clicked, a console record is created and when
you've second clicked, the record is expanded to provide a profile report as seen in the picture below.

however, this tool is not perfect
JavaScript is many time a headache, using firebug won't solve it, at least not completely
. Moreover, sometimes it will add it some headache of it's own. For example -
if you're using multiple tabs you will see sometime scripts from another tab.
Although a major performance improvement regarding performance, firebug is still a
debugging tool and therefore it slows your page loading process.
It's user interface is much less convenient that Visual Studio, for example the collapsible list
of the script resources to debug. It's DOM inspector and CSS editor are far less effective than
other tools available and so on...
In conclusion
Need a tool for script debugging, especially if your targeted audience has multiple browsers
and you need your client script to be the closest you can to the standards? you may use
Firebug.
Need to review a web application client performances, need to track down errors easily -
Firebug may be your answer.
However, if you've developed an IE only application , Firebug may not worth the overhead
of making it standard.
On the other hand, it will suit you best if you're developing a web application that should
support almost all browsers (where it's better to develop for Firefox and test on other
browsers). It's is best for AJAX developers because of it's joined abilities of monitoring
your XHR transport and debug your script.
Get Rid of COM+ Application after Migrating to Framework 2.0
Scenario: Let's say that you went to work on an already-in-production system
which started on the old ages on Framework 1.1 (or lower). Back then,
transaction management could only be via COM+ application.
Beside it's advantage (back then...) in transaction management using COM Plus
is a burden for developers and has performance penalty because of inter process
communication between the main process and the DLLHost.exe that runs
the COM Plus.
Moreover, this architecture suffers from maintenance difficulties because you
have to keep at least two .config files, maybe share Dll files, and many other
error possibilities.
Therefore, altohugh COM+ has alot more to offer than only transaction management
(and because we have used nothing but transaction management) after migrating our
system to .Net Framework 2.0 we've decided to use the TransactionScope of
System.Transaction rather than the ContextUtil of System.EnterpriseServices and let
our COM+ application go
The Process:
The code, before the process should look this way:
Class decleration:
[Transaction(TransactionOption.Required)]
public class YourClass : ServicedComponent
Your methods may look like this:
public void UpdateSomething()
{
try
{
//Your code here
ContextUtil.SetComplete();
}
catch(Exception ex)
{
ContextUtil.SetAbort();
}
}
Or, with an AutoComplete attribute, like that:
[AutoComplete]
public void UpdateSomething()
{
//Your code here
}
1. Loose the reference to System.EnterpriseServices (unless you need it
not only for transaction management)
If you do need this reference besides transaction management matters,
you may temporarily loose it and correct only the transaction-related
compilation errors to come.
2. Add reference to System.Transactions
3. Loose the ServicedComponent inheritances and Transaction
attribute for your class.
4. On every method, Insert the using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
block to cover all transaction activities area.
After doing so, your method should be looking like that:
public void UpdateSomething()
{
try
{
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
//Your code here
ts.Complete();
}
}
catch(Exception ex)
{
//Do something with the exception
}
}
5. If your transaction managing methods uses ContextUtil.SetComplete() /
ContextUtil.SetAbort() methods you might replace the ContextUtil.SetComplete()
call by ts.Complete() call and erase the ContextUtil.SetAbort() call.
If your method is decorated by an AutoComplete attribute you might
place the ts.Complete call at the end of your TransactionScope block.
6. After your transaction managing assembly is compiled, all calling assemblies
project probably have compilation error, that is because your classes
won't implement IDisposable (implemented by ServicedComponent) anymore,
and therefore you cannot use them in a using(...) block.
Here you have two options:
A. Implement IDisposable yourself.
B. Remove the using(...) block and call them regularly.
Because from now on, these classes will be used on the same process,
you don't have to use the using(...) block and therefore I'd recommend
removing the using(...) block and call them regularly.
This process might take long but it can be done in steps. You can remove
the System.EnterpriseServices reference deal with several classes,
add it back on, deal with calling assemblies compilation errors and so on...
Summary:
If you've used COM+ for transaction management solly Loosing the dependency
on COM+ application is worthwhile, although it is a long process and must be
done with extreme caution. The transaction managing assembly is most of
the times the business layer assembly and needless to say how harmful reckless
changes can be there.
However, If there is one thing my colleges thank me for, loosing the COM+
application it is.

Sending complex typed data from web service to SilverLight client - Part III
On my previous post I discussed the JavaScript mediator part,
Here I'll sum this part which is Serialize the object for the SilverLight
component and operate method inside it to bind the data.
Step 5 - Serialize the data for the SilverLight component
And here is the code converting the objects
function onGettingAllEmployeesSuccess(result)
{
var slEmployees = new Array(result.length);
for (var index = 0; index <result.length; index++)
{
var newEmployee =
{
"FirstName" : result[index].FirstName,
"LastName" : result[index].LastName,
"EmployeeNumber" : result[index].EmployeeNumber
};
slEmployees[index] = newEmployee;
}
//Serialize the employees
var slSerEmployees = Object.toJSON(slEmployees);
//Bind the data on the silverlight component
$get("Xaml1").Content.silverlightManagedCode.BindListBox(slSerEmployees);
}
The method Object.toJSON is taken from the file Prototype.js written by
Sam Stephenson and distributed freely on http://www.prototypejs.org/
And Finally - Let's insert our SilverlLight control into our test page:
...
<asp:Silverlight ID="Xaml1" runat="server"
Source="~/ClientBin/<YourSilverLightProjectName>.xap"
Version="2.0" Width="100%" Height="100%" />
...
Summary: In order to have complex typed data sent from
your server to your Cleint's SilverLight control via JavaScript you
need to do the following:
1. On your SilverLight project code - write a class with data corresponds
to the data you get from your server.
2. Write JavasCript mediator between your page and your SilverLight control
3. Operate method from your page on your SilverLight control to bind
the serialized data received.
I've attached the SilverLight project's code so you can get started
with your server & mediator easily.
AJAX WEB Methods and Daylight Saving Settings
As most of you know, although our computer displayed time moves forward
by an hour on DST period, It's time isn't changing actually, it just moves to
it's neighboring time zone.
This is in order not to change the computer UTC so different DST setting on different
countries won't cause actual time difference between computers.
However, many system administrators doesn't know how to configure correctly
the time zone shift and instead they simply setting the clock forward / backwards by
one hour.
In an hours reporting system which I've developed I came across a side effect of the
phenomenon mentioned above. When reporting a working day hour one of my colleague
has discovered that his report was "shifted" one hour sooner. The cause of it was
combination of wrong DST settings on the customer's site along with right settings on
our company's site.
Well, In order to solve this problem we cannot change the customer's settings (It's a bank,
they cannot change something so fundamental so rapidly...) and we also can't (and won't)
change our company's settings to the wrong ones, what we can do is sending the client's
current date as a parameter so we can "fix" the dates being sent back to it, if needed.
What we basically need to do is send is the current date from our client.
For that meter we will simply call the new Date() function in our client side.
The server, from it's side, will receive it as a UTC date (you can check it by reading it's Kind
property on the server side or simply by checking the date itself while your client and server
are on the same computer.
Now, all you have to do is compare the date received with the server's UTC date and
correct the dates being sent back to the client if needed..
var hoursToAdd = clientDate.Subtract(DateTime.Now.ToUniversalTime()).Hours;
.
.
.
//Correct the hour "Gap"
MoveHour(result, hoursToAdd);
The MoveHour method implementation simply "shift" all the dates sending
back to the client by the "gap" needed. I did not post the implementation
because it differs from one structure to another and it is very simple.
I know I could use the TimeSpan object itself (without it Hours property)
to correct the gap but this was an example for work around the DST
miss-configuration and I used the Hour property to make it clearer.
Note: This solution contains security risk. If you sent sensitive
data and you relay on time stamp, you
cannot use this solution.
Moreover, if you're using your web service with another system
(not a browser to service like in
AJAX) and you're
implementing WS security this solution is not enough.
To sum up: This solution can go where you have no other choice.
We use it simply because we cannot force large organizations to correctly
configure their DST settings. The date being sent from the client is the
client's machine current UTC time and therefore it is easy to compare
with the server's current UTC time. The rest is too easy to write about...
Sending complex typed data from web service to SilverLight client - Part II
On my previous post I've explained the first steps of creating the service and methods on the server side, and the client
corresponding objects in the Silverlight project. Here I'll go further on the JavaScript mediator side.
After making the Web method for getting the employee, we have to call it from out JavaScript mediator, convert the objects received from the server to the SilverLight corresponding ones, and serialize the objects for our SilverLight component.
Step 3 - Create the JavaScript mediator:
Here is the code for the service call (very simple one but nevertheless...)
function loadEmployees()
{
Billing.GetAllEmployees(onGettingAllEmployeesSuccess, onError);
}
Step 4 - Write the Databind Method on the SilverLight control code
In order to operate methods of your Silverlight control from
JavaScript code, you have to decorate your control class with
ScriptableType attribute and your methodswhich you want to access
with ScriptableMember attribute
[ScriptableType]
public partial class Page
{
.
.
.
//Method to access from JavaScript
[ScriptableMember]
public void BindListBox(string employeesString)
{
MemoryStream memStr = null;
try
{
//Deserialize the data received from the JavaScript mediator
var jSer = new DataContractJsonSerializer(typeof(Employee[]));
memStr = new MemoryStream(Encoding.Unicode.GetBytes(employeesString));
var employees = jSer.ReadObject(memStr) as Employee[];
//Bind the deserialized object with a control (Listbox in that case)
Employee.ItemsSource = employees;
Employee.Width = GetMaxWidth();
}
catch (Exception ex)
{
//This is for debuging, you can operate JavaScript methods of the page
// as an HtmlPage public methods
var message = ex.Message;
HtmlPage.Window.Alert(message);
}
finally
{
//Close the memory stream to release resources
if (memStr != null)
{
memStr.Close();
}
}
}
}
On my next and last post I'll go into the JavaScrip mediator
and sum everything up.
Sending complex typed data from web service to SilverLight client - Part I
In this post I'll explain in how to send complex typed data between web service and SilverLight client
code. In order to avoid security issues I'll use JavaScript as mediator between my server code and SilverLight
code.
First - Let's have a look at a solution contains web server side code with all layers (Presentation that will host
silverlight control , BL, DAL, Structures)
and another SilverLight project
Now, leaving out all server-side lower layers and focusing on presentation layer
and SilverLight code, let's have a look at what we'll demonstrate:
1. Getting complex typed data from the server via JavaScript .
2. Sending some of the data to SilverLight control
3. Presenting data on Silverlight control (A simple ListBox for that matter).
Step 1 - Create a server web method to provide as with the data we need:
[WebMethod(EnableSession = true)]
public List<Employee> GetAllEmployees()
{
var result = new List<Employee>();
//Adding some employees to the collection
result.Add(new Employee()
{EmployeeNumber = 1, FirstName = "Ran", LastName = "Wahle"});
result.Add(new Employee()
{EmployeeNumber = 2, FirstName = "Anonymous", LastName = "Employee" }); result.Add(new Employee()
{EmployeeNumber = 3 , FirstName = "Known", LastName = "Employee"});
return result;
}
Step 2 - Create object similar to the one in the server site.
At this stage the word "Why" might come to mind followed by a question mark...
The reason for that is simple - we cannot make reference from SilverLight project to
a regular .Net one because SilverLight runs on compact framework and therefore can have referenced to SilverLight projects only.
However, You might of course use the service referenced object if you connect to a service, here we don't do it to avoid security failures may caused by connection service
directly from the Silverlight object.
public class Employee
{ public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", FirstName, LastName);
}
}
public int EmployeeNumber { get; set; }
}
On the second part I'll explain how to serialize the objects through JSON.
Technorati Tags:
SilverLight,
JSON
More Posts
Next page »