I have a .NET application that generates an XML file via serialization (through XmlTextWriter) and submits the data via https. Recently, they changed something on their end to only accept an upper cased UTF-8 encoding, like this:
<?xml version="1.0" encoding="UTF-8"?>
Unfortunately, using the .NET classes mentioned above, it generates the encoding string in lower case. I could find one mention of this on google, and they said to have the other company change (not an option here), or override XmlTextWriter. I went with that approach, making heavy use of Reflector along the way. I started by looking at the WriteStartDocument method, but realized that the private StartDocument is the thing that generates the output. It also gets called by the overloaded WriteStartDocument, so I'd need to override that method, too. However, in the private StartDocument method, it uses a bunch of private variables and generates output via another private method, InternalWriteProcessingInstructions. Ugly. At this point I realize that XmlTextWriter is not a class made for inheriting.
Back to Reflector, and I notice that the Encoding.WebName is the property used to write out the encoding string. I now create a descendant class of UTF8Encoding. The class is listed below. Now I just call XmlTextWriter, passing in UpperCaseUTF8Encoding.UpperCaseUTF8 for the Encoding type, and everything works perfectly. public class UpperCaseUTF8Encoding : UTF8Encoding
{
public override string WebName
{
get { return base.WebName.ToUpper(); }
}
public static UpperCaseUTF8Encoding UpperCaseUTF8
{
get
{
if (upperCaseUtf8Encoding == null)
upperCaseUtf8Encoding = new UpperCaseUTF8Encoding();
return upperCaseUtf8Encoding;
}
}
private static UpperCaseUTF8Encoding upperCaseUtf8Encoding = null;
}
I went in search of an application that would synchronize my bookmarks. It needed to meet the following minimum specifications: - Sync between Windows and Macintosh
- Sync bookmarks between IE, Mozilla, and Safari
- Sync between machines
- Automatic synchronization. If I have to perform a manual step, I'm not interested.
- Could not be an Internet-only bookmark storage service
- Good conflict detection and resolution
Sync2It met all of those requirements, and after using it for a couple of weeks with no real major issues, I bought it. Diigo and Google bookmarks were very good applications, too, but didn't pass some portion of my needs. I did email the author about some enhancements I'd like to see to make Sync2It even better. I'd encourage you to try and buy Sync2It. That way, maybe these suggestions have a chance of getting implemented.  - While the Mac download doesn't say it, it does appear to work with Leopard.
- The Mac version only syncs with IE and Safari. We need Mozilla support on this platform.
- Provide an easy way to auto-launch the Sync2It application as a daemon when logging in.
- We need to be certain that Safari 3 is supported (both on Mac and Windows).
- It would be nice to have some kind of log to see the actual activity of a given sync.
Here's hoping this will let me focus on saving and categorizing bookmarks, as opposed to constantly leaving stray bookmarks around and needing that one bookmark on the one machine I'm not currently using!
I had a need to move some VB.NET code to C# today. We're still not at the point where we can just mix and match languages within an assembly, and in this case, it would be more work than I wanted to separate things out. I looked around the net, and the best code converter that I found (read: it successfully converted everything I threw at it, where others failed) was this one.
I needed to put 2 test assemblies into my automated CruiseControl.NET build and get coverage results. It appears that this is a pretty common need, with some tricks to get things working properly. According to http://www.kiwidude.com/blog/2006/10/ncoverexplorer-merging-ncover-reports.html, you need to either use an NUnit project file to contain all of the unit tests or merge the coverage xml files in the NCoverExplorer task. NUnit project setup and problems By using an NUnit project file, all of the tests are executed within one call, which produces one coverage.xml file. This allows tests from multiple test assemblies to be merged together into one coverage file that NCoverExplorer will understand automatically. <TestAssemblies Include="MyApp.Tests.nunit" />
MyApp.Tests.nunit contents: <NUnitProject>
<Config name="Default" binpathtype="Auto">
<assembly path="MyApp.DAL.Test\bin\Debug\MyApp.DAL.Test.dll" />
<assembly path="MyApp.Service.Test\bin\Debug\MyApp.Service.Test.dll" />
</Config>
</NUnitProject>
The major downside of this approach is that, according to http://nunit.com/blogs/?p=9, when using the NUnit project file, the config file that gets loaded needs to be based off of the NUnit project filename (i.e. in this case, MyAppT.Tests.config) and not the individual test assembly filenames. This means that we need to continually merge all of the app.config files into one "master" config file. This is not exactly a long-term, maintainable solution.
NCoverExplorer task setup
That brings us to the second possible solution presented above, namely to merge multiple coverage files together. To do this, you need to take some care in how you set the properties up for the tasks so that you don't overwrite coverage output files. My current build project looks similar to the one below. One other thing to keep in mind is to include the *.CoverageMerge.xml file in your CC.NET config file's <merge> section for this project. <ItemGroup>
<TestAssemblies Include="$(DALTestAssembly)" />
<TestAssemblies Include="$(ServiceTestAssembly)" />
<NCoverAssemblies Include="$(DALAssembly)" />
<NCoverAssemblies Include="$(ServiceAssembly)" />
<NCoverCoverageFiles Include="**.Coverage.xml" />
</ItemGroup>
<Target Name="Test" DependsOnTargets="CoreBuild">
<NCover ToolPath="lib\NCover\"
CommandLineArgs="%(TestAssemblies.FullPath) /xml=%(TestAssemblies.Filename).xml /labels /nologo"
CommandLineExe="lib\NUnit\nunit-console.exe"
CoverageFile="%(TestAssemblies.Filename).Coverage.xml"
LogFile="%(TestAssemblies.Filename).Coverage.log"
LogLevel="Verbose"
WorkingDirectory="$(MSBuildProjectDirectory)"
Assemblies="@(NCoverAssemblies)"
/>
<NCoverExplorer
ProjectName="MyApp"
ReportType="ModuleClassSummary"
OutputDir="$(MSBuildProjectDirectory)"
XmlReportName="MyApp.CoverageSummary.xml"
HtmlReportName="MyApp.CoverageSummary.html"
ShowExcluded="True"
SatisfactoryCoverage="80"
CoverageFiles="@(NCoverCoverageFiles)"
MergeFileName="MyApp.CoverageMerge.xml"
ToolPath="lib\NCover\Explorer"
/>
</Target>
To be sure, this is an incomplete list, but it is a good start. Here's what I don't like about LINQ to SQL: - It only works with MSSQL. Yes, this point has been beaten to death, but it is entirely justified. Third party solutions don't cut it. LINQ to SQL intentionally seeks to exclude a sizeable population because of this hair-brained decision.
- No way to easily specify adhoc LINQ queries. This doesn't count. I know the benefits of design-time queries, but I should also be allowed to shoot myself to get the added flexibility if I so choose. Building up expression trees is not a viable option for every day development.
- The constant labeling of LINQ to SQL as an OR/M. That label considerably overstates what this technology does. One to one mapping between a table and a class is not really OR/M. It seems like they want to force you to change your database by writing stored procs and views to make your object model better.
- There is no automated way to easily pick up changes to the database schema.
- There is no easy way to preserve changes to the generated code. e.g. I change the name of the automatically generated class from collection_details to CollectionDetails, but I evolve the schema of the table. When I re-add the table, I need to set all of the custom properties again. I know I shouldn't change generated code, but see the next point.
- Speaking of collection_details, it would be much better if the underlying class generator had some options to clean up legacy table names (e.g. remove underscores, camel case resulting table and column names).
- No many-to-many support. In short, when you have an junction table (aka associative table or cross-reference table), you will need to write code like this: User.UserPermissions[0].Permission vs. User.Permissions[0]. Until we see LINQ to Entity (if ever), we do have this, but you can't use the new entity in a LINQ query.
- There is no built-in solution to using LINQ across tiers. I don't want to expose my LINQ classes (see the point above about the tight coupling between database and objects) as I may want to change my database, and I don't want that cascading to all of the places that use it. There is also no diffgram, so even if I did it, I would have to write my own change tracking and resolving support. I went to an OpenSpaces meeting on this very topic during CodeMash, and the consensus was not flattering.
In short, it seems like this part of LINQ was released way before it was ready. But it does demo well... Feel free to add your own grievance to the comments.
I have a PATH that is miles long, and I needed to find out where a certain application was launching from. On a good operating system, this kind of functionality is built in. On a Windows operating system, you can create a BAT file, or download a utility.
I have been reading Dustin Campbell's series, The 12 Days of Refactor! X-mas, with interest. He's a very good writer, and has broken down a bunch of Developer Express features into easy to digest chunks of information. The episode I linked to above touched on the XML Literal support that shipped with VB in Visual Studio 2008. The one sentence summary of this technology is that it lets the VB compiler translate raw XML in the source code into strongly-typed code using XML classes under the hood. It's a very nice idea, and I encourage you to look at the links to learn a little more about it. While the VB team thought this was a good idea and added the feature, Anders and the C# team believed that it was superfluous to add such a thing to the C# side. I haven't really made up my mind which group I side with yet. However, Anders is benevolent , so he gave us the little-documented PasteXmlAsLinq addin that will take XML on the clipboard and paste it into a file in C# syntax building the XML up using classes like XElement. In a default install of VS2008, open C:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\CSharpSamples.zip and extract the LinqSamples\PasteXmlAsLinq files. There is a Readme.html file in there that tells you how to build, install and use the addin. While this isn't the same as VB's support for XML Literals, it does make things easier to work with.
Things I learned this week (sorry, Carl!): - The Cisco VPN Client software is very fickle. In order to upgrade from 4.8 to 5.0, you need to uninstall and install, with reboots to be found everywhere.
- Installing an entire slew of MS updates is usually a good idea to keep your system up to date.
- Even though your computer works fine at home, you can't rely on it working the same way when you get to work. For example, you might have internet access at home with no problems, but when you get to work, traffic over port 80 will suddenly stop about 5 minutes from the time you power up. https, ftp, email, IM, and everything else will continue to work just fine. Just no http traffic over port 80.
- 5 minutes is not a lot of time to conduct google searches to find out what's wrong.
- MS System Restore is implemented about as horribly as anything I've ever seen.
- After running System Restore, the problem does not go away.
- To make matters worse, System Restore totally hosed my Office install where it deleted a bunch of files from MSOCache, thereby causing my Office products to not be able to launch properly, or even uninstall.
- After copying missing files back to MSOCache, all of the Office applications claimed they needed to repair installs upon launch. Every time.
- MS has really good directions for how to manually uninstall Office 2007.
- Seconds before doing a complete wipe of your system, it's a good thing to double check with friends who have Google-Fu.
- It turns out that c:\windows\system32 has 2 files: vsdatant.dll and vsdatant.sys. These files get linked with ZoneAlarm a lot in google searches, but they are also used by the Cisco VPN Client. Something in the Cisco (un)installer caused rogue versions of these files to be left in my system. Rebooting to Safe Mode to clean these files up (along with the registry entries) finally got things back to normal.
And that, my friends, is what I learned this week. Now where's that next Monday's episode?!?
|