This is my blog on programming issues and my life as an Systems Developer.
fredag, oktober 27, 2006
Sitecore Instructur at last
I just completed my first instruction in the Sitecore API course. It was actually quite giving and interesting to teach Sitecore on a lower level, surely something I want to do again.
Actually, if everything goes well, my next instruction session will be in Holland sometime late next month.
onsdag, oktober 25, 2006
Dont trust your debugger
I just waisted a couple of hours because of a strange behaviour in the Visual Studio debugger.
Consider the following code:
object obj = new String('a',1); //"a"
string str = new String('a',1); //"a"
Console.Out.WriteLine(obj == str); //ln1
Console.Out.WriteLine(str == obj); //ln2
Console.Out.WriteLine((string)obj == str);//ln3
Console.Out.WriteLine(str ==(string)obj); //ln4
Console.Out.WriteLine(obj.Equals(str)); //ln5
Console.Out.WriteLine(str.Equals(obj)); //ln6
Now, add breakpoints in Visulal Studio on line 1 to 6 - and make the debugger evaluate the expression before it is printet to the console.
What would you (the debugger) expect the output to be? The Visual Studio Debugger says:
true
true
true
true
true
true
This is however not the case. The actual output is:
false
false
true
true
true
true
There is really nothing strange about the result. The == operator does not just call the Equals method blindly and virtually as one might expect. It is actually an operator that compares references unless overridden.
By default the == operator compares for reference equality. So if == tests for reference equality, this would explain the behavior of the result of ln1 and ln2, but not ln 3 and 4. This is because the == operator has been overridden in the String class to call the Equals method, thus comparing the value of the string rather than its reference. (this explains ln 3 and 4).
The runtime system determines which operator to call based on the runtime type (the type of the reference rather than the type of the instance). In ln 1 and 2 the == operator of the Object class is used, where in ln3 and ln4 the operator as defined in the String class is used.
So much for the == operator. The strange thing however, is that the Visual Studio debugger does not seam to get this. (VS2003). I used a lot of time debugging an expression inside an 'if' statement, which evaluated to false (by the debugger) but the if - statement - body was entered anyway. Grrr – I’m a bit pissed at the debugger.
torsdag, august 31, 2006
Media Library Posts Removed
A Sitecore Core Developer goes solo
My decision has been a hard one and has nothing to do with me not being happy with working on this amazing product. I simply missed the kick of being around real customers and following projects through.
During the time of employment at Sitecore I have learned allot of hardcore stuff. Specially working with Ole and Jacob (Core Developers and innovators of Sitecore) has been extremely giving. Before working at Sitecore, I was a consultant and have therefore worked with allot of developers through the years. Without comparison, the guys at Sitecore are the most competent. I will truly miss the high level of abstraction there guys are able to discuss architecture on.
However, this will not be the end of my work with Sitecore. Sitecore will make sure that I become a Sitecore Certified Trainer as soon as possible and I have decided that my new firm (Delegate ApS ) is to become a certified Sitecore Partner within a month or so. This means that I will finally sit on the other end of the table and experience actually working with the product, instead of creating the product.
All the luck in the world to Sitecore here at the end of my voyage as an Sitecore employee.
tirsdag, maj 02, 2006
InPlaceEditExtender for April CTP release of ATLAS
Download the control from Nikhil's blog, and replace the javascript with the following javascript and you will have the InPlaceEditExtender control for April CTP:
Type.registerNamespace('nStuff.Samples.InPlaceEdit');
nStuff.Samples.InPlaceEdit.InPlaceEditBehavior = function() {
nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.initializeBase(this);
var _labelCssClass;
var _labelHoverCssClass;
var _labelElement;
var _isEditing = false;
var _isInputControl = false;
var _textBoxBlurHandler;
var _labelFocusHandler;
var _labelMouseOverHandler;
var _labelMouseOutHandler;
var _validatedHandler;
this.get_isEditing = function() {
return _isEditing;
}
this.get_labelCssClass = function() {
return _labelCssClass;
}
this.set_labelCssClass = function(value) {
_labelCssClass = value;
}
this.get_labelHoverCssClass = function() {
return _labelHoverCssClass;
}
this.set_labelHoverCssClass = function(value) {
_labelHoverCssClass = value;
}
this.beginEdit = function() {
if (_isEditing) {
return;
}
var textBoxElement = this.control.element;
textBoxElement.style.display = '';
_labelElement.style.display = 'none';
if(!textBoxElement.disabled)
textBoxElement.focus();
_isEditing = true;
this.raisePropertyChanged('isEditing');
}
this.dispose = function() {
if (_labelElement) {
_labelElement.detachEvent('onfocus', _labelFocusHandler);
_labelElement.detachEvent('onmouseover', _labelMouseOverHandler);
_labelElement.detachEvent('onmouseout', _labelMouseOutHandler);
_labelElement = null;
_labelFocusHandler = null;
_labelMouseOverHandler = null;
_labelMouseOutHandler = null;
}
if (_textBoxBlurHandler) {
var textBoxElement = this.control.element;
textBoxElement.detachEvent('onblur', _textBoxBlurHandler);
_textBoxBlurHandler = null;
}
if (_validatedHandler) {
this.control.validated.remove(_validatedHandler);
_validatedHandler = null;
}
nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.callBaseMethod(this, 'dispose');
}
this.endEdit = function() {
if (!_isEditing) {
return;
}
if (_isInputControl && this.control.get_isInvalid()) {
return;
}
var textBoxElement = this.control.element;
_labelElement.innerHTML = textBoxElement.value;
_labelElement.style.display = 'block';
textBoxElement.style.display = 'none';
_isEditing = false;
this.raisePropertyChanged('isEditing');
}
this.getDescriptor = function() {
var td = nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.callBaseMethod(this, 'getDescriptor');
td.addProperty('isEditing', Boolean, /* readOnly */ true);
td.addProperty('labelCssClass', String);
td.addProperty('labelHoverCssClass', String);
td.addMethod('beginEdit');
td.addMethod('endEdit');
return td;
}
this.initialize = function() {
nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.callBaseMethod(this, 'initialize');
_labelElement = document.createElement('LABEL');
var textBoxElement = this.control.element;
var textBoxBounds = Sys.UI.Control.getBounds(textBoxElement);
var containerElement = document.createElement('SPAN');
textBoxElement.parentNode.insertBefore(containerElement, textBoxElement);
containerElement.appendChild(textBoxElement);
containerElement.appendChild(_labelElement);
textBoxElement.style.display = 'none';
if(textBoxElement.tagName == 'SELECT')
_labelElement.innerHTML= textBoxElement.options[textBoxElement.selectedIndex].text;
else
_labelElement.innerHTML = textBoxElement.value;
_labelElement.tabIndex = textBoxElement.tabIndex;
_labelElement.className = _labelCssClass;
_labelElement.style.display = 'block';
_labelElement.style.width = textBoxBounds.width + 'px';
_labelElement.style.height = textBoxBounds.height + 'px';
_textBoxBlurHandler = Function.createDelegate(this, this._onTextBoxBlur);
_labelFocusHandler = Function.createDelegate(this, this._onLabelFocus);
_labelMouseOverHandler = Function.createDelegate(this, this._onLabelMouseOver);
_labelMouseOutHandler = Function.createDelegate(this, this._onLabelMouseOut);
textBoxElement.attachEvent('onblur', _textBoxBlurHandler);
if (Sys.Runtime.get_hostType() == Sys.HostType.InternetExploreJ) {
_labelElement.attachEvent('onfocus', _labelFocusHandler);
}
else {
_labelElement.attachEvent('onclick', _labelFocusHandler);
}
_labelElement.attachEvent('onmouseover', _labelMouseOverHandler);
_labelElement.attachEvent('onmouseout', _labelMouseOutHandler);
if (Sys.UI.InputControl.isInstanceOfType(this.control)) {
_isInputControl = true;
_validatedHandler = Function.createDelegate(this, this._onValidated);
this.control.validated.add(_validatedHandler);
}
}
this._onLabelFocus = function() {
if (_labelHoverCssClass && _labelHoverCssClass.length) {
Sys.UI.Control.removeCssClass(_labelElement, _labelHoverCssClass);
}
this.beginEdit();
}
this._onLabelMouseOut = function() {
if (_labelHoverCssClass && _labelHoverCssClass.length) {
Sys.UI.Control.removeCssClass(_labelElement, _labelHoverCssClass);
}
}
this._onLabelMouseOver = function() {
if (_labelHoverCssClass && _labelHoverCssClass.length) {
Sys.UI.Control.addCssClass(_labelElement, _labelHoverCssClass);
}
}
this._onTextBoxBlur = function() {
this.endEdit();
}
this._onValidated = function(sender, eventArgs) {
if (this.control.get_isInvalid()) {
this.beginEdit();
}
}
}
//Type.registerSealedClass('nStuff.Samples.InPlaceEdit.InPlaceEditBehavior', Sys.UI.Behavior);
nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.registerSealedClass('nStuff.Samples.InPlaceEdit.InPlaceEditBehavior', Sys.UI.Behavior);
Sys.TypeDescriptor.addType('nk', 'inPlaceEdit', nStuff.Samples.InPlaceEdit.InPlaceEditBehavior);
tirsdag, april 11, 2006
Sitecore performance
The consequenses include:
1) Compilation of pages takes longer
2) Code executes slower
3) More memory is used at runtime
4) Scripts and images from WebResources.axd are not cached.
This is specially Sitecore relevant.
For details, see Scott's blog post.
http://weblogs.asp.net/scottgu/archive/2006/04/11/442448.aspx
fredag, april 07, 2006
.NET Remoting in Sitecore
Hopefully the Remoting features will be stable enough to make the final release.
To enable your non-sitecore project (for example a Forms application) to use Sitecore Remoting, simply add a reference to Sitecore.Kernel.dll and you are good to go.
Access to Sitecore API is achieved through the new Sitecore.Remoting namespace, where you will have to know about two new types: The RemoteFactory and RemotingClientConfigurator. Only one line of code is necessary in order to get a remote reference to Sitecore:
Sitecore.Remoting.RemotingClientConfigurator.Configure(_sitecoreurl, "admin", "");
This snippet sets up the connection to Sitecore at a given url, with the username 'admin' and the empty password.
To access Sitecore objects, simply use the new RemoteFactory object (a remoting enabled version of the Factory class):
RemoteFactory factory = new RemoteFactory();
You now have access to all Sitecore objects. For example:
factory.GetDatabase("master").GetRootItem()
This will get you the root item of the master database.
In a later post, I will show how Sitecore can be managed and scripted through Microsofts new shell: MONAD using the new Remoting features.
Hopefully other more or less useful programs will be developed as a result of the introduction of .NET Remoting in Sitecore. I talked to Alexy Rusakov (Sitecore developer from our Ukraine division) about creating an addin to the Google toolbar showing a list of items who's workflow step is assigned to a specific user.
Only your imagination is the limit :-)
Regards