Disclaimer
The opinions expressed herein are my own personal opinions. However, they also represent my employer's view 100%, since I am self-employed.
All source code found here is licensed under the MIT license, which essentially gives you the right to do whatever you want with it, except blaming me if something goes wrong.
© Copyright 2012, Zdeslav Vojkovic
|
|
It takes so little time to make to make a decent company utter crap, and I recently joined the ranks of extremely annoyed Webhost4Life customers, some of which vented their frustration here.
Since Webhost4life moved my sites to their 'new platform', all the sites stopped working, which I would tolerate if what followed hasn't been an encyclopedic example of poor customer support. They were not able to fix any of the problems in 2 months, while the provided support falls somewhere between an insult and an injury.
Some examples:
- First level support is a bot, and a cheap one. It spins in circles, until you get lucky enough to get transferred to second level support. Of course, you don't get that lucky most of the time
- Second level support is clueless, and have no problems lying in your face
- 90% of answers are 'our technicians are working on the issue, we will contact you ASAP'. Then nothing happens for WEEKS. In short, "don't call us, we'll call you"
- I had to fix some of their redirection scripts, to make them work. When other sites broke, they were not even able to copy the stuff
- Fixing one thing broke the other
- They resolved the issue by telling me that they will leave it open indefinitely, while "they assess the need for further actions". WTF?
- They flat out lie: 'we have been able to manually fix many of your accounts'. Of course, they didn't fix anything
Although all the problems were related to broken redirection and app roots for ASP.NET apps, they obviously have no one there who knows anything about the technology they sell. If you consider hosting with them, DON'T DO IT, unless you are working on some artificial intelligence paper, and you find fun in talking to bots (which, admittedly, can be quite funny sometimes - try discussing politics or food with Webhost4Life first level support).
Now, I have moved to Arvixe and things have been great so far.
Finally got a few spare hours to do some hacking on my poor man's NH profiler, and that resulted with Crumbs.
It's an NHibernate profiler for web applications based on Asp.Net, regardless of which framework (Monorail, Asp.Net MVC,...) you prefer to use. It is now much easier to set it up: just drop in the Crumbs.Profiler HttpModule and off you go (actually, you will also need additional CCS stylesheet to make it look nice, and maybe jQuery to make it act nice).
Hopefully, future versions should bring even simpler usage and better functionality.
At the moment code is rather ugly (actually, my first HttpHandler ever) and has no tests at all, but it will change. It is now hosted at Google Code, so feel free to check it out.
First of all, if you do any serious work with NHibernate, consider using the excellent NHibernate profiler. It will save you time and pinpoint many non-obvious issues with your NHibernate usage patterns.
Now, if all you need is a way to check what SQL has your web application been executing (e.g to optimize lazy loading, check for N+1 issues, etc), it is helpful if you can see this information straight on the web page which executed the statements.
For my web development work, I prefer using Castle Monorail (+ ActiveRecord or NHibernate) I have attached a demo project (see the bottom of the post) which you can feel free to use with your application. It shows how to trace NHibernate log data into the web page by using Monorail filter which collects the NHibernate information (by reading from log4net in-memory appender which receives NHibernate.SQL logging), and a component which displays the collected data.
In order to use this in your application, you need to:
- copy DebuggingFilter and DebuggingComponent into your project
- register DebuggingFilter with your controllers
- set up the log4net in-memory appender (see web.config in the sample)
- set DebuggingFilter.DebuggingActive to true at some point (e.g OnApplicationStart)
- copy and include jQuery JavaScript in your pages (if you want to toggle the details)
- copy a part of the stylesheet which formats debugging div (or roll your own)
- if some step is missing, please drop me a comment
If time allows me, I would like to implement following features:
- providing an implementation for Asp.Net MVC (actually, I already have it)
- setting a global/per-request limit of SQL statements, which triggers an error information
- filtering who can see the data (for use on live site, but there are issues with logging all the SQL)
- an HttpModule implementation - need no setting up, independent of framework (Monorail, Asp.Net MVC)
- extract CSS for debug window into separate file
- use only minimum JavaScript instead of full jQuery
It would also be great if Oren would provide similar functionality in NHProf. E.g. you would just embed the URL of NHProf service into your pages, and the service would return the requested data.
Here's how it looks in action:
When a request is executed, the summary of the SQL is shown at the top. If there was a redirect, each request will have separate entry.  Clicking the 'toggle details' button will display the executed statements:  Download Monorail sample (uses ActiveRecord for DB access): demoapp.zip (1.87 mb)
Recently, I was bitten in the ass while trying to generate the PDF documents on fly inside an ASP.NET web application, to be downloaded from a web site.
First, some background to describe the problem:
In short, the idea was that a user would click a link, and the application would generate the PDF in the memory (without backing file on the disk) and write it to the Response stream, which results in document being downloaded to client machine. PDF generation is done using the excellent iTextSharp open-source library, which gives you all that you need to build PDF documents - at least if you requirements are as modest as mine.
Let's see how this method looks like, stripped of all unnecessary details.
...
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
...
void Download()
{
Document document = new Document(); // instantiate a iTextSharp.text.pdf.Document
MemoryStream mem = new MemoryStream(); // PDF data will be written here
PdfWriter.GetInstance(document, mem); // tie a PdfWriter instance to the stream
document.Open();
... // adding content to iTextSharp Document instance
... // tutorial: http://itextsharp.sourceforge.net/tutorial/index.html
document.Close(); // automatically closes the attached MemoryStream
byte[] docData = mem.GetBuffer(); // get the generated PDF as raw data
// write the document data to response stream and set appropriate headers:
Response.AppendHeader("Content-Disposition", "attachment; filename=testdoc.pdf");
Response.ContentType = "application/pdf";
Response.BinaryWrite(docData);
Response.End();
}
Initially, everything looked great, but as documents grew more complex, some of them turned out to be corrupted, when opened on the client machine. At the same time, if they were created through a backing FileStream instead of MemoryStream everything was fine.
It turned out (after couple of hours of guessing and debugging), that the problem is in a way how MemoryStream and Document objects interact. When data is written to a MemoryStream instance, underlying buffer is increased in blocks which are multiples of 512 bytes long (an implementation detail which might change, don't rely on it). This means that the capacity of the underlying buffer is always at least equal to the real length of written data, but typically it is larger. When the Document instance s closed, it also closes the stream. However, the length of written data is less than the capacity. When you ask for buffer ( mem.GetBuffer()), the whole buffer is retrieved, including the padding bytes which are set to zero. When this buffer is transferred to client machine, excessive padding bytes result in a corrupted document.
There is no way to read the real length of written data prior to document.Close() because document has not been flushed yet. There is also no way to read it after the Close() call, because the stream was disposed already.
I solved this by introducing a new stream class, which records the real data length while being disposed, and overrides GetBuffer() method to return the buffer resized to correct length:
class LengthFixingStream : MemoryStream // feel free to suggest better name than LengthFixingStream
{
private long m_length;
protected override void Dispose(bool disposing)
{
m_length = Length;
base.Dispose(disposing);
}
public override byte[] GetBuffer()
{
byte[] buffer = base.GetBuffer();
Array.Resize<byte>(ref buffer, (int) ContentLength); // dirty, but my documents are < 2GB long
return buffer;
}
public long ContentLength
{
get { return m_length; }
}
}
Now, the only change which has to be done is to replace MemoryStream reference in Download() method to LengthFixingStream:
void Download()
{
Document document = new Document();
LengthFixingStream mem = new LengthFixingStream();
... // yadda yadda yadda... the rest is the same
}
Here's another reminder to myself: a nifty one-liner regex which transforms Pascal/camel case string into a sentence. I always write it from scratch so I decided to put it here. It might also be a good idea to write it as an extension method for string class.
static string PascalCaseToSentence( string input)
{
return Regex.Replace(input, ".[A-Z]", m => m.ToString()[0] + " " + char.ToLower(m.ToString()[1]));
}
Following line
Console.Out.WriteLine(PascalCaseToSentence("MyVeryLongSentence"));
will result in:
My very long sentence
On our project, we are experimenting with continuous integration, and so we set up a build server based on CruiseControl.NET. The server is running on Windows Server 2008, and we try to keep it as clean as possible. Development machines typically run on Win XP.
The project tree contains tools folder which contains copy of NAnt and other tools which are used to run the build (NUnit, NCover, Simian, etc). This way, when a developer downloads project files to development machine, he just runs the build script and same version of tools is used to perform a local build, thus avoiding the risk of using mismatching version of tools. NAnt build script internally uses <msbuild> task to compile the msbuild solutions.
This has all worked great until we recently switched from .NET 2.0 to .NET 3.5. During this, our development machines were updated to Visual Studio 2008, and our build server was updated to 3.5 framework and SDK (we don't install Visual Studio on build server,so we have to install SDK separately after the .NET framework is installed).
This initially created issues with some of our build scripts: builds started failing with error messages pointing to the fact that <msbuild> task doesn't understand format of the solution file (new version is 10 and build complained about understanding only 7 and 9). After updating NAnt to latest version and testing on a dev machine, problem seemed to went away.
However, builds on our CI build server started failing with same error.
After some investigation, it turned out that Visual Studio 2008 installs version 6.0A of Windows SDK. However, standalone Windows SDK installs version 6.1, thus resulting in mismatch between build server and dev machines.
The heart of the problem is that nant.exe.config internally uses ${sdkInstallRoot} variable which is initialized to the value read from the registry key SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A\WinSDKNetFxTools\InstallationFolder. Now, we couldn't just change the entry in nant.exe.config because the same file is used both on server and dev machines, and if we fix it for one it won't work for the other.
We also didn't want to install Visual Studio 2008 on build server.
The solution (or more precisely, the hack) was simple:
- Open regedit
- Go to 'SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1\WinSDKNetFxTools\InstallationFolder' key
- Export it into a file
-
Open the file and replace all references in key names from "v6.1" into "v6.0A". Leave the file paths with 'v6.1' unchanged.
-
Save the file and import it into regedit
Now you have the exact copy of the SDK 6.1 keys, saved under 6.0A key. This way, build server can use the same nant.exe.config file as dev machines.
If there is a cleaner way, I would be glad to hear it, but this is working for us without any problems.
After failing many times before, I have finally found out how to create user-friendly timestamps in batch scripts. For many people this may be yesterday's news, but I am posting it here as a reminder to myself and in hope that it might help someone else.
Windows command shell (sometimes erroneously called DOS prompt) provides %DATE% and %TIME% environment variables which, unsurprisingly, return current date and time. On the other hand, it is possible to extract a group of characters from any environment variable using following syntax:
where VARIABLE is the name of the environment variable, START is the zero-based index of the first character to be retrieved and LENGTH is the length of the string to be retrieved. E.g. %USERNAME:~1,3% would return second, third and fourth letter of the current user's name.
So in order to create a time stamp, we define a temporary environment variable with value defined by parts of %DATE% and %TIME%. Then we use this variable to create file names. Please note that the exact indices will depend on your time format settings. In a batch file or a script it would look like this:
set backup_time=%date:~10,4%_%date:~7,2%_%date:~4,2%
set backup_detailed=%date:~10,4%_%date:~7,2%_%date:~4,2%__%time:~0,2%_%time:~3,2%_%time:~6,2%
md d:\zzz_%backup_time%
md d:\zzz_%backup_detailed%
Output of the batch file is:
D:\tmp>set backup_time=2008_09_23
D:\tmp>set backup_detailed=2008_09_23__15_50_31
D:\tmp>md d:\zzz_2008_09_23
D:\tmp>md d:\zzz_2008_09_23__15_50_31
For those who don't already know, NVelocity is a .NET port of Jakarta Velocity template engine. Castle team took it over, due to the lack of releases, support and bug fixes on the original port, and I strongly suggest to use this improved version.
NVelocity is a fine tool, but it is not quite obvious how to set it up so that embedded assembly resources can be used as templates. This is done by setting a group of properties which control what implementation of ResourceLoader abstract class is used to load the templates. To use embedded resources, you need to register the NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader class as ResourceLoader, and specify the assembly which contains the templates as parameter "assembly.resource.loader.assembly". Here's how:
private static void InitializeVelocity()
{
ExtendedProperties properties = new ExtendedProperties();
properties.AddProperty("resource.loader", "assembly");
properties.AddProperty("assembly.resource.loader.class",
"NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader, NVelocity");
properties.AddProperty("assembly.resource.loader.assembly",
Assembly.GetExecutingAssembly().GetName().Name);
m_velocity = new VelocityEngine(properties);
}
You can find the full sample here: NVelocitySample.zip (87.13 kb)
Since most of my daily work is done in C++, every now and then I miss some niceties which are available in C#. One such example are .NET events, which are really an elegant solution for implementing observer design pattern.
Idiomatic C++ implementations of observer pattern are based on defining abstract interfaces, which have to be implemented by subject and observer classes. Sometimes it would be nicer to bind to an event just based on event/method signature instead of building all the needed scaffolding.
Here is a quick take at this problem. This is by no means a complete solution, but can be a basis for more elaborate one.
Events are defined and fired like this:
class Subject
{
public:
event<int> ValueChanged; // same template is used, regardless of number of arguments
event<int, const char*> ValueAndNameChanged; // no need for having event1<A> and event2<A, B>
void SetValue(int x)
{
// .. do something
ValueChanged(x); // then fire ValueChanged event
}
void SetValueAndName(int x, const string& name)
{
// do something...
ValueAndNameChanged(x, name.c_str()); // fire ValueAndNameChanged event
}
};
Clients consume events like this:
// implementation of observer object
class Observer
{
public:
void OnValueChanged(int i)
{
printf(" - non-static handler for SetValue called, new value = %ld\n", i);
}
static void OnValueChangedStatic(int i)
{
printf(" - static handler for SetValue called, new value = %ld\n", i);
}
};
// global functions work, too:
void OnValueChangedGlobal(int i)
{
printf(" - global handler for SetValue called, new value = %ld\n", i);
}
// test
int _tmain(int argc, _TCHAR* argv[])
{
Subject subject;
Observer observer;
subject.ValueChanged += Observer::OnValueChangedStatic; // static member method as handler
subject.ValueChanged += OnValueChangedGlobal; // global function as handler
subject.ValueChanged += event_handler(&observer, &Observer::OnValueChanged); // non-static member
subject.SetValue(3); // this will fire the event
// detach from event. This is not necessary when lifetime of observer is shorter than lifetime
// of the subject, but if subject outlives observer, handler must be unregistered
subject.ValueChanged -= Observer::OnValueChangedStatic;
subject.ValueChanged -= OnValueChangedGlobal;
subject.ValueChanged -= event_handler(&observer, &Observer::OnValueChanged);
return 0;
}
Output of this snippet is:
d:\dev\events>events.exe
- static handler for SetValue called, new value = 3
- global handler for SetValue called, new value = 3
- non-static handler for SetValue called, new value = 3
It is possible to use static and non-static members as handlers, as well as global functions. Note, however, that there is one difference compared to event behavior in .NET: if you register same handler twice, it will be called only once. This can easily be changed in the code, but it seems more logical to me.
Attached archive contains a Visual Studio solution with implementation of event class (events.h) and some additional examples.
events.zip (5.14 kb)
At a recent interview, a job candidate ticked me off when we reached one of the topics which is very dear to my heart. We are mostly C++ shop, but many of our job applicants come from .NET background. So during the interview we came to the topic of explicit memory management vs. automatic memory management (a.k.a. garbage collection), and the guy (with substantial C++ experience) started ranting about how troublesome explicit memory management is, with all this extra caution required to call delete for every new, as opposed to simplicity of platforms which support GC.
Well, if you happen to agree with this guy, then you are not doing it right :)
Although GC can be done in C++ (see here), that is not the point: the main issue here is that many people are still doing C code using C++ compiler.
Modern C++ is very different beast from C, and as such provides different patterns for common problems. The concept of smart pointers alleviates much of the manual work that is otherwise needed to handle allocations correctly. The STL comes with std::auto_ptr, which makes it trivial to ensure the proper deallocation in face of exceptions or normal scope exit.
If you need to handle an array, STL is your friend again: there is std::vector, and it also takes care of transparent resizing/reallocation, so you don't have to worry about it.
What is (currently) lacking in STL is an implementation of smart pointer with shared semantics. However, there is plenty of such implementations, most notably the excellent boost::shared_ptr, which is a reference counted implementation that makes sure that the allocated object is deleted when the last reference to it goes away. It will also become a part of new C++ standard, and some vendors support it already.
One issue where GC (at least when implemented with mark-and-sweep algorithm, like in Java or .NET) has an advantage to explicit memory management is the problem of circular references, i.e. when two objects hold a reference to each other. This is really a problem for reference counted implementations, but most cases can be handled by judiciously using weak pointers, and such an implementation is provided by boost::weak_ptr, which will also be included in new C++ standard.
If you think that this problem is a 'deal breaker' to prefer platforms with GC, bear in mind that the similar problem also exists even there, and that there is a very good reason why Java and .NET both provide WeakReference class (e.g. see here for one such problem).
What I really find annoying is the fact that the only resource which is deemed to be important enough to be automatically handled is memory. For everything else, like database connections, kernel or GDI objects, clients have to explicitly call Dispose, and it seems that most developers on managed platforms have no problems with that. A coworker who recently switched from VB to .NET found out hard way that you really have to call Dispose() on your bitmaps. What happens when you have to share such an object between multiple clients (yes, I know that there are idioms to avoid this resource sharing)? Who calls Dispose? Can you be sure that it has not already been disposed?
GC is a nice and useful thing, but it is not a silver bullet, and has its own problems.
Deterministic finalization is what makes it possible in C++ to treat all resources equally: whether it is a memory, a bitmap, a COM object or database reference, with a simple wrapper around it, you can rest assured that the object will be properly released as soon as it is not referenced anymore. Actually, smart pointers are only a special case of what is one of the most powerful concepts in C++, although a bit unfortunately named: RAII
If you are a C++ programmer, take some time to learn C++ idioms. It will make you a better programmer, and your code a better code.
When you program in C++, write C++, not C.
|