Home     Wordpress     Log in

Archive for the ‘.NET’ Category

ASP.NET Profile Compilation- Mystery Solved!

August 17th, 2009 by matt | No Comments | Filed in .NET, ASP.NET

ASP.NET will kick off a little profile thingy when it finds a <property> section. It appears to go into the ASP.NET Temporary Folder. It seems to be a private method in ProfileBase that loads this.

Some errors that happen:
Sometimes deleting the <property> section and readding it works. This happens all the time for all sorts of reasons, not just profile related, but dynamic compilation and shadow assembly related.

ProfileCommon not available- this is supposed to be compiled either at design time, run time or sometime. It fails to work in a variety of circumstances.

Precompiled apps can have problems with the ProfileBase class
Ambiguous reference errors- can happen when App_Code.Compiled or PrecompiledApp.config exist or fail to exist and ProfileCommon gets compiled twice.
Similarly copying the bin of the new version into the bin of the old is bad. You get a blended set of .dlls
Deleting files in ASP.NET Temporary Files sometimes works.

Interestingly, all the above don’t seem to be addressable by writing a custom provider. It doesn’t seem possible to override the settings part, where it reads web.config and starts trying to create that problematic ProfileCommon.

Conclusion
It turned out to be a dll that was referencing a native dll that wasn’t on the PATH. The profile was just triggering a compile. The compile then check references for everything in the \bin\ folder, even if the profile or invoked page isn’t using it. Oddly, this doesn’t happen on every single page, so there are some code paths where ASP.NET doesn’t feel the need to recompile every !@#$@!#$ thing in the world. This, I suppose is good or else we’d see pathalogical compile churning.

I diagnosed this by watching the list of assemblies that were getting loaded in Visual Studio while the debugger was attached. If it couldn’t load symbols or if it was obviously a COM dll, I considered it a candidate and finally narrowed it down to a SMO library, which happens to have non-managed dependencies.

The sorry state of application security audit logging

June 8th, 2009 by matt | No Comments | Filed in .NET

Security oriented audit logging records what happened and who did it. So lots of logging frameworks fail because they aren’t very well integrated into the authentication scheme. Ideally, the log entries would non-deniable and read and write-only (i.e. no updates and deletes) by a non-administrator. And super-ideal would be a rich, granular permissions system. For example, NTFS rights are read/write. There isn’t an append-only right for files. And ordinary users need to be able to write to the log. Logging isn’t useful if only the administrator can write a log entry. And ordinary users need to be able to review the log, although not necessarily the same ordinary users that wrote to the log.

This excludes logging techniques where you can write

Log(”I committed a crime”);
DeleteLogs(); //or update logs

Likewise, this should’t happen when running as user John Doe:

Log(”Bill committed a crime”); //Not me!

Windows Event Log.
Requires pinvoke/win32 API calls to record event with user Id.
Can log to Application from ASP.NET with blank user from C#.
You might not even be able to tell which website or application wrote the error log entry.
Looks like it only works with windows authentication, and not custom authentication, e.g. GenericPricincipal.
Only an administrator can create a new log/event source.

Sql Event Log
No user (except SPID) is recorded
Xp_Logevent requires membership in dbo in master, or systeadmin, or explicit rights

EXECUTE master..xp_logevent 50003,’hello world E’, ERROR
RAISERROR (’hello world from raiserror’, 500000,1) WITH LOG –Requires sysadmin rights to use WITH LOG

IIS Log
Response.AppendToLog(”Action recorded by Austin Powers, really.”);
Has the cs-username field, but it is the service name, not the real user.
For IIS5/6 you need to write an ISAPI filter to hook into the code writing to that log to change cs-username.

The given columnMapping does not match up with any column in the source or destination

November 30th, 2008 by matt | 1 Comment | Filed in .NET, ADO.NET

The SqlBulkCopy object is good, but probably buggy. The fact that it is case sensitive to columnames to me is a sign of likely low code quality, and the error that gives this blog entry its title is another.

Sometimes bulk copy will import a table from text without explicitly setting the columns. Sometimes you have to explicitly set the columns and poof! it works. It may have to do with white space or case sensitivity in the columns, or it may have to do with drivers making inaccurate counts of fields.

SqlBulkCopy bcp = new SqlBulkCopy(
“Server=.;persist security info=True;initial catalog=target;Integrated Security=SSPI”,
SqlBulkCopyOptions.KeepIdentity & SqlBulkCopyOptions.KeepNulls);

bcp.BatchSize = 50000;
bcp.ColumnMappings.Clear();

for (int i=0;i {
string name = reader.GetName(i).Trim().ToLower();
bcp.ColumnMappings.Add(name,name);
}

for (int i = 0; i < bcp.ColumnMappings.Count-1; i++)
{
System.Diagnostics.Debug.WriteLine(bcp.ColumnMappings[i].SourceColumn);
}
bcp.DestinationTableName = file.Name.Split('.')[0];

bcp.WriteToServer(reader);

bcp.Close();

NOTE: Even explicitly listing the columns often is not enough. I eventually gave up and used alternate techniques. The command is poorly documented with respect to what text formats are acceptable for BIT, DATETIME, IMAGE when doing heterogeneous bulkcopy. Until MSDN documents it, this otherwise fantastic tool is only reliable for copying from SQL to SQL with identical schemas and probably identical version and patch levels.

Error Messages: On_Error_Insult_User

November 3rd, 2008 by matt | No Comments | Filed in .NET, Programming

In the good ole days, if we hit an error message, we’d just write to the console a routine insult to the user.

If input_arg<0 then Print “You are such a dumb ass”

We now hide our contempt in secret code

If input_arg<0 then Print “Please contact your administrator”
/* You are such a dumb ass */

Sometimes we prefer the “I’m smarter than the runtime” pattern and send developers on a goose chase.

Sign the Pledge! Sign the Petition! Down with #region!

October 3rd, 2008 by matt | No Comments | Filed in .NET, ASP.NET, VB.NET, Visual Studio, c#

I beseech the developer community to swear to never use #region or #endregion blocks again, except for possibly machine generated code.

The first step is to stop typing #region and #endregion. This will greatly improve the transparency of your code. Next, because you are the sort of person that uses #region and #endregion to hide the code you are ashamed of– go find all those HACK:, BUG:, and CRAP: comments.

try/finally without catch

September 25th, 2008 by matt | No Comments | Filed in .NET, VB.NET, c#

You will get a YSOD, but the finally block executes before the YSOD.

try
{
int bar = 1 / int.Parse(this.TextBox1.Text);
int z = 21;
z++;
}
finally
{
int foobar = 1 + 1;
}

This is kind of like a IDisposable patter at the method and code block level. It means, on the way out of this code block, I want some clean up code to run. Off hand I can’t think of a good reason for this if you aren’t releasing resources. Using it as a control of flow technique looks very iffy especially if it wasn’t the error you were expecting.

Identical behavior to the above, YSOD, but finally block runs just before the YSOD. The following is code you’d see in code generation scenarios where the try/catch/block is code generated with the hope that the developer would fill better error handling later.

try
{
int bar = 1 / int.Parse(this.TextBox1.Text);
int z = 21;
z++;
z++;
z++;
}
catch (Exception) {
throw;
}
finally
{
int foobar = 1 + 1;
}

YSOD after line one, no other code after the error is executed

int bar = 1 / int.Parse(this.TextBox1.Text);
int z = 21;
z++;
z++;
z++;
int foobar = 1 + 1;

Catch/Rethrow

August 31st, 2008 by matt | No Comments | Filed in .NET

How often do you see this pattern (or variations on it)

try{
…some code…
}
catch{
throw;
}

Sometimes it will be catch(Exception ex) or catch(SomeParticularException ex), and sometimes it will be throw; or throw ex;, there is no finalizer block, but the important thing is that NO OTHER ACTION IS TAKEN (no logging, no retry, nothing else in the catch block).

As far as I can tell, this is equivallent of wrapping code in NOP (no-operation) commands.

Please don’t do this.

Automated Testing Using WebClient and HTML Agility Pack

August 24th, 2008 by matt | No Comments | Filed in .NET, ASP.NET, Unit Tests

I researched options for testing my ASP.NET website. I decided to use Scott Hanselman’s solution where simulate IIS using Cassini and simulate a browser using WebClient.

Good Points
It works!
It’s free!
Doesn’t require a massive refactoring or rewrite.

Challenges
Cassini should be a singleton. Unless you are testing something that is IIS dependent, you should not destroy Cassini inbetween each test or test fixture.

.NET Attributes to use more often

August 12th, 2008 by matt | No Comments | Filed in .NET

My theme here are general purpose programming attributes, ones that you might use for any class.

(first seen here)

DebuggerStepThroughAttribute, [DebuggerStepThrough()]
You can still set breaks here, but normally the debugger will fly right over it. Use this when you find yourself running through the same boiler plate code over & over again, especially if the code is machine generated, or otherwise not of interest.

DebuggerNonUserCodeAttrbute.[DebuggerNonUserCode()]
No step through, no breaking, even if you have a breakpoint.

[DebuggerDisplay(

Built in Exceptions you should use

August 12th, 2008 by matt | No Comments | Filed in .NET, ASP.NET

I’ve been using FxCops which looks down on “throw new Exception();”

Here are some more narrow exceptions that already exist in the framework that you should throw, hey it saves you the effort of writing a custom error class.

ArgumentNullException - Argument is null
ArgumentException - Argument not valid
ArgumentOutOfRangeException– arguement too big or small, or not on the list
ArithmeticException — The root of a negative number
InvalidOperationException -given state,