Home     Wordpress     Log in

Customizations I used with Elmah

January 6th, 2012 by matt | No Comments | Filed in Matthew Martin

Elmah isn’t especially secure if assume the error log itself has already been breached. Even if it hasn’t been breeched, sometimes Elmah logs things that the administrator doesn’t want to know, like other people’s passwords.

There are some reliability issues too.

1) Don’t log sensitive data.
- Some data is well known, e.g. HTML headers
- Some data is not well known, textboxes were you enter your password
- Viewstate for the above
2) Don’t refer to DLLs that won’t exist, for fear that dynamic compilation will fail due to a reference that can’t be found. For example the sqlite. I understand why the main project is set up this way though– the goal was to minimize the number assemblies distributed and still support lots of databases. This could also be a non-issue. Assembly resolution, for me, has always been black magic.
3) Override Email to use Apps config, insted of Elmahs config sections in the ErrorMailModule. I don’t like doubled config settings, where my app has a setting and so does the component.
4) Use Apps role system and PrincipalPermission to restrict display to certain roles
- Add PrinciplalPermissions to all classes that view things (but not classes that log things), see end for a list. If you don’t trust your server admins to keep from messing up the web.config, you can put the role checks right into the code: This set worked for me.
5) Stengthen XSS protections.
Change Mask. and HttpUtility.HtmlEncode to AntiXss.HtmlEncode. This creates a dependency on either the AnitXss library or .NET 4.0.
6) Add CDATA to javascript blocks
7) Switch to READ UNCOMMITTED. The error log must not cause errors (i.e. deadlocking)
SqlErrorLog.cs
8) When error log gets really large, it has to be rolled over and truncated to prevent locking issues. This at least was a problem in SQL 2000 and I think SQL 2005.

List of classes that could use a security attribute, should you choose such a strategy.

AboutPage.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorDetailPage.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorDigestRssHandler.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorHtmlPage.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorJsonHandler.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogDownloadHandler.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogPage.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogPageFactory.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogPageFactory.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogPageFactory.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorLogPageFactory.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorRssHandler.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
ErrorXmlHandler.cs [PrincipalPermission(SecurityAction.Demand, Role = "Admin")]

Opinionated Trace

December 9th, 2011 by matt | No Comments | Filed in .NET

The problem with trace-debug-loggers (I’ll call it trace from now on) is that anything goes. I’m going to try to use the System.Diagnostics namespace with the extensions on codeplex.

Trace is a story, it is the moment to moment diary of the application. The audience of trace is a developer. They want to know what the application is doing. Computers do a lot, so trace volume will have to be carefully managed.

Thou shall not trace in production, unless you have to.
Trace can be expensive. I took a representative 1000 repetition integration test that ran in 1/2 second and turned on verbose logging with DebugView running, and it took 17 seconds. This is why there should be some thought put into logging levels and why there should be multiple trace sources, so that most of them can be off most of the time.

Thou shall be very wary of logging to the same transactional database as the application.
Jeff had a bad experience with this kind of logging and decided to throw the baby & bath water out. I think they just needed to rethink what trace’s promise and possibilities really are.

Thou shall use a TraceSource per class.
There should be a trace source per class. Typically we’re debugging a few classes at a time and turning off the other trace by commenting it out isn’t a practical solution.

Thou shall not use System.Diagnostics.Trace or System.Diagnostics.Debug
Use TraceSource instead. You can’t turn off these sources as easily as a TraceSource

Thou shall not reinvent System.Diagnostics. Extend it. Resist using other people’s re-inventions. Do use other people’s extensions
Trace is for maintenance developers. A maintenance developer shows up on the scene and the last thing they want to see is yet another custom solution for a solved problem. How excited would you be to find a code base that shunned System.IO’s file system API and used an entirely custom one? Your app has a bug. You have one problem. You find out all the trace is written using a odd ball trace infrastructure. Now you have two problems.

Thou shall not do start/end trace with nothing inbetween
Entry exit should be recorded for things that have multiple traced steps. If there is nothing in between start/end, it shouldn’t be added to the story *unless* you are doing performance. If you are recording enter/exit, you should also record the amount of time. You should use a Dispose patter to ensure that the End is written.

Thou shall write a unit/integration test that is has been tuned for a good trace story.
The trace story should be shorter than a novel, longer than a flippant comment.

Thou shall not write a Error trace unless we know it will also be error logged via Elmah or the like
Trace is not error logging. The maintenance developer is obliged to look at the error log, Trace is only on occasionally and even after tuning could have too much info.

Thou shall educate the maintenance developer on how to use the existing trace
The .NET framework has a couple of trace sources. To get at them, you have to just know that they exist. There isn’t an easy way to query an assembly and ask it what trace sources are there and what switches it takes to activate them.

Thou shall look for opportunities to replace comments with trace
We don’t want code to become less readable because of trace. So apply the same reasoning about deciding when to comment to when to log (don’t log the obvious, like most variable assignments)

Thou shall not focus on domain specific events
These would be things like “John editing record B”, or “Sold book to customer Q”.

Thou shall use trace as sort of a poor mans Method-was-called Assertion
For example, if you are caching an expensive value, then on first call, there should be a trace message from the CreateExpensiveValue method and on the second go round there shouldn’t be any trace message. But unlike a unit test, the assertion is verified by a developer reading code. This shouldn’t be a substitute for using mockign frameworks.

Thou shall not bother with Warn. Just use Error and throw an Exception.
Warnings need to have an audience and trace doesn’t always have an audience. Exceptions have an audience. And when an exception is thrown, we may want to add that to the story, since trace and error logs aren’t necessarily going to be together.

Thou shall not bother with Verbose. Just use Info
Lets say I write a trace and I call it information. Years later it is in a tight loop that is executed 10 times a millisecond. You can’t control or predict in advance if a given message is info or verbose.

Thou shall see the link between Trace and step through
Ever step through code that kept going throw a 3rd class and you though, I wish this would stop stepping through that class? You could add attributes (and remember to remove them later) or you could switch to a trace strategy that allows you to turn off trace for the likely-just-fine class.

Rude and Passive Aggressive SQL Error Messages

December 5th, 2011 by matt | No Comments | Filed in SQL Server

First off, some people are just “rude-deaf” It doesn’t matter what rude language or actions one complains about and they say, “No that wasn’t rude, the error message only said ‘Fuck you and your grandmother’”

Second, you don’t have to have an error message that says “Fuck you and your grandmother” to be rude. Most error messages crimes are being unhelpful and passive aggressive (i.e. hostility through doing nothing, like just watching someone on crutch struggling to open a door)

Incorrect syntax near ‘%.*ls’.
This message typically is filled in with something like , or ‘ A typical query is choc full of commas. Only a passive aggressive human would tell someone, “There is a spelling mistake in your term paper near one of the spaces” SQL error messages tend to identify the location of a syntax error by a chunky measure, maybe the statement, so the error could be anywhere inside a 1000 line SQL statement. And if the syntax error could provide the previous 100 and succeeding 100 non-blank characters with a pointer at where SQL first realized something went wrong, that would be helpful.

Warning: Fatal error %d occurred at %S_DATE. Note the error and time, and contact your system administrator.
First off, the people who read this either are the administrator, or there isn’t an administrator. You might as well swap in some other imaginary figure, like god. “Fatal error. Pray to your gods, fucktard”

The type ‘%.*ls’ already exists, or you do not have permission to create it.
Oh SQL, you know why this failed. Surely there isn’t a single method called ExistsOrLacksPermissions and the implementers just can’t decide why that exception was thrown. I think this error is rude or fucked up. You decide.

Finally, be helpful.
Is it really so hard to write a suggested fix? “Permission denied, execute “GRANT” command to grant permissions”

Google exists, who ever is working on MS-SQL ought to google all their own messages and just put a sentence worth of the internet’s collective advice into their error message.

ClickOnce Experiments

November 11th, 2011 by matt | No Comments | Filed in .NET

Okay, I used to think click once was a sandbox, kind of like Java applets. I used to think that all click once applications installed from an internet link would be put in a sandbox with partial trust so that certain .NET API and unmanaged code couldn’t be executed.

I was wrong! At least, according to my experiments today with .NET 4.0 and click once.

I took the cassini source code and wrote it so that it would launch and then set up a virtual directory for a website that I bundled with it, essentially as “resource”/”content” files. I figure out how to get that to work in .NET and in ClickOnce. I thought, gee, I thought the APIs necessary to load an AppDomain and host an ASP.NET site and serve files on port 80 would be forbidden by the sandbox, right? Initially I thought it was because I was installing it locally. So I put the files up on a website, downloaded and installed and it still let cassini run as in the ClickOnce local storage area, and serve up a website in Full Trust.

Well, the sandbox is opt-in. If a software publisher doesn’t opt in, the user just gets a warning that doesn’t really make any sense and the application runs in Full Trust.

I did check to see how cassinni runs in ClickOnce after opting-in to Internet level trust. Now, the click once version of Cassini fails as soon as it tries to find out the path to it’s own assembly files. I still got… well not so scary as unintelligible warnings about needing to “trust” the remote website.

Well, so much for sandboxing. Now one thing worth nothing is I only get the browsers warning “Hey this came from the internet, sure you want to run it?” I don’t get teh UAC curtain of “this application will change your machine”. I do get the unintelligible Click once, message “Unknown publisher, this app has access to your machine, start menu, and well, it came from the internet” I’m imaging grandma reading that and thinking, “Well, I don’t personally know them either and I’ve already been told this is from the internet” Where else does software come from? The machine I’m writing from doesn’t event have a CD drive.

So a malicious code writer would distribute code and not opt in to sandboxing, in full expectation that some people will click through the messages.

A non-malicious code writer would only get benefit from this if he opts into sandboxing, didn’t need those other APIs, and if a malicious code writer tried to sneak an assembly into the non-malicious application and execute it, maybe if the sandboxed app has a plug in feature. Why bother with malicious plugins when you can just get people to run your separate full trust app? And besides, to run a plug in .NET you need to be able to load assemblies on demand and I bet a medium or low trust application wouldn’t be able to do that.

Tags:

Custom Exception Antipatterns

September 6th, 2011 by matt | No Comments | Filed in Matthew Martin

try{ } catch(SomeException)
{ throw MyCustomException(”Error in middle tier, method foobar()”);}

The above is wrong for multiple reasons. The text only tell you some stack trace information. Unless you know for sure that your error logging infrastructure or error reporting discards the stack trace and you can’t fix it, then don’t put stack trace information in your error. The default yellow screen and Elmah both capture stack trace.

The next reason the above is wrong, it overwrote the error. The error used to be something specific, e.g. SecurityException because you had the wrong NTFS permissions, for FormatingException, because you had two decimal points. But now the error is overwritten with “something bad happened”

try{ } catch(SomeException e)
{ throw MyCustomException(”You need to run batch file foo.bat”,e);}

The above pattern wraps the exception. But error loggers don’t always display the internal errors, especially if there are multiple internal errors. Don’t wrap errors unless they are providing something remarkably valuable or unless you are *actually* writing code to specifically trap this sort of error on the next tier. (planning or thinking you might in five years doesn’t count)

In ASP.NET don’t catch unless you feel pain from not catching.

In winforms, you have to catch, else the application exits. But in ASP.NET, only the page request ends. From the user’s standpoint, the application is still running because the next request can still succeed.

It’s not engineering. It’s school yard psychology

July 28th, 2011 by matt | No Comments | Filed in Matthew Martin

#regions are where we hide our shame and self loathing from not being able to refactor our class into anything smaller than 2500 lines of code. We only tell ourselves that we are being tidy so the self delusion does seem so obvious and depressing.

xml comments are where managers say “Get moving on documentation!” and developers respond by shuffling from foot to foot to show some movement.

The same people who write empty xml comments and add regions to their massive classes are the same people who ignore compilation warnings.

Microsoft is kind of like a parent with multiple, perverse personalities. They tell us to not use “autoeventwire up” because it’s a bug generator, then it is the default in Visual Studio.

Mobile Development and ASP.NET Websites

June 13th, 2011 by matt | No Comments | Filed in ASP.NET

I’ve been ignoring mobile development for the last decade. I have never been rich enough to buy the 300 phones necessary to do WAP development (a prerequisite for creating “hello world” that works across two phones). But iPhones, iPad, iPods and Androids over 3G change things. The network is fast enough, the UI conventions that Apple created make things worth looking at again. Since iPads can read random websites and render them pretty well, you’d think you could take conventional webapps and port them to iPhone/iPad Etc. You will want to use a library that will give you a iPhone theme and widgets, such as jQTouch, iUi or others. But those libraries all fall on their face to varying degrees if you browse them in MSIE (no surprise), Chrome(!), and Firefox. I didn’t check Safari, but I’ve read that many of these iphone targeting framework fail on desktop Safari, too.

You still have to write two websites, testing in two browsers. The only browser that behaves similar enough to an iPhone is iBB (download here)

There is only one library that doesn’t fall on it’s face in MSIE, that’s ComponentOne’s iPhone component library. But it costs about a grand. Performance seems sluggish, but that may just be the demo site– production code might be faster (fewer elements for one)

Also, (all?) the libraries seem to encourage MVC style programming. iUi for one, puts multiple forms on a single page, something that non-MVC ASP.NET can’t easily cope with.

Mercurial and .hgignore

May 31st, 2011 by matt | No Comments | Filed in Visual Studio

The .hgignore file must exist before the /bin/ /obj/ etc files exist. If you edit the .hgignore file after the /bin files have been created, you have to tell tortoise to forget the files. In my case, it was easier to completely empty out the folder by moving all the files outside of the repository folder & then re-adding them– this time with the .hgignore file in place.

The file needs to be at the root of the repository. This is an unlikely cause of the problem. It isn’t clear if putting the .hgignore file in every @#$@%^ folder helps.

There are about six ways to exclude /bin/,

glob:/bin
glob:*/bin/*
glob:bin/
regex:\/bin\/
glob:\/bin\/

And so on. God knows which one actually works, it isn’t clear if putting every @$!@% version in the .hgignore file will trigger an ignore.

Anyhow, I never had this problem with Ankh and Tortoise SVN. Tortoise SVN understood windows and Ankh understood .NET projects. The corresponding mercurial products don’t seem to understand either, and seem reluctant to ignore.

Personally, I’d rather a version control tool that was reluctant to ‘add’.

The standard advice on new opensource projects

January 31st, 2011 by matt | No Comments | Filed in Development

The Linux Advice
Work on a project alone until the project becomes so big, successful and large that other developers beat a path to your door.

This isn’t really very useful advice. It kind of implies some extreme assumptions– no one will help on a small project, and only really big, successful one man projects can attract community contributions.

Code yard sales
I heard the phrase first on Hanselman. Here’s some junk code, have fun. Because the original commiter is so … uncommitted, the project isn’t likely to go far.

This model has it’s places, but it doesn’t help if you want a medium sized open source project to grow and have some modest success.

Face it, odds are low your project will become as successful as Linux and it’s unnecessarily lazy to give away your starting code base and abandon it.

WordPress-style Plug in Model
If the application is designed from the get-go for extensibility in a variety of ways, from basic stuff like using abstract classes and interfaces, to using a full blown plug-in architecture, then people can  contribute in an unco-ordinated fashion, perhaps without even committing to the main trunk.

The core of the application is a component host. The lead developer first job is to provide the glue for the parts. The particular functions would be secondary. I think this is counterintuitive, but essential. If I have an idea for a great blog engine, if I write a blog engine first, I will have to retrofit it for plugins. If I write an application host first, albeit one optimized for plugins, then it will be a very different application.

Validation Application Block Post Mortem

January 27th, 2011 by matt | No Comments | Filed in Matthew Martin

VAB seemed to work only for simple domain restrictions on a single property.  This is the least interesting, least value providing sort of validation.  At worst It is a 2 line if/then block of code! Replacing it with an attribute saves 1 line of code and creates some design rigidities.

If you had complex logic (and it didn’t have to be very complicated), one was tempted to write complex expressions in attributes. This is ugly programming.

If you had complex logic, you were supposed to write custom validators.  Contrary to this blog post, which says, “This is very easy to do”, this is not easier than writing a Validate() method– at the very least, it’s 100s of lines of extra code.

The custom validators tend to be a lot like
List<string> Validate(MyObject someObject),
which is the way things were before attribute driven programming.

The codebase began to evolve to use VAB less and less.

Today I’m removing the assembly.