Installed dotTrace 3.1
Since I run windows 7 64bit on my laptop, I chose to install the 64bit version of dotTrace. After the the installation, the standalone profiler worked great. It was also showing up in the Visual Studio AddIns menu. However, the purple button (next to the Debug “Play” button”) was greyed out, and the one within the Resharper Unit Testing sessions window was also disabled.
After re-installing, re-booting, and re-filling my cuppa’ coffee, I suddenly remembered that Visual Studio is actually a 32bit application, and that I’d probably want to install the 32bit version of dotTrace if I want them both to play nicely.
Did it.
Problem solved.
FYI
Can you spot what will cause the following NUnit test not to run on TeamCity 4.5?
[TestFixture("Testing some cool things")]
public class CoolThingsFixture
{
[Test]
public void When_Do_Expect()
{
Assert.That(2, Is.EqualTo(1+1));
}
}
hint: TeamCity list it with the ignored tests, yelling “No suitable constructor was found”
During the long, long time it took to get from 1.0RC3 to 2.0, many things have changed, and many things were added. I probably won’t cover it all in this post, and I’ll probably forget a few things that I got so accustomed to use (I have always used trunk versions, even way before I became a committer).
If (like me) you do not like putting stuff in config files that the operations team do not care about, you can now run a Monorail application without the Monorail section in the web.config file.
How? you’d need your Global class to implement IMonoRailConfigurationEvents.
e.g. from many of my websites: (I’m configuring AspView as view-engine)
public void Configure(IMonoRailConfiguration configuration)
{
configuration.ControllersConfig.AddAssembly(Assembly.GetExecutingAssembly());
configuration.ViewEngineConfig.ViewPathRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");
configuration.ViewEngineConfig.ViewEngines.Add(new ViewEngineInfo(typeof(AspViewEngine), false));
}
you can setup many optional things that way. e.g.:
// configue jquery as the validation engine
configuration.JSGeneratorConfiguration.AddLibrary("jquery-1.2.1", typeof (JQueryGenerator))
.AddExtension(typeof (CommonJSExtension))
.ElementGenerator
.AddExtension(typeof (JQueryElementGenerator))
.Done
.BrowserValidatorIs(typeof (JQueryValidator))
.SetAsDefault();
// configure url extensions
configuration.UrlConfig.UseExtensions = false;
delve into the intellisense on the IMonoRailConfiguration interface to find more
The example speaks for itself:
public class State
{
public string Code { get; set; }
}
[return: JSONReturnBinder]
public State[] GetStates()
{
// fake code for the sake of the demonstration
return new[] { new State { Code=“CA” }, new State { Code=“WA” } };
}
will render the JSON representation of the given State array
see http://www.castleproject.org/monorail/documentation/trunk/advanced/routing.html
and http://www.kenegozi.com/blog/2009/02/10/monorail-routing-and-the-homepage-routing-rule.aspx for setting a homepage route
A rescue controller will take care of exceptions that have happened during an Action.
You’d create your rescue controller, implement IRescueController, inherit from SmartDispatcherController, and setup the rescue controller in the RescueAttribute on the regular controller.
see more here: http://www.castleproject.org/monorail/documentation/trunk/usersguide/rescues.html
The C# based view engine became a first class citizen in Monorail. There has been many improvements there during the time, which deserve a separate post perhaps. meanwhile you can look at the aspview tag on this blog: http://www.kenegozi.com/blog/Tag/aspview.aspx
I can’t think of more stuff right now, so ping me if I forgot anything.
Being an Open Source project, with very good test coverage and a very active development, most users that actually run Castle bits in production were running off of trunk anyway.
The trunk is very stable, and the act of “release” should have simply been tagging any single commit to trunk as the 2.0 RTM.
However, we felt that we wanted some more stuff to justify a release – like updating the documentation, re-doing samples and Visual Studio integration packages, etc.
That lead us to a halt, as active committers did not use neither integrations nor samples, and same for the documentation. My personal stand was (and still is) that if someone wanted an official release so badly, then that one should contribute toward this, either with time and work, or with sponsorship money to buy this time and work.
No one did.
A few attempts at these parts was taken, but none concluded.
Meanwhile the project grew more and more, and parts of it became mandatory dependencies to various mainstream projects (such as NHibernate), while Windsor became more and more adopted as an IoC container of choice for many people.
Getting to a single point of approval across the board for the whole castle stack, without breaking third-party projects that depends on parts of Castle, became very difficult.
In order to allow a manageable release process, the project was broken down to its parts. Now we have the four main projects, released on their on, with depending projects using compiled releases of the others.
The main projects are:
More details can be found on the projects page of castle’s website
An all-trunk builds can be retrieved with the aid of the horn-get project.
The reason is rather simple. Monorail depends on almost any other part of the stack. It even has subprojects such as ActiveRecord’s DataBinder (ARDataBind) which depends on ActiveRecord, and a WindsorIntegration project which depends on the IoC stack.
As a result we had to wait to get releases for all other projects.
I still have no idea. There are a few discussions going on about that (such as this one on the new roadmap), and you are all welcome to join the debates.
Tired of setting up stubs for your class under test?
Tired of compile errors when you add one more dependency to a class?
The AutoStubber to the rescue.
Given
interface IServiceA
{
string GetThis(long param);
}
interface IServiceB
{
Do DoThat(string s);
}
class MyService
{
public MyService(IServiceA a, IServiceB b) { ... }
...
}
...
you can write;
var service = new AutoStubber.Create(); // Arrange var theString = "whatever"; service.Stubs().Get .Stub(x=>x.GetThis(0).IgnoreArguments().Return(theString); // Act service.Execute(); // Assert service.Stubs().Get .AssertWasCalled(x=>x.DoThat(theString);
The code for AutoStubber:
* Mind you – it’s not the prettiest, but it gets the job done
public class AutoStubber<T> where T : class
{
static readonly Type TypeofT;
static readonly ConstructorInfo Constructor;
static readonly Type[] ParameterTypes;
static readonly Dictionary<object, AutoStubber<T>> Instances = new Dictionary<object, AutoStubber<T>>();
static AutoStubber()
{
TypeofT = typeof(T);
Constructor = TypeofT.GetConstructors().OrderByDescending(ci => ci.GetParameters().Length).First();
ParameterTypes = Constructor.GetParameters().Select(pi => pi.ParameterType).ToArray();
}
public static AutoStubber<T> GetStubberFor(T obj)
{
return Instances[obj];
}
bool _created;
public T Create()
{
if (_created)
throw new InvalidOperationException("Create can only be called once per AutoStubber");
_created = true;
return Instance;
}
readonly Dictionary<Type, object> _dependencies = new Dictionary<Type, object>();
private T Instance { get; set; }
public AutoStubber()
{
var parameters = new List<object>(ParameterTypes.Length);
foreach (var parameterType in ParameterTypes)
{
var parameter = MockRepository.GenerateStub(parameterType);
parameters.Add(parameter);
_dependencies[parameterType] = parameter;
}
Instance = (T)Constructor.Invoke(parameters.ToArray());
Instances[Instance] = this;
}
public TDependency Get<TDependency>()
{
return (TDependency)_dependencies[typeof(TDependency)];
}
}
public static class AutoStubberExtensions
{
public static AutoStubber<T> Stubs<T>(this T obj)
where T : class
{
return AutoStubber<T>.GetStubberFor(obj);
}
}
I know there is the AutoMockingContainer, and various other stuff out there, but this thing just was very natural to me, it uses a very simple API (do not need to keep reference to the Container), and took me less than an hour to knock off.
An enhancement I consider would be to allow setting pre-created values to some of the parameters. But meanwhile I did not happen to need it.
After a long huge wait, finally Monorail 2.0 is out, get yours from https://sourceforge.net/projects/castleproject/files/
HUGE thanks to John Simons and the rest of the Castle project committers, plus the rest of the good people that have supplied us with patches, bug fixes, and whatnot.
This move somewhat concludes the move from the old 1.0RC3 release from 2007, to the new releases of the Castle stack about two years afterwards.
I’m going to follow up with a couple of “what’s new”, “how-to upgrade” and “why the hell did it take so long” posts soon, so keep watching.
I’ve just found out that my I’m being *quoted in a book !
the book is Testing ASP.NET Web Applications (Wrox Programmer to Programmer) from Ben Hall, a great guy I know from the first UK ALT.NET conf, and another guy, who happens to blog quite rarely, but I do like his
So You Think You’re A Web Developer series. Plus anyone investing time in Web apps testing is a worthy man, not to mention a guy that invests time in educating people into testing their web apps.
* Actually, it’s not anything smart that I’ve been saying, but rather my simple IoC implementation, which I originally created for a tiny project that couldn’t have had *any 3rd party dependency (including Windsor), and is now being used as a manner of teaching what an IoC is and how it can help you. neat, and thx for the credit.
When using Windsor’s logging facility, you’d usually take a dependency of an ILogger in your component, and have Windsor create the logger instance. The logger’s name will be of your component’s full type name.
e.g. for the following component:
namespace My.Application
{
public class UsingLogIntegration
{
readonly ILogger logger;
public UsingLogIntegration(ILogger logger)
{
this.logger = logger;
}
}
}
The logger's name will be My.Application.UsingLogIntegration
At times, you would need to get a logger in a different way, either because you’d want a special name, or you will be in a location where you cannot have Windsor resolve that for you as a dependency (say within an ASP.NET’s Global.asax class, which gets instantiated by ASP.NET, not by Windsor).
The naive approach would be to ask the container for an ILogger, however if you’d try this, you’ll discover that Container.Resolve<ILogger>() will not fit your needs. So what will you do?
Well, the facility also sets an ILoggerFactory, which is in charge of creating loggers. So, do that instead:
var loggerTypeOrName = GetTheTypeForTheLoggerOrAStringIfYouPrefer(); var logger = Container.Resolve().Create(loggerTypeOrName);
ILoggerFactory.Create() can live with a type (will use the full type name as name) or with a string.
So you want to be able to do some logging from your code.
log4net for example, is a very common logging framework for .NET, and using it is pretty straight forward, and the net is full of log4net intros.
Usage example:
namespace My.Application
{
public class UsingLog4netDirectly
{
private static log4net.ILog logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.FullName);
...
...
...
}
}
However, there are some caveats with using it directly.
Windsor, once again, can help a lot with making it much easier. e.g:
namespace My.Application
{
public class UsingLogIntegration
{
readonly ILogger logger;
public UsingLogIntegration(ILogger logger)
{
this.logger = logger;
}
...
...
...
}
}
Windsor will take care of injecting the correct logger instance, with the name set correctly (using the class name, not needing the wacky MethodBase… stuff)
So, what do you set this up?
Assuming you already use Windsor, you need
You actually do not need to reference these assemblies, only make sure they are on the application’s bin folder. If you use the programmatic configuration (like I do), you’d also need the first (the facility) referenced from your code.
container.AddFacility("LoggingFacility", new LoggingFacility(LoggerImplementation.Log4net));
and … that’s it !
You still need to setup log4net’s configuration, and tell the application where it is:
log4net.Config.XmlConfigurator.Configure();
Easy. Instead of configuring the facility, you simply configure another implementation.
container.Register(Component.For
If you'd explore the Castle.Core.Logging namespace you'd find few, very useful built-in implementations, such as a NullLogger (which you get by calling NullLogger.Instance), ConsoleLogger, StreamLogger (write to a file or memory stream), TraceLogger (writes to the diagnostic trace output) and WebLogger (writes to the HttpContext’s Trace, visible at trace.axd).
I got a docx document by email, with an image embedded inside. I needed to take it to Paint.NET for some cropping and resizing. Usually I’d copy the image, then “Paste as New Image” on Paint.NET (using Ctrl+Alt+V, or the Edit menu).
Paint.NET did not recognize the clipboard content as a valid image.
I pasted the image into the good ol’ Paint.exe, then copied from there, and “Pasted as New” in Paint.NET
voila.
Just throw ‘!svn/bc/REVISION_NUMBER/’ to the url, right after the repository root
thx gooli for the superb tip.
We’re using MySql at work, and for that I installed 5.1 on my workstation (Windows 7 RC x64), with all the defaults (next, next, next, …, finish)
Being environmentally friendly (or mentally instable – depends on who you’re asking), I tend to shut down my workstation when I go home at the end of every day.
So – today, when first navigating to a url served by my local working copy, I was greeted with a SystemException telling me that MySql is not responding.
My first reaction was WTF
My following reaction was
Win-R
cmd
net start mysql
Surprisingly enough, instead of the laconic OK, I was greeted with:
The MySQL service could not be started.
A system error has occurred.
System error 1067 has occurred.
My next reaction was back to WTF.
Goggling around I found no meaningful answer, so I went for uninstall/reinstall.
So, Win+MySql (to look for an uninstaller in the Start Menu, lazy me) I stumbled upon “MySQL Server Instance Config Wizard”
This dude apparently can re-do the Instance Configuration thing, and running it (again with the next, …, next, finish ritual) appear to have fixed the problem.
After all I do have something nice to say about MySql. when weird shit happen, there is a tool to make instance re-install rather painless.
All the rest about it is crap.
At time you'd want to store data, related to a DOM element.
storing it directly into the element (either by elm.someArbitraryName = value, or with setAttribute) is wacky. Some browsers might not like you using non standard attributes, so you start using things like 'alt' and 'rel'. Then again, these things has meaning, and storing arbitrary data is ... well, uncool to say the least.
jQuery.data() to the rescue. As jQuery objects are wrappers that HasA DOM elements, and not the DOM elements themselves (as in prototype), storing data on them is like storing data on POJSO (Plain Old JavaScript Objects), and the data() functions allows for an easy way of doing that.
Read on that (and of a few other jQuery tips) at http://marcgrabanski.com/article/5-tips-for-better-jquery-code
Today I opened a GoGrid account, as I'm looking for quite some time to upgrade my hosted environment.
Setting up the account was a breeze, and in a few minutes from starting the process I had a running instance of vs2008 64bit, with IIS and MSSql2005 express.
First impressions:
Good:
Bad:
That's it for now
I've started a new oss project under the name "D9".
the project is hosted at http://code.google.com/p/d-9/
I'm adding all kinds of useful stuff I've written during my years doing .NET, that I didn't have any better place for.
It's fairly empty now, but during the following days I hope to add more stuff in there.
Currently you can find:
What I'm gonna add shortly:
I generally am doing this so I'll have a place for all my recurring stuff (instead of copy&pasting from project to project every now and then). If people will find it useful it'd be great. If people will want to contribute to it it'd be even greater.
License is "new BSD" so feel free to use it if you like
comments, endorsements and insults are welcome as always.
I've just came across a comparison on IoC containers in the .NET world:
Haven't read it yet cuz Im actually off-computer right now (the lappy is attached to the living room TV, and the break in the movie is almost over), but MAN is has COLOUR charts, so you can bet your arse I'm gonna read it later.
Not that I'm excited. I'm pretty sure that (INSERT WINNER HERE LATER) will prove to be the best IoC ever.
The FactorySupportFacility in Windsor is very useful but there's a little something to be aware of when using it.
This facility allows you to tell the container that when a given service is to be resolved, instead of new-ing it, it should call a factory method to obtain an instance.
This is very useful for context objects (like DbContext, HttpContext etc.) , which are usually being supplied by a framework thus you can't have the container instantiate them directly.
So, assuming you want to inject a ISomeContext object into a service, you need to create a factory that can obtain it for you:
public class SomeContextFactory
{
ISomeContext ObtainFromFramework()
{
return SomeFrameworkContext.Current; //or whatever
}
}
then you can setup the container to use that factory when injecting the context
Online examples:
When taking the programmatic road, you must follow this order of doing things:
var facility = new FactorySupportFacility();
container.Kernel.AddFacility("factory.support", facility);
facility.AddFactory<ISomeContext, SomeContextFactory>("some.context", "ObtainFromFramework");If you mix 2 and 3, it would break.
There reason of course is that registering the factory into the facility, mean that the facility needs no know about the current container and kernel. This is being done in step 2 so you simply can't do step 3 before that.
A dude on the ALT.NET Israel mailing list has given the new Google Insights a few things to chew on.
For example, he's shown that there is much more interest in ASP.NET MVC over MonoRail.
So a wonder came up, whether one should choose a framework or a technology should it be highly searched for.
my take on the matter:
I'd look for this type of people in the tech community.
People that:
No matter how you'd turn the search statistics, based on parameter 3 only, any OSS will be way ahead a closed source solution.
Gustavo Ringel also had a say:
I see a lot of articles about how to do stupid things with typed datasets, and much less about how to do great things with ORM's...should i had go for typed datasets instead of NHibernate or other ORM because i have more help of less skilled people?
I'm a big fan of google maps. A simple and yet very effective tool. I wish they had maps for Israel too ...
Anyway, I noticed today that the maps do not load on my FF. started disabling addons one by one (you'd usually blame FireBug ...) but I found out that it was the skype plugin's fault.
hmm. Im not really using it much anyway, and for the rare cases I do need to phone someone abroad, I guess I'll copy and paste into skype.
Following Ayende's post on Patch management approaches using centralized SCM, here are how I would have dealt with the 4 issues that he brings up, using a Decentralised SCM.
I use git, so I'll use git terms here. I guess it's quite similar for other DSCM systems.
Note that I haven't used patches on git development as until now all of my git work was on repositories I had write access to, However the principals are the same (i.e. - all of the tree is local to my machine, thus I can reach any point in the history locally).
First I'll clone the hosted repository to my local machine.
So, using a DSCM, I can work locally with the benefits of a SCM, have as many branches/features as I want. the whole tree is stored locally, and its blazing fast to switch branches, so I can easily work on every aspect I want, and easily create a patch from every node in the history tree, to send to the project owners.
The tools (various small helper libraries) are now under http://svn.castleproject.org:8080/svn/castlecontrib/Tools/
what's in there:
I've been asked about it several times lately, so I'll just put here an oldie that I've been using for a few years now untouched:
1: // MIT license
2: // Copyright 2005-2008 Ken Egozi
3: //
4: // Permission is hereby granted, free of charge, to any person obtaining a copy
5: // of this software and associated documentation files (the "Software"), to deal
6: // in the Software without restriction, including without limitation the rights
7: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8: // copies of the Software, and to permit persons to whom the Software is
9: // furnished to do so, subject to the following conditions:
10: //
11: // The above copyright notice and this permission notice shall be included in
12: // all copies or substantial portions of the Software.
13: //
14: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20: // THE SOFTWARE.
21:
22: using System;
23: using System.Collections.Generic;
24: using System.Text;
25: using System.Security.Cryptography;
26: using System.Collections;
27:
28: namespace KenEgozi.CryptographicServices
29: {
30: public static class Hashing
31: {
32: private static Hashtable hashAlgorithms = Hashtable.Synchronized(new Hashtable());
33:
34: /// <summary>
35: /// Hashing a given string with SHA2.
36: /// </summary>
37: /// <param name="data">Data to hash</param>
38: /// <returns>Hashed data</returns>
39: public static string HashData(string data)
40: {
41: return HashData(data, HashType.SHA256);
42: }
43:
44: /// <summary>
45: /// Hashing a given string with any of the supported hash algorithms.
46: /// </summary>
47: /// <param name="data">Data to hash</param>
48: /// <param name="hashType">Hashing algorithm to use</param>
49: /// <returns>Hashed data</returns>
50: public static string HashData(string data, HashType hashType)
51: {
52: HashAlgorithm hash = GetHash(hashType);
53: byte[] bytes = (new UnicodeEncoding()).GetBytes(data);
54: byte[] hashed = hash.ComputeHash(bytes);
55: StringBuilder sb = new StringBuilder(64);
56: foreach (byte b in hashed)
57: sb.AppendFormat("{0:x2}", b);
58: return sb.ToString();
59: }
60:
61: private static HashAlgorithm GetHash(HashType hashType)
62: {
63: if (!hashAlgorithms.ContainsKey(hashType))
64: hashAlgorithms.Add(hashType, CreateaHashAlgorithm(hashType));
65: return hashAlgorithms[hashType] as HashAlgorithm;
66: }
67:
68: private static HashAlgorithm CreateaHashAlgorithm(HashType hashType)
69: {
70: switch (hashType)
71: {
72: case HashType.MD5:
73: return new MD5CryptoServiceProvider();
74: case HashType.SHA1:
75: return new SHA1Managed();
76: case HashType.SHA256:
77: return new SHA256Managed();
78: case HashType.SHA384:
79: return new SHA384Managed();
80: case HashType.SHA512:
81: return new SHA512Managed();
82: default:
83: throw new NotImplementedException();
84: }
85: }
86: }
87:
88: public enum HashType
89: {
90: MD5,
91: SHA1,
92: SHA256,
93: SHA384,
94: SHA512
95: }
96: }
Not beautiful, however useful.
You can download this file from here (just remove the .txt - the server doesn't serve .cs files directly)
btw, the colouring of the source was made with the help of http://www.manoli.net/csharpformat/, even though I had to do some manual tweaking to make it work with this blog. If colours of reserved words, comments etc. do not appear, then please refresh your browser's cache to get the updated css
I really don't need to add anything, right?
Installed it myself today. Appear to be a bit faster, and to eat up less memory.
The Google Toolbar and FireFTP were updated automatically.
I needed to manually re-install FireBug and IE-Tab
btw, does anybody know where did the Back and Forward buttons has gone to? Im using the keyboard usually, but sometimes (especially during in-office-lunch-time) I need to click the Back thing with the mouse
UPDATE: it appear that as part of the upgrade, FF3 has inherited my customised toolbars and that's why it was looking weird. So I right-clicked on the toolbar -> customise, the clicked "Restore Default Set". All the buttons came back, then I rearranged the toolbar to my liking.
Following a question from NHibernate's users list:
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<appender name="rollingFile"
type="log4net.Appender.RollingFileAppender,log4net" >
<param name="File" value="log.txt" />
<param name="AppendToFile" value="true" />
<param name="DatePattern" value="yyyy.MM.dd" />
<layout type="log4net.Layout.PatternLayout,log4net">
<conversionPattern value="%d %p %m%n" />
</layout>
</appender>
<logger name="NHibernate.SQL">
<level value="ALL" />
<appender-ref ref="rollingFile" />
</logger>
</log4net>
and configuring your application to use Log4Net (if you hadn't done that anyway):
log4net.Config.XmlConfigurator.Configure();
If you wan't to know more about log4net and it's configuration options - look here or use your favorite search engine.
From the website:
Current version includes following features:
The coolest thing is the ability to spell check identifiers. I'd love it.
It's at http://www.agentsmithplugin.com/ and I found out about it on Castle's dev list (thx Victor)
As I'm trying to avoid xml files as much as possible, when I do find the need to xpath, I always need to refresh my memory on the matter.
Today I've been working with kml files, and the need for some simple xpath queries came up, forcing me to do some trial-and-error in an area I don't really like ...
Next time I'll have Visual XPath to help me with that.
the new stuff:
Examples:
Reusing clauses:
FromClause from = new FromClause(SQL.Blogs);
WhereClause where = new WhereClause(SQL.Blogs.Id == 2);
SQLQuery q1 = SQLQuery
.Select(SQL.Blogs.Id)
.From(from)
.Where(where);
SQLQuery q2 = SQLQuery
.Select(SQL.Blogs.Name)
.From(from)
.Where(where);
Console.WriteLine(q1);
Console.WriteLine(q2);
makes
SELECT
[dbo].[Blogs].[Id]
FROM
[dbo].[Blogs]
WHERE
([dbo].[Blogs].[Id] = 2)
SELECT
[dbo].[Blogs].[Name]
FROM
[dbo].[Blogs]
WHERE
([dbo].[Blogs].[Id] = 2)
Operators:
SQLQuery q1 = SQLQuery
.Select(SQL.Blogs.Id)
.From(SQL.Blogs)
.Where(SQL.Blogs.Id > 2 || SQL.Blogs.Name == "Ken");
Console.WriteLine(q1);
makes
SELECT
[dbo].[Blogs].[Id]
FROM
[dbo].[Blogs]
WHERE
(([dbo].[Blogs].[Id] > 2) OR ([dbo].[Blogs].[Name] = N'Ken'))
OrderBy Clause:
SQLQuery q = SQLQuery
.Select(SQL.Blogs.Id)
.From(SQL.Blogs)
.Where(SQL.Blogs.Id > 2)
.OrderBy(Order.By(SQL.Blogs.Id), Order.By(SQL.Blogs.Name).Desc);
Console.WriteLine(q);
makes
SELECT
[dbo].[Blogs].[Id]
FROM
[dbo].[Blogs]
WHERE
([dbo].[Blogs].[Id] > 2)
ORDER BY
[dbo].[Blogs].[Id],
[dbo].[Blogs].[Name] DESC
Didn't have time to upload a binary, but you can simply grab the source and build yourself. it has absolutely no dependencies but .NET 2.0
Where from?
http://svn.castleproject.org:8080/svn/castlecontrib/Castle.Tools.SQLQueryGenerator/trunk/
UPDATE (22/06/2008):
The source has slightly moved (to a sub folder):
http://svn.castleproject.org:8080/svn/castlecontrib/Tools/Castle.Tools.SQLQueryGenerator/
A tool that generates a strongly typed representation of a relational database, to be used for generating SQL queries in a type-safe fashion, with the aid of intellisense.
UPDATE (22/06/2008):
The source has slightly moved (to a sub folder):
http://svn.castleproject.org:8080/svn/castlecontrib/Tools/Castle.Tools.SQLQueryGenerator/
Usage sample (from Examples.cs in the test project:
SQLQuery q = SQLQuery
.Select(SQL.Blogs.Id, SQL.Blogs.Name)
.From(SQL.Blogs);
Console.WriteLine(q);
Would print out:
SELECT
[dbo].[Blogs].[Id],
[dbo].[Blogs].[Name]
FROM
[dbo].[Blogs]
Not impressed? Well,
dbo_ForumMessages Message = SQL.ForumMessages.As("Message");
dbo_ForumMessages Parent = SQL.ForumMessages.As("Parent");
SQLQuery q = SQLQuery
.Select(Message.Id, Message.ParentId, Message.Content)
.From(Message)
.Join(Parent, Message.ParentId == Parent.Id);
Console.WriteLine(q);
Will spit out
SELECT
[Message].[Id],
[Message].[ParentId],
[Message].[Content]
FROM
[dbo].[ForumMessages] AS [Message]
JOIN [dbo].[ForumMessages] AS [Parent] ON
([Message].[ParentId] = [Parent].[Id])
Need parameters?
Parameter<int> blogId = new Parameter<int>("BlogId");
SQLQuery q = SQLQuery
.Select(SQL.Blogs.Id, SQL.Blogs.Name)
.From(SQL.Blogs)
.Where(SQL.Blogs.Id == blogId);
Console.WriteLine(q);
would echo
SELECT
[dbo].[Blogs].[Id],
[dbo].[Blogs].[Name]
FROM
[dbo].[Blogs]
WHERE
([dbo].[Blogs].[Id] = @BlogId)
Nothing fancy.
With a little help from Moran Benisty, here's the script I use to get the metadata I need for the SQLQueryGenerator:
SELECT schemas.name AS [Schema],
tables.name AS [Table],
columns.name AS [Column],
CASE
WHEN columns.system_type_id = 34 THEN 'byte[]'
WHEN columns.system_type_id = 35 THEN 'string'
WHEN columns.system_type_id = 36 THEN 'System.Guid'
WHEN columns.system_type_id = 48 THEN 'byte'
WHEN columns.system_type_id = 52 THEN 'short'
WHEN columns.system_type_id = 56 THEN 'int'
WHEN columns.system_type_id = 58 THEN 'System.DateTime'
WHEN columns.system_type_id = 59 THEN 'float'
WHEN columns.system_type_id = 60 THEN 'decimal'
WHEN columns.system_type_id = 61 THEN 'System.DateTime'
WHEN columns.system_type_id = 62 THEN 'double'
WHEN columns.system_type_id = 98 THEN 'object'
WHEN columns.system_type_id = 99 THEN 'string'
WHEN columns.system_type_id = 104 THEN 'bool'
WHEN columns.system_type_id = 106 THEN 'decimal'
WHEN columns.system_type_id = 108 THEN 'decimal'
WHEN columns.system_type_id = 122 THEN 'decimal'
WHEN columns.system_type_id = 127 THEN 'long'
WHEN columns.system_type_id = 165 THEN 'byte[]'
WHEN columns.system_type_id = 167 THEN 'string'
WHEN columns.system_type_id = 173 THEN 'byte[]'
WHEN columns.system_type_id = 175 THEN 'string'
WHEN columns.system_type_id = 189 THEN 'long'
WHEN columns.system_type_id = 231 THEN 'string'
WHEN columns.system_type_id = 239 THEN 'string'
WHEN columns.system_type_id = 241 THEN 'string'
WHEN columns.system_type_id = 241 THEN 'string'
END AS [Type],
columns.is_nullable AS [Nullable]
FROM sys.tables tables
INNER JOIN sys.schemas schemas ON (tables.schema_id = schemas.schema_id )
INNER JOIN sys.columns columns ON (columns.object_id = tables.object_id)
WHERE tables.name <> 'sysdiagrams'
AND tables.name <> 'dtproperties'
ORDER BY [Schema], [Table], [Column], [Type]
Quick, Dirty, Working.
Anyone up to contributing a similar thing for SQL 2000 / MySql / Oracle / Postgres / MS-ACCESS ?
it's going to be subversion-ed really soon.
Imagine you could write that in your IDE:
SQLQuery q = SQLQuery
.Select(SQL.Blogs.Id, SQL.Blogs.Name)
.From(SQL.Blogs)
.Join(SQL.Posts, Join.On(SQL.Blogs.Id == SQL.Posts.BlogId))
.Where(SQL.Blogs.Name != "Ken's blog");
Console.WriteLine(q);
and getting that output :
SELECT [Blogs].[Id], [Blogs].[Name]
FROM ([Blogs] JOIN [Posts] ON ([Blogs].[Id]=[Posts].[BlogId]))
WHERE ([Blogs].[Name]<>'Ken''s blog')
Soon enough you would be able to to that.
After having fun creating the Static Sitemap Generator, today I've had a little free time (as my main machine is being reinstalled), so I came up with a SQL query generator.
It would be a tool to generate classes out of a database, that would make writing typed sql queries a breeze.
I have most of it working, except the part where I retrieve the metadata from the database ... No worries, my good friend and SQL guru Moran is about to send me the queries for that real soon.
First release would work with SQL Server 2005, and later on I'll add extension points to hook up other db engines.
It's funny. At the end of the day, I didn't use the tiny IoC in the StaticSiteMap for the testing.
It was fun however.
The Static SiteMap Generator's home is in Castle Contrib, and it's named Castle.Tools.StaticMapGenerator
I've just commited it to the repository, so it's at http://svn.castleproject.org:8080/svn/castlecontrib/Castle.Tools.StaticMapGenerator/trunk/
UPDATE (22/06/2008):
The source has slightly moved (to a sub folder):
http://svn.castleproject.org:8080/svn/castlecontrib/Tools/Castle.Tools.StaticMapGenerator/
I hope to have time soon to blog about the creation of this little tool, and of the usage. Also, expect a binary soon.
Last night I got frustrated with the fact that I have no intellisense (nor compile time check) for locating static files like .js, .css and image files.
So I sat up and created a simple console application that can generate exactly that, out of the site's filesystem.
usage:
D:\MyTools\StaticMapGenerator /site:D:\Dev\MySite
it generates a file called Static.Site.Generated.cs within the site's root folder, and then I go and include that file in my web project.
No I can do stuff like:
<script type="text/javascript" src="<%= Static.Site.Include.Scripts.myscript_js %>"> </script>
<link rel="stylesheet" href="<%= Static.Site.Include.CSS.master_css %>" />
<img alt="Ken Egozi" title="My Logo" src="<%= Static.Site.Include.Images.Logos.my_logo_png" />
How cool is that?
It works in every ASP.NET compatible web framework (MonoRail, ASP.NET MVC, even WebForms ...)
The only prequisite is .NET 2.0 runtime.
Sorry for keeping it out of reach for the moment. I need a little bit of time to setup a svn repository to make the source public (it would of course be BSD/Apache2/MIT thing) and to upload a binary. No promises given, I'll try to make it in the coming weekend, or even tonight, so stay tuned.
The code is somewhat naive, and certainly does not cover any edge cases, however it's enough to work cleanly on the largest project I'm currently involved in (Music Glue). Patches to make it more configurable and able to handle more edge cases would be gladly accepted once it's out.
One cool spot - as part of this, I have also implemented my tiny IoC container in 33 LoC.
Last night I've built a nice new tool called StaticMapGenerator which is used to generate a typed static resources site-map for ASP.NET sites (works for MonoRail, ASP.NET MVC and even WebForms).
I'll blog about it on a separate post in details.
Since I didn't want any dependency (but .NET 2.0 runtime) for the generator and the generated code, I couldn't use Windsor to IoC. That calls for a hand rolled simple IoC implementation
Ayende has already done it in 15 lines, but I wanted also to automagically set dependencies and have a simpler registration model.
so I've quickly hacked together a configurable DI resolver (a.k.a. IoC container) in 15 Minutes and 33 Lines Of Code. Call me a sloppy-coder, call me whadever-ya-like. It just works.
static class IoC
{
static readonly IDictionary<Type, Type>types = new Dictionary<Type, Type> ();
public static void Register<TContract, TImplementation>()
{
types[typeof(TContract)] = typeof(TImplementation);
}
public static T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
public static object Resolve(Type contract)
{
Type implementation = types[contract];
ConstructorInfo constructor = implementation.GetConstructors()[0];
ParameterInfo[] constructorParameters = constructor.GetParameters();
if (constructorParameters.Length == 0)
return Activator.CreateInstance(implementation);
List<object> parameters = new List<object>(constructorParameters.Length);
foreach (ParameterInfo parameterInfo in constructorParameters)
parameters.Add(Resolve(parameterInfo.ParameterType));
return constructor.Invoke(parameters.ToArray());
}
}
Ok, I've cheated. You'd need using statements too, but you can see that I was generous enough with newlines ...
Usage:
Given those:
public interface IFileSystemAdapter { }
public class FileSystemAdapter : IFileSystemAdapter { }
public interface IBuildDirectoryStructureService { }
public class BuildDirectoryStructureService : IBuildDirectoryStructureService
{
IFileSystemAdapter fileSystemAdapter;
public BuildDirectoryStructureService(IFileSystemAdapter fileSystemAdapter)
{
this.fileSystemAdapter = fileSystemAdapter;
}
}
You can do that:
IoC.Register<IFileSystemAdapter, FileSystemAdapter>();You need not worry about supplying the BuildDirectoryStructureService with an implementation for the service it depends on, but only to register an implementation for that service.
IoC.Register<IBuildDirectoryStructureService, BuildDirectoryStructureService>();
IBuildDirectoryStructureService service = IoC.Resolve<IBuildDirectoryStructureService>();
From time to time you'd want some of your markup rendered only on 'real' scenarios. For example, you wouldn't want google analytics to track visits you do on your dev machine. Sometime you'd even develop while your machine is not even connected to the internet, and every page would try get the analytics script and will behave strangely.
In Monorail, the Request has a property named IsLocal, just for that. I've wrapped it in a nice ViewComponent.
public class GoogleAnalyticsComponent : ViewComponent
{public override void Render()
{
if (Request.IsLocal)
return;
RenderView("AnalyticsCode");
}
}
Accompanied by the AnalyticsCode view template:
<%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime" %>
<script src="https://ssl.google-analytics.com/urchin.js" type="text/javascript"></script>
<script type="text/javascript">
_uacct = "MY_URCHIN_CODE";
urchinTracker();
</script>
, that can easily be extensible to set the urchin code with a parameter.
Have just read Ayende's post about C#/Java vs Boo/Ruby.
Tried to comment, but then I decided it's worth a post.
I'd say that the difference is MAF - Management Acceptance Factor
Boo is also a way too cool/strange/creepy name for a distinguished suit to grasp.
It's like when you're a collage girl, and you want to introduce your new boyfriend to your mama. It doesn't matter that he has a BSc and MBA plus 3 castles in the Swiss alps. If he'd first show up to the family on his way-too-cool motorcycle, then you're going to be grounded.
When I approached my last manager about MonoRail, and told him that the views will be written in 'Boo', he got all scared. Then I wrote AspView, views to be written in c#, and he gave consent to go MonoRail.
Even though, at least at that time, Brail was way more mature than AspView.
The 'cooler' languages needs to be marketed to management.
Ruby works in Eclipse. I wonder who is going to start an OSS effort to create a decent Boo plugin for VS2008 (based on the VS2008 shell).
Make it demoable, make it look 'official', and MAF would go way higher.
Following users requests, I have just posted two documents to using.castleproject.org.
The first is an explanation about the CodeGenerator (from Contrib), and another one, on using the DictionaryAdapter.
Here are the links:
Related stuff:
Problem:
Possible causes:
Setting XHTML output manually:
Thanks Mr. Joe Chang, from the Windows Live Writer team, who have pointed that out for me.
Although about three weeks too late, I present thee:
AspView, built for Castle RC3 (release, debug, source)
I've also introduced a well due improvement to the engine. Now it supports the use of a 404 rescue view, that would get rendered in case of the url mapping to a non-existent controller.
the commit comment (for revision 314) says it all:
Handling view creation for EmptyController, specifically when a controller is not found and a 404 rescue exists
Next improvement will include an option for doing AutoRecompilation in memory, as sometimes the IIS process gets hold on the CompiledViews assembly files (dll and pdb) and failing the automatic recompilation process.
I certainly need that as it happens on my machine too much, and building the Web project takes a solid 10-15 seconds, while running vcompile is a milliseconds thing only.
Soon ...
That's a great news for everyone who build websites and web applications.
IE7 would be installable even to XP users without the Genuine Check.
That means that in short time, the IE7 adoption rate would increase so much, that hopefully the annoying IE6 would become as obsolete as Netscape 4 and IE 5.5 ...
No more dirty CSS hacks (or at least, a lot less)
No more buggy box-model
Finally we can use input[type=text] and the likes
I've kept IE6 on my box for so long only to be able to test what I write. Even though I use Firefox for day-to-day browsing, I still need IE for some crappy israeli sites that would just not work on non IE (and by not work - I mean that you get an alert box saying:
For people who knows not Hebrew:
"This site supports IE browsers, from version 5.5 and up. Support to other browsers is planned for next release"
Ha Ha.
This message is there for at least a year.
And it's not even dependant on ActiveX or other IE magic. It's only some laziness regarding JS and CSS compatibility.
look at http://www.codeplex.com/xunit
Quite interesting. I might give that a shot soon.
You can read about it at http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html
The upside for that is the simplification of things by removing some attributes, and having a more consistent model regarding assertions on exceptions.
Main reason - I want to reduce traffic to my blog (I do have a gazzilion a million few hundreds subscribers, just like you, my dear reader.).
Plus, since feed-burner has gone Google-d, they give the PRO services for free, so I'd be able to enjoy the stats - which means I'd be able to know exactly how many people are reading me, and then can arrange the kenegozi-readers-party (thought about the Madison Square Garden, but I guess my living room will do just fine).
So, please update your favorite reader to point to http://feeds.feedburner.com/kenegozi.
Seriously, it's Google. What took them so long?
Anyway - Google Reader remains my feed reader of choice. I do not use my laptop offline much, so it's ok like that, plus the offline mode in reader kinda works, so for the occasional offline sessions I do have it's more than enough.
It took me almost a week to notice, though ...
I'm using VS2005 (with SP1, like duhh) and have had R# 3.0.1
Now, I'm not a fan of the default font and color scheme, as I like better the slicker mono-fonts, like Consolas. I am also becoming a Black-Background type, not for the WouldSaveTheRainForests==true reason (in LCD the light is static no matter what color it shows) but for the implements IDLikeToKeepMyEyeSightForALongTime reason.
So, started with importing a color scheme from some internet-found-place, don't remember where, and then tried to change those Resharper coloring options (like, a variable name that is being used an odd amount of times, by internal classes, however not in an explicit-interface implemented method, that returns a struct), just to find out the the Fonts-And-Colors menu miss those lovely Resharper entries).
Okay, so what should I do? Export the settings, edit the xml, and re-import. Not much fun there.
Hmm. Googled it (I may use the term, as I actually use Google as a search engine), and found a post on jetbrains support site, with the same problem.
no solution though.
However - this is how I solved it eventually:
1. Export the current settings to a file
2. Reset all settings
3. Re-install R# (hey - now it's 3.0.2 !!)
4. Import back my settings.
Assuming you have a main "trunk" in your subversion repository, and that you are actually working on a different branch.
You'd need to merge your changes from your branch to the trunk so other team members would be able to use your code. You'd also want to be able to merge from the trunk to your branch, to be able to use your teammate's code.
The thing you should bear in mind while you merge, is that the actual merge process is actually working by generating a patch (using diff) and applying this patch on the target.
a quick note: It is very much recommended that you have committed all changes to the target of the merge, into the repository, so it would be easy to revert if something went wrong.
So:
a. Go to the trunk folder on your filesystem, right-click->tortoise->merge.
b. You want the changes between the current trunk revision and your branch's current revision to be applied on the trunk, so you choose:
From: your trunk, revision HEAD
To: your branch, revision HEAD.
I know, the terminology is confusing, as you want to "update" from the trunk to the branch's state, but remember that you want the diff(erence), or in other words, the changes that will take the trunk FROM it's current state, TO your branch's state.
screenshot:
now you have a merged trunk on your workstation. Make sure that everything compiles and that tests are green, and commit.
a) Go to your branch's folder, right-click->tortoise->merge;
Now, you want the changes between the last trunk revision that you have on your branch, to the newest revision of the trunk. To find out that last trunk revision that you have on your branch, go to your branch's folder, right-click->tortoise->show-log, and look for it. If you are a good reader you'd easily find it since you have mentioned the revision numbers of your merges in the commit remarks, as you are kindly recommended)
A screenshot from the branch's log:
I need to check if I have merged my branch to the trunk on a later point. I'll do that using the Trunk's log (trunk folder, right-click->tortoise->show-log):
Indeed. It seams that my branch is in sync with the trunk at revision 918
b) Now you fill
From: your trunk, revision "last revision you have"
To: your trunk, revision "new, wanted state" (usually HEAD).
in my example, the last trunk version I have merged into my branch is 902, so that's the screenshot:
I know, terminology sucks again. You probably thing "from trunk to trunk? Is he crazy?" well, again, you want to get the changes that was made TO THE TRUNK, and apply them to your branch. Remembering that this is actually a patch that will get applied make anything clear again.
now you have a merged branch on your workstation. Make sure that everything compiles and that tests are green, and commit.
Recommendation: write down in the commit's remark, the revision number of the trunk (the current HEAD before the merge) for next time.
My thanks to this page, and to Lee Henson who have pointed it out for me, and helped my grasp the whole merge==diff'n'patch thing.
Today I noticed that piece of code on my working copy:
Repository.Blog.FindOne(Where.Blog.Id == blogId)
Check out this nice tool from Omer Rauchwerger.
It could help a team to manage a coding convention. Should be very useful in Open Source environments. For example, when committing changes to castle project (or sending a patch) there is a coding standard than needs to be followed. Regionerate could help a lot with that effort.
I need to see if it can select methods and properties by attributes. It could then help making MonoRail controllers and ActiveRecord decorated classes more readable (region of all actions with a "SkipFilterAttribute", region of "Property" and region of "HasMany", etc.)
UPDATE:
Silly me, I forgot to mention that I found about this great tool at Roy Osherov's blog. A very good one, that is. Many Agile related stuff, and funny little things, too. So go on and subscribe to it's feed.
Checkout the latest post of Scott Guthrie.
Is the long awaited JS IDE will be VS2008?
Now it's a matter of adding ///<summery> tags to prototype.js and maybe people would really stop being afraid of developing javascript code.
Now that's a good reason to switch to VS2008, combined with the fact than you can hold to your current .NET distribution.
After all, even VS2005 was actually calling csc.exe rather that calling some magical inner stuff as in 2002/2003.
I hope that this also means better addin development support, so great projects like CVSI and ActiveWriter, could become even better.
Do you think they'd enable a "Compile for Mono" option?
If you are an AspView user you might have noticed a problem.
If you setup a nullable-value-type parameter with a default value other than null, then you'd get a casting error.
example:
<%
int? someInt = default(int);
%>
some markup
<% if (someInt == default(int)) DoSomething();%>
it happened because of the way GetParameter worked
GetParameter is a method that gets a view parameter value from the view's properties collection (PropertyBag, Flash, Request.Params, etc.). It's located in the AspViewBase class (the base class for each and every view in the AspView world).
So, now it's fixed, and a test was added to make sure it'll stay that way.
As soon as google.com will be accesible again, you'd be able to check out and build.
UPDATE:
I'm too tired (3am here). The sources are on castle contrib and not on google, so you'd find them here
Wow.
Another great tool from Google.
Works on Win/Mac/Linux, for IE and FF.
In a few words - it can give you offline browsing, plus local storage using SQLite (so you can run SQL queries strait from your javascript to query the local store)
I wonder what secutiry issues can come up. However, it looks very cool, and can help bring power to existing DHTML/Ajax apps.
Makes me think. Now that you do SQL from javascript, isn't it time for JsHibernate? and what about an ActiveRecord inplementation in javascript?
So, in the Flex/Silverlight war, it seams that Google is gonna win again ...
(from Scott Hanselman's Blog)
I needed to manually Castle today, for the first time.
The need is for Castle.MonoRail.TestSupport.BaseControllerTest only, so I do not really care about all the rest.
Opened "How to build.txt"
I know that the builds in the CI server are failing due to some filing tests on DP2, so I add "-D:common.run-tests=false".
no brainer.
I am also targeting .net2 only, so I add "-t:net-2.0"
baboom. This fails.
The nant exe is telling me that I can only build to .net 1.1, or .net compact framework 1.0.
So I went to nant's config file, and found out to my surprise, that the frameworks that are present there are:
.net 1.1,
.net compact framework 1.0
.net 2.0 BETA 1
hmmm.
So I've edited the config, changed the existing .net 2.0 config name to .net2.0Beta1,
copy&pasted the .net node to another one, now switching version number from
sdkdirectory="${path::combine(sdkInstallRoot, 'bin')}"
frameworkdirectory="${path::combine(installRoot, 'v2.0.40607')}"
frameworkassemblydirectory="${path::combine(installRoot, 'v2.0.40607')}"
clrversion="2.0.40607"
to
sdkdirectory="${path::combine(sdkInstallRoot, 'bin')}"
frameworkdirectory="${path::combine(installRoot, 'v2.0.50727')}"
frameworkassemblydirectory="${path::combine(installRoot, 'v2.0.50727')}"
clrversion="2.0.50727"
voila. Now the build is starting.
However, the Castle.Components.Validator.Tests dll refuse to build. I'll disable it, too.
UPDATE:
I'm an idiot. Did not notice that NAnt has gone far beyond rc3 a long time ago ...
just added a blogroll.
To the DB, to the Domain, to the controller and to the view.
Took me (all in all) 30 minutes, including all the coding, CSS-ing, uploading to the webserver, setting up the DB table on the hosted server, adding a few entries, clearing the browser's cache, and viewing it.
ah, and committing changes to Google code.
All of that was made in the Budapest Airport cafeteria, while waiting for my flight home (was a great trip. Photos, though not many of them, will be posted later on).
Rest assure that the DB access code is tested, and that the calls to the DB and to the cached data from the Controller and View are all typed.
I'd like to thank NHibernate, Castle and AspView (hey - that's me !), who made this possible.
I bet Ayende would have done it in 20 ...
Since this blog is running on an engine that I wrote (available on Google code site, here), it lack some features that more mature blog engines already have. (the other engines lacks the combined power of ActiveRecord/MonoRail/AspView ...)
So, that's currently my list:
1. Blogroll, for obvious reasons.
2. Email alert for me when anyone posts a comment for one of my posts.
3. Comments feed (via ATOM).
UPDATE - Done
4. Email subscriptions for new posts, or new comments on specific posts.
5. I have a problem with the font. I should fix the CSS but the Internet connection here (I'm at a Budapest hotel) is quite poor. Will be fixed next week.
UPDATE - Done
Any other suggestions?
note that I do not intent on implementing Pingbacks and Trackbacks, since those were littering my blog in the past.
So if you wanna download it, you should go directry to the NUnit's page on sourceforge
I've just commited to the repository a new version of AspView.
The main addition is "Auto Recompilation" feature.
This means that when you change one of the view sources, the application will automatically recompile the views upon the following request.
You enable the feature by adding the next attribure to the aspview config section in web.config:
<aspview .... autoRecompilation="true" ... > ... </aspview>
Breaking change:
If you happen to reference an assembly from the GAC (using the aspview configuration in the web.config) you need to add a hint for the engine, like this:
<reference assembly="MyAssemblyFromGAC.dll" isFromGac="true" />
Known issues:
1. You need to let ASPNET user (or the Application Pool user) a modify access on the bin folder.
Note that if you use the inner WebServer of Visual Studio this should not be a problem, since in that case the web application runs with your user, that has the needed peremissions on the bin folder.
2. For a strange reason, after you change a view and do the F5 in the browser, you still see the old version, and only on second F5 will the views be actually recompiled and refreshed. I hope to fix it soon ...
Download from here.
Sources are here.
As you already have probably noticed by now, I did some renovation on my blog.
Among other things, it is now being served from a SQL Server database, rather than form the daBlog xml files.
One caveat of this, is the fact that backuping the blog's content became much harder. Since I have no access to db backups, I neede to find a way to generate the INSERT scripts that will enable me recreationg the content if it would be needed.
My first try-out was the Microsoft SQL Server Database Publishing Wizard, that I saw at Scott Gu's blog
This tool is meant to create the script form a local dev db, in order to make it run on the remote one. Actually you can make it run on the remote one, nd save the generated sql file locally, for backup purposes.
I tried it up, but it send some nasty .NET break dialogs. It however managed to create A script, that I'm yet to check for it's usability.
Nice tool. But I'll look for something that is pure t-sql so it'd be easier to run (maybe automated every once in a while)
Another dumb error message.
While installing ActiveWriter, it asked me to install DslToolsRedist. Trying to do so raised the said error message. I was on my way to shot the admin, but then googled a bit, and found out on http://www.appdeploy.com/messageboards/tm.asp?m=8872&mpage=1 that it is caused by prior installations of he same product that was not fully removed from the registry while uninstalled. Searching "DSL" in HKEY_CLASSES_ROOT\Installer\Products\ showed me that a previous CTP left some dirt in my registry. Removed that key, reinstalled DslTools and the ActiveWriter magic could finally started.
ActiveWriter is a VS2005 plugin, that adds a new item type for your projects. This item is actually a visual designer for ActiveRecord classes. Quite neat, and hopefully will increase the penetration of Castle's ActiveRecord to the "If there's no VS wizard, I do not use it" kinda guys.
You can read about it and download it from http://altinoren.com/activewriter/
There is a great article on CodeProject, by Guenter Prossliner.
A simple class in presented there, that makes Duck Typing possible for Generics enabled CLS languages (VB.NET 8 and C#2.0 for instance).
I'll present it here in short form:
let's say we have two classes:
1: class Foo1
2: {
3: public string Bar() { }
4: }
5: class Foo2
6: {
7: public string Bar() { }
8: }
Now you have a method that can work with instances of eiether one, and invoke Bar on it:
1: void SimpleMethodOnFoo1(Foo1 foo)
2: {
3: foo.Bar();
4: }
5: void SimpleMethodOnFoo2(Foo2 foo)
6: {
7: foo.Bar();
8: }
Just in case that Scott Hanselman's blog isn't accessible, I'll post here the steps to use watir and WatirRecorder.
1. Install Ruby using the Ruby One-Click Installer, or search http://www.ruby-lang.org/en/ for a newer version to download.
2. Install watir:
3. Install WatirRecorder++
Some problems I've faces during the use of Watir:
1. The WatirRecorder couldn't run my recorded tests. So I've saved the script to a file, changed it's extension to .rb and let Ruby run the test.
2. This led to another problem. For some reason, Ruby doesn't handle hebrew characters so well when they're saved in UTF8 format, and that's the format WatirRecorder saves the scripts, So if you are recording hebrew characters to your script, then after saving the script to a file and changing it's extension to .rb, open it in notepad and resave it in ANSI encoding, and Ruby will run the test flawlessly.
Thumbs up for the makers of Ruby, Watir and WatirRecorder++, as well as to Scott Hanselman who've pointed this tool out for us