|
Mar
08
2010
Monday, 08 March 2010 11:56 AM
by
Coose
One of the most annoying parts of developing with WCF and Silverlight is the configuration files. I have always hated WCF configuration files. While powerful and necessary, they are just the opposite of fun.
Using Visual Studio 10 “publish” web functionality, the Web.Config files could be transformed with Web.Release.Config. Not bad. Makes things a little easier. Here’s the rub: when creating a WCF/Silverlight application, the publish transformation would transform the web.config for the server, but NOT the ServiceReferences.ClientConfig on the client. What a PITA.
Some Microsoft blogs show that the preferred solution for this problem is to rename the published .xap file to .zip, then open the .zip file, extract the .ClientConfig file, change it, save it, re-zip it, then rename the .zip back to .xap.
Really?
After the first time, this got so cumbersome I wanted to shoot myself. Really I wanted to shoot someone at Microsoft. :) Anyway, Google provided a few solutions, none totally to my liking.
My boss pushed the ConfigSwitcher project on me, as in theory it seems to be what I am looking for. Being pre-VS2010, this didn’t use the XML transformation functionality but instead used a full copy of the config file, and required another .exe that had to be copied to each machine that this would be run on. But it is a good idea.
So my strategy is to write custom build tasks that copy the ServiceReferences.ClientConfig file to a temp file before the build, then run the XML transformation using ServiceReferences.$(Configuration).ClientConfig and output to ServiceReferences.ClientConfig. Then after the build completes, and the transformed file has been put into the .xap file, delete the ServiceReferences.ClientConfig, and copy the original file (which is now a temp file) back.
So…
Before Build:
- Copy ServiceReferences.ClientConfig to ServiceReferences.Build.ClientConfig
- Transform ServiceReferences.Build.ClientConfig to ServiceReferences.ClientConfig using ServiceReferences.$(Configuration).ClientConfig
and After Build:
- Delete ServiceReferenes.ClientConfig
- Move ServiceReferenes.Build.ClientConfig to ServiceReferences.ClientConfig
And, I don’t want any more baggage required. I don’t want a program that has to be installed on developer machines, and I don’t want a macro that has to be present on developer machines. I don’t even want custom MSBuild targets installed. So, to do this, I use the BeforeBuild and AfterBuild target overrides of the .csproj file, and I use the already present XmlTransform task of Visual Studio 10.
So, unload the project and edit the .csproj file directly. Scroll to the bottom and there are commented out BeforeBuild and AfterBuild overrides. Adding this snippet:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="BeforeBuild" Condition="Exists('ServiceReferences.$(Configuration).ClientConfig')">
<Move SourceFiles="ServiceReferences.ClientConfig" DestinationFiles="ServiceReferences.Build.ClientConfig" />
<TransformXml Source="ServiceReferences.Build.ClientConfig" Destination="ServiceReferences.ClientConfig" Transform="ServiceReferences.$(Configuration).ClientConfig" />
</Target>
<Target Name="AfterBuild" Condition="Exists('ServiceReferences.Build.ClientConfig')">
<Delete Files="ServiceReferences.ClientConfig" />
<Move SourceFiles="ServiceReferences.Build.ClientConfig"
DestinationFiles="ServiceReferences.ClientConfig" />
</Target>
gives me what I want. If there is a file named ServiceReferences.Release.ClientConfig and I am building a Release version, then the transformation is run at compile time, and the transformed .ClientConfig is put into the .xap file.
Development
silverlight | visual studio
Dec
17
2009
Thursday, 17 December 2009 10:04 AM
by
Coose
We like to stay ahead of the game and get the newest stuff on the .NET platform when we can. Since VS2010 and .NET 4.0 Beta 2 came out recently, we are in the process of migrating to it. When trying to use an ASP.NET AppPool with the 4.0 Beta 2 framework (4.0.21006), I could get nothing but a “503 Service Unavailable” on any web site using that AppPool. Long story short: Some of the framework Beta 1 components still existed in the framework directory (c:\windows\microsoft.net\framework\v4.0.21006). Delete that folder, restart the AppPool, and all is well. Does it surprise anyone else that Microsoft’s Beta Uninstaller didn’t do a complete job of uninstallation?
Mike's Blog
visual studio
Dec
08
2009
Tuesday, 08 December 2009 11:43 AM
by
Coose
Visual Studio 2010 Beta 2 has been running relatively good for a while now, but today, I had a crash in the WPF designer, which crashed Visual Studio, and it could not start again. When trying to launch, I just get a “The application cannot start.” error. No more info. That’s it. The problem is caused by the Visual Studio environment not saving correctly. It saves and cleans up with the IDE closes. In my case, the IDE didn’t close correctly, so the settings weren’t saved. So, to fix it simply, run devenv /resetuserdata Be warned: all of your settings are going to be erased. Any fonts that you had configured, your MRU’s, etc. Everything will be reset to “factory settings”. But at least Visual Studio loads again.
Development
visual studio
Oct
19
2009
Monday, 19 October 2009 09:09 PM
by
Coose
VS2010 Beta 2 was released for MSDN subscribers today. I’ve been waiting for a while and was real excited to get started with WF4. Obviously beta 1 has to be uninstalled before installing beta 2. Had a slight problem almost right away: WTF? I dug up the original beta 1 disk, and still couldn’t get past this dialog. I copied the file locally, and pointed to that folder, and still couldn’t get past this dialog. Finally, going to the Programs and Features in the Control Panel I can see that I have the TFS Object Model component. So uninstalling this component by itself succeeds. Then, running the uninstall on Visual Studio 2010 Beta 1 works fine.
Development
visual studio
Jul
14
2009
Tuesday, 14 July 2009 10:58 AM
by
Coose
I was having some problems today with my workflows, and I needed to get some more information. Of course, tracing is the obvious solution. I didn’t even know where to begin putting trace points in my code, so I thought I would jack up the integrated workflow tracing and see if that gave me any ideas. Now how to do that? I just can’t remember. Google to the rescue! Of course, you get the documentation sample: <system.diagnostics> <switches> <add name="System.Workflow LogToFile" value="1" /> <add name="Host" value="Error" /> <add name="Runtime" value="Warning" /> <add name="Tracking" value="Info" /> <add name="Activity" value="All" /> </switches> <trace autoflush="true" indentsize="4"> </trace> </system.diagnostics> Uh…Ok. But where does that go? It goes to a file (WorkflowTrace.log) in your program exe directory. And it’s plain text. How to integrate this into the Service Model tracing I already have established for my project? <system.diagnostics> <switches> <add name="System.Workflow LogToTraceListeners" value="1" /> <add name="Host" value="Error" /> <add name="Runtime" value="Warning" /> <add name="Tracking" value="Info" /> <add name="Activity" value="All" /> </switches> <trace autoflush="true" indentsize="4"> </trace> </system.diagnostics> Uh…Ok. But what listeners is it going to? For me…none. It’s not explicitly stated, so sometimes I don’t explicitly do it. We have to manually add a trace listener in the trace configuration section, not sources. So our configuration becomes: <system.diagnostics> <switches> <add name="System.Workflow LogToTraceListeners" value="1" /> <add name="Host" value="Error" /> <add name="Runtime" value="Warning" /> <add name="Tracking" value="Info" /> <add name="Activity" value="All" /> </switches> <trace autoflush="true" indentsize="4">
<listeners> <add initializeData="c:\logs\test.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelTraceListener" traceOutputOptions="Timestamp"> </add> </listeners> </trace> </system.diagnostics> Ok. One step closer to the edge. But, you can eliminate the LogToTraceListeners line altogether, and use each switch name as a source. This keeps a more consistent Service Model e2e tracing configuration: <system.diagnostics> <switches> <!--<add name="System.Workflow LogToFile" value="1" /> <add name="System.Workflow LogToTraceListeners" value="1" />--> <add name="System.Workflow.Runtime" value="Warning" /> <add name="System.Workflow.Runtime.Hosting" value="Warning" /> <add name="System.Workflow.Runtime.Tracking" value="Warning" /> <add name="System.Workflow.Activities" value="Warning" /> <add name="System.Workflow.Activities.Rules" value="Warning" /> </switches> <trace autoflush="true" /> <sources> <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true"> <listeners> <add type="System.Diagnostics.DefaultTraceListener" name="Default" /> <add name="ServiceModelTraceListener" /> </listeners> </source> <source name="System.Workflow"> <listeners> <add name="ServiceModelTraceListener" /> </listeners> </source> <source name="System.Workflow.Runtime"> <listeners> <add name="ServiceModelTraceListener" /> </listeners> </source> <source name="System.Workflow.Runtime.Hosting"> <listeners> <add name="ServiceModelTraceListener" /> </listeners> </source> <source name="System.Workflow.Runtime.Tracking"> <listeners> <add name="ServiceModelTraceListener" /> </listeners> </source> <source name="System.Workflow.Activities"> <listeners> <add name="ServiceModelTraceListener" /> </listeners> </source> </sources> <sharedListeners> <add initializeData="c:\logs\test.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelTraceListener" traceOutputOptions="Timestamp" /> </sharedListeners> </system.diagnostics> Now, a single .svclog file contains WCF Service Model tracing, as well as Workflow tracing, including activity tracing. One word of warning: Again, blindly copying and pasting code from other blogs led me to use “Verbose” as the switch value for the workflow switches. You know what? Nothing traced at all because Verbose is not a valid switch value. Yeah…I wish I had that 30 minutes of my life back. The proper switch value for verbose output is All, not Verbose. Don’t say I didn’t warn you. It is documented incorrectly out there.
Development
workflow | visual studio
Jul
14
2009
Tuesday, 14 July 2009 10:34 AM
by
Coose
We all know that Alt+Print Scrn copies the active window to the clipboard. Here’s a trick that saves me a lot of time. When entering a bug in Team Foundation Server that requires a screen shot, I copy the window, open MSPAINT.exe, save to temp directory, then attach that file on the work item. Or, on Windows 7 I use the snipping tool.
But not only is this a giant pain in the ass, it’s a huge waste of time. I stumbled across this little tidbit that I had to share. Alt+Print Scrn copies the value to the clipboard. Then just press Ctrl+V (Paste) in the Work Item window, and the screen shot is automatically attached!

Saved me tons of time and I feel a little less like an idiot.
Development
visual studio |
Jun
11
2009
Thursday, 11 June 2009 09:19 AM
by
Coose
Running on Windows 7 build 7100, I have Visual Studio 2008 SP1 and Visual Studio 2010 Beta 1 running side by side. The only problem I have run into so far (as much as conflicts go) is that all of my .csproj, .sln, .cs, etc file extensions now open Visual Studio 2010. Not ready for that move yet…but it’s an easy fix. In Visual Studio 2008: Tools | Options…, Select Environment > General, then click the “Restore File Associations”. But wait, that fixed everything but .csproj (.vbproj, etc) files. All of my projects were still launching in VS 2010 if there was no associated solution file. Copying an OLD version of VSLauncher.exe from a machine with VS2008 only to my side-by-side installation now launches all double-clicked project files in VS2008. VSLauncher.exe is found at: c:\Program Files\Common Files\Microsoft Shared\MSEnv
Development
visual studio
May
28
2009
Thursday, 28 May 2009 07:40 PM
by
Coose
It's incredibly annoying...but sometimes Visual Studio seems to "forget" to use intellisense when editing .config files. With Visual Studio 2008...it seems to be fixed...so they say. It is actually fixed...but sometimes appears not to be. Here's why, and how to fix it: If your app.config or web.config file is part of your project, it must be targeted to .NET 3.0 or higher, and there must not be a namespace defined on the root <configuration> element. If this is the case, intellisense should work just fine. If you just did a "File | Open" on a .config file, then you have to do something differently. In your C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas, there is a file called catalog.xml. This file contains the following tags: <Association extension="config" schema="%InstallRoot%/xml/schemas/dotNetConfig20.xsd" condition="%TargetFrameworkVersion% = 2.0" /> <Association extension="config" schema="%InstallRoot%/xml/schemas/dotNetConfig30.xsd" condition="%TargetFrameworkVersion% = 3.0" /> <Association extension="config" schema="%InstallRoot%/xml/schemas/dotNetConfig.xsd" condition="%TargetFrameworkVersion% != 2.0 and %TargetFrameworkVersion% != 3.0" /> These tags associate all .config extension xml files with the specified schemas based on the target framework version. If the file is not part of a current project, is has no framework version. In this case, the 2.0 version is somehow picked up. You will have some configuration options, but not the WCF ones. What I did on my configuration is to ALWAYS use the 3.0 schema with .config files. So I commented out the above lines, and added the following: <Association extension="config" schema="%InstallRoot%/xml/schemas/dotNetConfig30.xsd" /> Now my intellisense works...but if I happen to be modifying a 1.1 schema (like I do that so often), then I will get options that are not applicable. Oh well. You can tinker with the conditions to your liking.
Development
visual studio
Apr
17
2009
Friday, 17 April 2009 02:51 PM
by
Coose
My previous posts here and here talked about compiling Cassini and using it from Visual Studio. After all that, I found that Cassini doesn’t understand NTLM, and writing it is complicated. So what to do now?
More...
Development
asp.net | visual studio
Apr
17
2009
Friday, 17 April 2009 01:13 PM
by
Coose
In my previous post, I described compiling a custom version of Cassini that could listen to external requests, not just loopback. Now, I want to use that version of Cassini to debug from Visual Studio. The problem is that the command lines are different. Visual Studio uses Webdev.WebServer.exe, and issues argument in the format /port:1234 /path:c:\temp /vpath:/test Cassini expects arguments in the format apppath port virtroot So, in main.cs, I have modified the Main function as so: 50 public MainForm(String[] args) { 51 //_portString = "80"; 52 //_virtRoot = "/"; 53 //_appPath = string.Empty; 54 55 // look for arguments in the form of /port:1234, or /path:"abcdefg" or /vpath:/ 56 foreach (string arg in args) 57 { 58 if (arg.StartsWith("/port:", StringComparison.OrdinalIgnoreCase)) _portString = arg.Substring(6).Trim(); 59 if (arg.StartsWith("/path:", StringComparison.OrdinalIgnoreCase)) _appPath = arg.Substring(6).Trim(); 60 if (arg.StartsWith("/vpath:", StringComparison.OrdinalIgnoreCase)) _virtRoot = arg.Substring(7).Trim(); 61 } 62 63 try { 64 if (string.IsNullOrEmpty(_appPath) && args.Length >= 1) _appPath = args[0]; 65 if (string.IsNullOrEmpty(_portString) && args.Length >= 2) _portString = args[1]; 66 if (string.IsNullOrEmpty(_virtRoot) && args.Length >= 3) _virtRoot = args[2]; 67 } 68 catch { 69 } 70 71 InitializeForm(); 72 73 if (string.IsNullOrEmpty(_appPath)) { 74 appDirTextBox.Focus(); 75 return; 76 } 77 78 Start(); 79 } Now, the application will accept command line arguments in either form. I copy this cassini-v35.exe to C:\Program Files\Common Files\microsoft shared\DevServer\9.0 and rename it webdev.webserver.exe (making a backup of the old webdev.webserver.exe of course), and now I can launch my custom Cassini from Visual Studio.
Development
.net | visual studio | asp.net
|
|