oktober 2008 - Posts

I had the pleasure of getting a rather large pivoted list of numbers to import today, where of course the data to import were niftily marked with a green color.

Of course I have my "convert pivoted stuff to tabluar data" macro ready, but I was unsure how to attack the problem of limiting my list to updated stuff (green rows).

Luckily my mind was quicker than my need to do heavy lifting, so I came up with this nice little custom function:

Public Function GetColor(ref As Range) As String
    Dim color As String
    color = Hex(ref.Cells(1, 1).Interior.color)
    GetColor = color & Replace(Space(6 - Len(color)), " ", "0")
End Function

With it, I could add a column with the following formula:

=GetColor(Table1[[#This Row];[ColoredColumn]])

Et voilá, out comes a nicely formatted hexadecimal color for me to filter on:

Some data 50D092
Some unformatted data FFFFFF
More formatted 50D092
Yellow data FFFF00
And some red data FF0000

If you haven't written custom Excel functions before, the trick is to put them in a module in the VBA project. Excel does not look for custom functions in ThisWorkbook or the Sheetn classes.

Of course, later in the day I found that filtering by color is a new feature in 2007. :P
http://msdn.microsoft.com/en-us/library/cc952296.aspx

 

Posted 28. oktober 2008 23:42 by lea | with no comments
Filed under: ,

I thought of this the other day and wrote a post about it, but my browser crashed when I hit "publish". Might have been a cosmic hint to think it through, but here goes again. :P

To fix a long demanded requirement of uploading multiple files at once to our CMS tool, we finally came out with a Silverlight 2 control handling the issue. (Ended up rather nice :) )
When I copied the .xap to a web app I was gonna use it in, put in a reference to the silverlight dll and referenced the assembly in my user control, the IDE promptly told me to include a scriptmanager too. All right, I thought, that's reasonable.. But when I opened the toolbox to drag one out, I had to find it under the "AJAX" tab.

Whatever happened to good old DHTML?

There's obviously no asynchronous operations when scripting creation of an object tag clientside, and there's not much XML involved either (the contents of the .xap aside). So that leaves us with some HTML and some JavaScript modding the DOM.
In the old days, that was DHTML.
In the old days, I wrote AJAX without knowing it was AJAX using the Remote Scripting Java applet included in Visual InterDev 6.0. I even used Netscape and Access, but I was a devil with DHTML.

Can we please put the hats where they ought to be again? ;)

Posted 17. oktober 2008 06:41 by lea | with no comments
Filed under: , , ,

We got an urgent request today to help a client wrap an internal web application in a custom FireFox browser with an accompagnying .msi installer.

We started hacking along on a fresh 3.0.3 setup package, modding userchrome.css to remove menu items and installing this and that extension. When I was half green in the face and complained loudly to a colleague who hadn't listened to us, he just lit up and uttered "Prism" with a big grin. Saved my day! It's a side project of Mozilla for a light-weight FF installation without any toolbars or other browser clutter. It just shows the web app, and that's it.

(Who at the FF team figured the help menu should be named #helpMenu, when file, edit etc. are #file-menu? And why is the history menu named #go-menu, when all other are equal? God bless Prism...)

We didn't accomplish the .msi installer, but at least we managed to produce a nice small installer using Nullsofts NSIS. Mostly because I found a more or less finished NSIS script for Prism, but also because it's open source and free. And it supported silent install, and passed the customer's policy. :P

All in all, I'm rather happy about the result, and the customer seems rather happy too. :)

Here's the resources:
Prism: http://labs.mozilla.com/projects/prism/
NSIS: http://nsis.sourceforge.net/Main_Page
NSIS Script (bottom of page): http://labs.mozilla.com/forum/comments.php?DiscussionID=285
(Thanks to "royce" https://labs.mozilla.com/forum/account.php?u=1963)

Shortened down and line-break fixed NSIS script:

;NSIS Modern User Interface 

;-------------------------------- 
; Start 

!include "MUI2.nsh" 

!define MUI_PRODUCT "Name of webapp" 
!define MUI_VERSION "" 
!define MUI_BRANDINGTEXT "Your company here" 
CRCCheck On 

;!include "${NSISDIR}\Contrib\Modern UI\System.nsh" 

;-------------------------------- 
;General 

;Name and file 
Name "Name of webapp" 
OutFile "setup.exe" 

;Default installation folder 
InstallDir "$PROGRAMFILES\Prism" 

;Get installation folder from registry if available 
InstallDirRegKey HKCU "Software\Prism" "" 

;Request application privileges for Windows Vista 
RequestExecutionLevel user 

;-------------------------------- 
;Interface Settings 

!define MUI_ABORTWARNING 
!define MUI_ICON "---PATH TO SETUP ICON HERE---"; There's some in the NSIS folder
!define MUI_UNICON "---PATH TO SETUP ICON HERE---"
!define MUI_WELCOMEPAGE   
!define MUI_UNINSTALLER 
!define MUI_UNCONFIRMPAGE 
!define MUI_FINISHPAGE   

;Pages 

!insertmacro MUI_PAGE_WELCOME 
!insertmacro MUI_PAGE_INSTFILES 

# These indented statements modify settings for MUI_PAGE_FINISH 
!define MUI_FINISHPAGE_NOAUTOCLOSE 
!define MUI_FINISHPAGE_RUN 
!define MUI_FINISHPAGE_RUN_CHECKED 
!define MUI_FINISHPAGE_RUN_TEXT "Start -- YOUR APP NAME HERE --" 
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink" 

!insertmacro MUI_PAGE_FINISH		 


;-------------------------------- 
;Languages 

!insertmacro MUI_LANGUAGE "English" 

;--------------------------------  

;-------------------------------- 
;Installer Sections 

Section "Install Section" SecInstall 

;  set the context for $SMPROGRAMS and other shell folder to the 'current' user 
SetShellVarContext current 

;  PRISM webApp data is recursively copied from yourAppAppData to "$APPDATA\WebApps" 
SetOutPath "$APPDATA\WebApps\-- YOUR PRISM APP NAME HERE --@prism.app\" 
File /r --- YOUR APPDATA FOLDER HERE --- \WebApps\-- YOUR PRISM APP NAME HERE --@prism.app\* 

;  PRISM application data is recursively copied from yourAppPgmFiles to "$APPDATA\yourApp\Prism" 
SetOutPath "$PROGRAMFILES\Prism" 
File /r C:\Program Files\Prism\*   

;windirExists: 
;Store installation folder 
WriteRegStr HKCU "Software\Prism" "" $INSTDIR 


;Create Shortcut links 
CreateShortcut "$DESKTOP\${MUI_PRODUCT}.lnk" "$PROGRAMFILES\Prism\prism.exe" "-override $\"$APPDATA\WebApps\-- YOUR PRISM APP NAME --@prism.app\override.ini$\" -webapp -- YOUR PRISM APP NAME --@prism.app" "$APPDATA\WebApps\-- YOUR PRISM APP NAME --@prism.app\icons\default\webapp.ico"

;Create uninstaller 
;write uninstall information to the registry 
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MUI_PRODUCT}" "DisplayName" "${MUI_PRODUCT} (remove only)" 
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MUI_PRODUCT}" "UninstallString" "$INSTDIR\Uninstall.exe"  
WriteUninstaller "$INSTDIR\Uninstall.exe" 


SectionEnd 

;-------------------------------- 
;Uninstaller Section 

Section "Uninstall" 

;  set the context for $SMPROGRAMS and other shell folder to the 'current' user 
SetShellVarContext current 

;ADD YOUR OWN FILES HERE... 

Delete "$DESKTOP\${MUI_PRODUCT}.lnk"  
Delete "$INSTDIR\Uninstall.exe" 

;Delete Files  
RMDir /r "$INSTDIR\*.*"   

RMDir "$INSTDIR"   
RMDir "$PROGRAMFILES\Prism" 
RmDir "$APPDATA\WebApps\-- YOUR PRISM APP NAME --@prism.app" 

;Delete Uninstaller And Unistall Registry Entries 
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\${MUI_PRODUCT}" 
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${MUI_PRODUCT}"   
DeleteRegKey /ifempty HKCU "Software\Prism" 

SectionEnd 


Function LaunchLink 
SetShellVarContext current	 

ExecShell "" "$DESKTOP\${MUI_PRODUCT}.lnk" 
FunctionEnd 

[Edit: The problem of eager-loading the stuff I ask for in expand is solved]

I didn't remember when first writing the code and this post that I've got a DataLoadOptions override in a custom context wrapped around the original Linq to SQL model. The Catalog/Items association in the example below is never eager-loaded, so of course I have to add a LoadWith(catalog => catalog.Items) option on the innermost context's DataLoadOptions. Now my .Expand("Items") call gives me a larger set of data and I'm most happy. Just feeling quite stupid not knowing my own API. :P

The code now looks like the attractive:

DataServiceQuery<Catalog> catalogQuery = context.Catalogs
    .Expand(
"Items/ItemFields/TemplateField")
    .Where(c => c.ParentId == (
int)rootCatalogId) as DataServiceQuery<Catalog>;

catalogQuery.BeginExecute(
   
delegate(IAsyncResult result)
    {
        catalogs = catalogQuery.EndExecute(result).ToList();
        AllDone();
    },
null);

The original solution was quite fun to write tho:

[Warning: See bolded text below]

I've been fiddling a bit with an ADO Data Service and the expand method. Can't seem get it to work, or I don't get to know when the associations are loaded.

So I started looking into LoadProperty, but Silverlight wants to call everything asynchronously, so if I loop in the callbacks, I just generate a lot more callbacks, and never know when the last one occurs.

Enter the NotifyingStack. :P

	public class NotifyingStack<T> : Stack<T>
	{
		public event EventHandler OnPopped;

		public NotifyingStack(EventHandler popped) : base()
		{
			OnPopped = popped;
		}

		public new T Pop()
		{
			T obj = base.Pop();
			if (OnPopped != null)
				OnPopped(this, EventArgs.Empty);
			return obj;
		}
	}

Now I can do this:

		private void PopulateSubCatalogsWithItems(object rootCatalogId)
		{
			DataServiceQuery<Catalog> catalogQuery = context.Catalogs
				.Expand("Items/ItemFields")
				.Where(c => c.ParentId == (int)rootCatalogId) as DataServiceQuery<Catalog>;

			justAStack = new NotifyingStack<object>(new EventHandler(OnPop));
			justAStack.Push(null);
			catalogQuery.BeginExecute(
				delegate(IAsyncResult catalogQueryResult)
				{
					IEnumerable<Catalog> catalogResult = catalogQuery.EndExecute(catalogQueryResult);
					catalogs = catalogResult.ToList();
					foreach (Catalog catalog in catalogs)
					{
						justAStack.Push(null);
						context.BeginLoadProperty(catalog, "Items",
							delegate(IAsyncResult itemQueryResult)
							{
								IEnumerable<Item> items = syzwebContext.EndLoadProperty(itemQueryResult).Cast<Item>();
								foreach (Item item in items)
								{
									justAStack.Push(null);
									syzwebContext.BeginLoadProperty(item, "ItemFields",
										delegate(IAsyncResult itemFieldResult)
										{
											syzwebContext.EndLoadProperty(itemFieldResult);
											justAStack.Pop();
										}, null);
								}
								justAStack.Pop();
							}, null);
					}
					justAStack.Pop();
				}
				, catalogQuery);
			
		}

		private void OnPop(object sender, EventArgs e)
		{
			System.Diagnostics.Debug.WriteLine(justAStack.Count);
			if (justAStack.Count == 0)
			{
				AllDone();
			}
		}

I was first experimenting with a timer checking a regular stack, but when trying to add stuff to the UserControl, Silverlight threw a cross threading exception.

In this case, the event handler is in the right thread, and as long as I'm diciplined with the pushing and popping, the AllDone method will only be called once when all the data is loaded. :)

Now, if anyone have a good laugh because you know how to get the expand method to instruct the BeginExecute method to get a big package, ie. by altering the server side service, please gimme a comment. (I've been looking at the xml from the ADO Service, and it only generates urls to the data for the expanded properties)

Turns out though, I need a lot more than the stuff I got so far. So I have to keep this little trick up my sleave for something else. This method would create about a 100 small chatty calls to the server before done, hence I'm gonna [Edit: Remember my DataLoadOptions in the future]. :)

(But it was real fun doing it)

 

[Edit: This post is a continuation of this post. The latter contains some links to some of the code used. For instance VarianceWorkaround] 

It didn't actually turn out quite as I had hoped, (the DataServiceQuery don't know how to translate interface queries to URL queries) but at least I'm able to write code such as this:

private void userControl_Loaded(object sender, RoutedEventArgs e)
{
	IQueryableprojectQuery = 
		context.Project
		.Expand("ProjectEntries")
		.Where(p => p.Name.Contains("project"))
		.Skip(1)
		.Take(2);
	context.BeginExecute(newAsyncCallback(GotResult), projectQuery);
}
protected void GotResult(IAsyncResult result) { IList<Model.Project> projects = context.EndExecuteAsList<Model.Project>(result); }

I generated a proxy for an ADO Data Service using the Entity Model created for my previous posts as described here:
http://msdn.microsoft.com/en-us/magazine/cc794279.aspx

Then hooked up all the interfaces on the generated entities and created these two methods on the datacontext:

public void BeginExecute(AsyncCallback callback, IQueryable queryable)
{
    queryable.GetType().GetMethod(
"BeginExecute").Invoke(queryable,
        new object[] { callback, queryable });
}


public IList<T> EndExecuteAsList<T>(IAsyncResult result) where T : Model.OPWObject
{
    DataServiceQuery query = result.AsyncState as System.Data.Services.Client.DataServiceQuery;
    Type elementType = query.ElementType;
    System.Reflection.
MethodInfo toListGenericMethod = typeof(Enumerable).GetMethod("ToList")
        .MakeGenericMethod(
new Type[] { elementType });
    System.Data.Services.Client.
QueryOperationResponse queryResponse =
        query.GetType().GetMethod(
"EndExecute").Invoke(result.AsyncState, new object[] { result })
        as
System.Data.Services.Client.QueryOperationResponse;
    System.Collections.
IList list = toListGenericMethod.Invoke(null, new object[] { queryResponse })
        as System.Collections.IList;

    System.Reflection.MethodInfo listConvertMethod = null;
    foreach (System.Reflection.MethodInfo method in typeof(VarianceWorkaround).GetMethods())
        if (method.ReturnType.Name == "IList`1")
        {
            listConvertMethod = method;
            break;
        }

    System.Reflection.MethodInfo genericListConvert = listConvertMethod.MakeGenericMethod(
        new Type[] { elementType, typeof(T) }
    );

    IList<T> retVal = genericListConvert.Invoke(null, new object[] { list }) as IList<T>;
    return retVal;
}

I believe my main concern is to use lists of the interfaces in my UI logic. So as long as I can rely on intellitip in the queries without referencing the "real" type, I'm where I want to be. :)

Of course I need to have some kind of factory method to create instances of the entities, but that's a small sacrifice.

I do wonder though; as I discovered the EndExecute method of the context itself and not just on the DataServiceQueries when I was done; whether my code could be considerably shorter...

[Edit: Once again, I revisit this one, and it's probably still flawed as h***]

I guess the VarianceWorkaround posted here will give you the complete table contents before filtering based on the interface properties. At least that's what happens when using L2S.

Some day soon I'll hopefully manage to create either an ExpressionTreeVisitor to translate, or find or be told a better solution.

 

[Edit: I leave my original ramblings without the accusations.. see my solution further down. :) ] 

I was almost there yesterday, but when I finnaly got all the lines right and ran my test, [Edit]I had probably sat for too long[/Edit].

The following attempt at a repository for ADO.NET Entities throws a sad exception. Anyone?

public IQueryable<T> Repository<T>() where T : class, global::MyNamespace.IEntityInterface
{
   
EdmType theType =
        types.Where(
             t =>
Type.GetType(t.FullName).GetInterface(typeof(T).FullName) != null
        ).FirstOrDefault();
    
Type entityType = Type.GetType(theType.FullName);
   
MethodInfo createQuery = internalContext.GetType().GetMethod("CreateQuery").MakeGenericMethod(entityType);
   
object[] parameters = new object[] { theType.Name, new System.Data.Objects.ObjectParameter[0] };
   
IQueryable queryable = createQuery.Invoke(internalContext, parameters) as IQueryable;
   
if (queryable != null)
       
return ((IQueryable)queryable).Cast<T>(); // Throws the baddie
   
else
       
return null;
}

Throws the following:

System.NotSupportedException: Unable to cast the type 'EntityImpl' to type 'IEntityInterface'. LINQ to Entities only supports casting Entity Data Model primitive types..

[Edit: And here's how my week-end might turn out to include time with my better half after all... :P]

Turns out I'd already posted the answer to my casting woes in my original post. The generics variance wrapper can at least convert enumerables of implemetations to their respective interfaces. Of course this demands dicipline when using (not casting birds as seagulls etc.), but at least I was able to query against the interface. And that's a huge step forward!

I'm gonna dive into the VarianceWorkaround class sometime and see if I can't make it fix IQueryables too.

Here's the working repository method:
(If anyone has any tips on how to get rid of the reflection mess, feel free to come forward)

public IEnumerable<T> Repository<T>() where T : global::IEntity
{
   
// LTE type for source type
    EdmType theType = 
        types.Where(
            t =>
Type.GetType(t.FullName).GetInterface(typeof(T).FullName) != null
       
).FirstOrDefault();

    // Source type
   
Type entityType = Type.GetType(theType.FullName);

    // Get create query method
   
MethodInfo createQuery = internalContext.GetType().GetMethod("CreateQuery").MakeGenericMethod(entityType);
    object[] parameters = new object[] { theType.Name, new System.Data.Objects.ObjectParameter[0] };

    // Get queryable
   
IQueryable queryable = createQuery.Invoke(internalContext, parameters) as IQueryable;
   
if (queryable != null)
    {
       
// source
       
Type enumerableType = Type.GetType("System.Collections.Generic.IEnumerable`1");

       
// Find enumerable override of convert (find better way..?)
        MethodInfo enumerableConvert = null;
       
foreach(MethodInfo method in typeof(VarianceWorkaround).GetMethods())
           
if (method.ReturnType.Name == enumerableType.Name)
            {
                enumerableConvert = method;
                
break;
            }

        // Get typed version of the convert method
       
MethodInfo genericEnumerableConvert = enumerableConvert.MakeGenericMethod(
           
new Type[] { entityType, typeof(T) }
        );
        // Cast the objectquery as IEnumerable<T>
       
IEnumerable<T> retVal = genericEnumerableConvert.Invoke(null, new object[] { queryable }) as IEnumerable<T>;

        return retVal;
    }
    else
       
return null;
}

This is really a scream for comments...

Refering to my previous post about loose coupling, we really don't want to write IThis and IThat when refering to business entities. That's really an issue for me, because I've been breething naming guidelines for a while. Shouldn't an interface be named ISomething and not Something? The implementation gets the honour of being named Something. But differentiating between Something and Something by namespace might also create some confusion?

I think I'm going to call our entity interfaces their domain specific names without the I, but keep calling my service and helper interfaces IWhatever.

Feel free to give any two cents you can spare. :)

Posted 11. oktober 2008 07:20 by lea | with no comments
Filed under: ,

I've been trying to wrap my head around all those patterns and practices flying around without never actually striking a real home run. Even though www.andersnoras.com did a great job trying to explain it all a couple of years ago. After the recent MSDN Live in Oslo and some surfing, I think I finally found some real good samples, most of them from just over the fjord. (http://iridescence.no) :P

Recently we've been discussing wether to use Linq to Entities or Linq to Sql, and both imply dependencies of given classes. The only way to get around it is to declare even your business objects as interfaces, as if the programming against interface instead of implementation of services wasn't enough already. :P

Here's some links to what I found and are hoping to utilize:

Great articles by Fredrik Kalseth about loose coupling of domain model from data repository
http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx
http://iridescence.no/post/Linq-the-Specification-Pattern-and-Encapsulation.aspx

MSDN Article about generics variance wrappers (For converting EntitySet<T> to IList<T>)
http://msdn.microsoft.com/en-us/library/ms228359(VS.80).aspx

Inversion of Control for configurable implementation of the repository (and more)
http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/03/31/ptom-the-dependency-inversion-principle.aspx
http://www.castleproject.org/ (Windsor)

Of course, the man should always get credit:
http://www.martinfowler.com/