If you tried to work with process templates for TFS in VS 2010 you probably noticed how slow it is. One of my colleagues tried this: http://www.edsquared.com/2010/09/20/Increase+Performance+When+Editing+TFS+2010+Build+Process+Templates.aspx
Here I will post problems I and my colleagues met and solutions we found.
Tuesday, January 11, 2011
Working with TFS process templates
Friday, November 26, 2010
Performance in WPF
Recently we struggled with the performance of our WPF application. Everything was slow. Changing size of the window - slow, maximizing - slow, refreshing - slow. Then I looked at CPU - it was using CPU in idle. Something definitely wasn't right.
And then I found WPF Performance Tool
Using this tool I found that we had animation running in the background. We used it to indicate that something is going on when we do asynchronous calls, and then we hided animated elements with visibility. Well, even being invisible, animation continued to use resources, and very noticeably
Monday, November 15, 2010
app.config file and MSI
There are so many examples in the internet demonstrating how to update your app.config file during installation. But these examples never tell you about consequences of this action. And there are some.
If you use installer from Visual Studio 2008 or 2010, you probably use RemovePreviousVersion property, by setting it to true. However, starting from 2008, the the implementation of this feature changed significantly, so significantly that it has nothing to do with the name of the property. Previous version is no longer uninstalled, and there some rules for updating old files with new ones. While "versioned" files handled straightforwardly, by replacing the file with newer version, content files are replaced only if they were not changed after previous installation.
Back to updating app.config files during installation. When you changing them during installation, you change them from those that were included in your .msi package. That means it will be ignored in the next update.
See this link. http://msdn.microsoft.com/en-us/library/aa370531.aspx
Wednesday, August 18, 2010
Images in Toolbar for Disabled buttons
I started to use ToolBar control in our WPF application. The problem is that when toolbar buttons have only images, these images are not grayed when button is disabled. The solution I googled (and little bit modified) is this:
<Style x:Key="{x:Static ToolBar.ButtonStyleKey}" TargetType="{x:Type Button}">
<!-- To support graying images when button is disabled-->
<Style.Resources>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
<Setter Property="Opacity" Value="0.30"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
<Setter Property="Margin" Value="3"/>
</Style>
Make sure this style is available in you resources.
Update:
When I tried to put images as content for the button I got an error "Specified element is already the logical child..."
So, my styles look like this:
<!-- Cannot use Content to display image to avoid "specified element is already the logical child" error -->
<Style x:Key="ToolButton_Edit" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="ToolTip" Value="Edit"/>
<!--<Setter Property="Content">
<Setter.Value>
<Viewbox>
<Image Source="pack://application:,,,/Actsoft.Styles;Component/ToolImages/icons-paper-edit.png"/>
</Viewbox>
</Setter.Value>
</Setter>-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Image Source="pack://application:,,,/Actsoft.Styles;Component/ToolImages/icons-paper-edit.png"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
One more update
OK, now I lost the "Mouse Over" effects. So, I copied existing Button Template, modified it with putting Image instead of ContentPresenter and "stole" Tag property for Image Source.
Here is what I got now, hope this is the last change.
<Style x:Key="{x:Static ToolBar.ButtonStyleKey}" TargetType="{x:Type Button}">
<!-- To support graying images when button is disabled-->
<Style.Resources>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
<Setter Property="Opacity" Value="0.30"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
<Setter Property="Margin" Value="3"/>
<!-- To support images -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" TargetName="Bd" Value="#FF3399FF"/>
<Setter Property="Background" TargetName="Bd" Value="#FFC2E0FF"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="BorderBrush" TargetName="Bd" Value="#FF3399FF"/>
<Setter Property="Background" TargetName="Bd" Value="#FFC2E0FF"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="BorderBrush" TargetName="Bd" Value="#FF3399FF"/>
<Setter Property="Background" TargetName="Bd" Value="#FF99CCFF"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- now buttons styles -->
<Style x:Key="ToolButton_Edit" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="ToolTip" Value="Edit"/>
<Setter Property="Tag" Value="pack://application:,,,/Actsoft.Styles;Component/ToolImages/icons-paper-edit.png"/>
</Style>
<Style x:Key="ToolButton_Save" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="ToolTip" Value="Save"/>
<Setter Property="Tag" Value="pack://application:,,,/Actsoft.Styles;Component/ToolImages/icon_save.png"/>
</Style>
Wednesday, June 30, 2010
TFS 2010 build machine workspace issues
When we converted from TFS 2008 to TFS 2010 everything seemed fine. But then I created new build definition and got this error:
The path XXX
OK, I talked to IT who made the setup and they told they changed Build agent Working directory to
$(BuildDirectory)\$(BuildDefinitionPath)\$(BuildDefintionId) (added BuildDefinitionId).
When we tried to reverse it back we got the same error message for old converted builds, the new one started to work. Going back and forward, trying to clear workspace with tf.exe command we couldn't resolve it. Either one or another build failed.
Finally, I asked him to change Wokring Directory to some completely new folder, suspecting that we had conflict with some old settings in workspaces that we could not clean. And it helped. So, we may still have some old settings somewhere, but changing working folder to new one we had clean start and it's working so far.
Tuesday, June 29, 2010
Reporting Services and Web farm
So, we switched to using Microsoft Reporting Services instead of Local reporting. However we had one issue with our configuration. We have our web site running in a farm with two servers with NLB implemented. Also, we have one server where we have our Reporting Services running. Since reports not that critical for our application, we decided just to have one server for that.
What we found though, is very often we got this message: ReportServerException: Execution 'uj2yx4bxgzfvwsvegkwuex45' cannot be found (rsExecutionNotFound)
While first googling suggested problems with timeout, I was pretty sure it's not the issue, and started to google specifically for this error and load balancing.
What we found out is that Reporting Services create some session to handle subsequent requests. Since we have cluster, those requests come from different servers. The problem though is that in our configuration requests came from different users, particulary
Our solution was simple, we configured our web site to run under dedicated user, the same for both instances.
Here are links that helped me:
http://social.technet.microsoft.com/Forums/en-US/sqlreportingservices/thread/1eb12568-bfea-4e4e-bd09-1f09b055c595
http://www.andypotts.com/Blog/2009/03/30/rsExecutionNotFoundWithReportViewerInALoadBalancedReportingServicesEnvironment.aspx
Tuesday, April 13, 2010
Simple way of editing enumerators using ComboBox in WPF
Here is the simple way of setting ComboBox for editing values of some enum type.
I would not use in application for production, since it's not localizable etc. But when I need to quicky write some testing application, it works perfect.
First, put this to your resource section:
<Window.Resources>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="keyName">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="a:enumType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Then, in your combobox use it like this:
<ComboBox ItemsSource="{Binding Source={StaticResource keyName}}" SelectedItem="{Binding propertyName}">
Friday, February 12, 2010
Get Reflector Pro Beta
If you google Reflector and the open cached version of the page, you can download Beta version of Reflector Pro that integrates with Visual Studio. I assume it will be released soon for money.
Monday, November 16, 2009
ReportViewer control from Microsoft
Recently we needed to add reporting capabilities to our web site. We had following requirements
- All standard requirements for report designs, they are pretty much the same everywhere.
- Ability to share report designs between web and desktop applications.
- Export to PDF and Excel.
- Royalty free.
We decided to try Microsoft Report Viewer control from VS 2008. And we started with web. Also, we have our "Data Access layer" which produces data as lists of objects, no direct access to the database. There is some logic involved in building these data both in database and in .NET.
You can find what report viewer control can and cannot do anywhere, what surprised me is the way it's done.
First of all, we didn't use Reporting Service, we used LocalReport.
- LocalReport uses a lot of memory. To give you an idea, we used set of data with about 50,000 records. It took about 16Mb of memory for the data and then it took about 200Mb to prepare report in PDF. It was much worse for Excel, 500Mb. We tried to add/remove sorting from rdlc template - 100Mb difference. This was exporting reports without using ReportViewer control itself.
- Then we tried to use ReportViewer web control. The problem here was that it uses about same amount of memory from sessions. OK, it doesn't make much sense to prepare such reports in "on-demand" mode. Still it took about 20Mb for 3000 records. This is just terrible
- Not only control uses session, it leaves objects in session when rendering is done and we clear the list of data sources.
- Export to Excel is supported for Office 2003, not 2007
- Not an issue, but everything is copied in two namespaces, WinForms and Web. Why not to reuse LocalReport?
So, what we are going to do next? First of all we are going to try to use Reporting Services. I expect it to be little bit tricky since we still don't want to use direct access to the database, but use our Data Access layer, but it seams doable. When using Reporting Services ReportViewer control supposed to be able to work without using session.
Second, we will break batch reports into multiple files. Having grouping and sorting in mind, this two will require some additional efforts.
I will report how this is going.
Wednesday, June 24, 2009
This element is not currently associated with any context
When debugging WCF you can see this exception. Some people advice to just disable stop on exception But it's useful feature.
The better is to go into details of this dialog and disable just this specific exception. The only small problem is that it's not in the list. But it's really a small problem. You can add it.
Just press "Add..." button, choose "Common Language Runtime Exceptions" from the drop down list and type the exception type, which is System.Configuration.ConfigurationErrorsException. Now you can disable stopping on just this exception and not all of them.
Friday, June 05, 2009
Getting output parameters when executing reader in ADO.NET
Interestingly, the values of output parameters are not available after ExcecuteReader() is called, even after all records were fetched.
To get these values it is required to either close reader (call reader.Close()) or at least call NextResult() method.
Wednesday, June 03, 2009
WCF - nullable values are not working in generics
Today I spent couple of hours figuring out why I suddenly got an error "Referenced type 'x`1, ... with data contract name 'xIF_Ph6aZR' in namespace 'x cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types."
It was working and what I did just little bit of re-factoring. What I found is that there is a combination of conditions that does not work, while every one of them works separately:
- Generic class is used as DataContract.
- This class has nullable DataMember property
- You want to reference your class in your client instead of creating in through wsdl.
[DataContract]and then you use it like this:
public class DummnyContract<T> where T: IBusinessObject
{
[DataMember]
public DateTime? LastModified{get;set;}
}
[ServiceContract]
public interface IService
{
[OperationContract]
DummyContract<int> Get(int id);
}
This just does not work when you reference your assembly with declaration of this class. You can have it without class being generic. Or, you can have generic without nullable property. But not together.
Saturday, May 02, 2009
WSE and Visual Studio 2008
If you got here from search engine you already know that WSE is integrated into Visual Studio 2005, but not 2008. You also know that if add reference to the web service that implements WSE you would get proper class in Visual Studio 2005 but not in 2008. The common advise is use VS 2005 to do the import, or use svcutil.exe.
The easiest solution though is just to open Reference.cs file and replace System.Web.Services.Protocols.SoapHttpClientProtocol with Microsoft.Web.Services3.WebServicesClientProtocol manually.
Also, here you can find how to make plug-in available in VS 2008 UI.
Friday, April 24, 2009
WCF under IIS access problems
Today I spent few hours trying to resolve problem with our WCF server for one of our clients. Somehow everything went wrong. Our configuration is WCF server that utilize .NET 3.5, and I set it up to work under IIS6.
The errors I got were different, but in result it was all about setting permissions for IIS. Many of them were trivial, but the last one I found tricky. HTTP result code was 500, internal server error, the error in EventViewer said: Could not load file or assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=xxx or one of its dependencies. Access denied.
Logically, something was wrong with access to \WINDOWS\Microsoft.NET\Framework\v2.0.0.527 folder. However, it was not so. What helped me was adding NT permissions to the folder with my WCF server to the group IIS_WPG. And this is after I tried to add permissions to user ASP_NET… and IUSR_… without success.
Wednesday, March 04, 2009
Fill WrapPanel from the list (WPF)
Sometime, when it is necessary to make a choice from the list, and the list is not that big, it makes sense to use buttons with some actions instead of lists. I found useful technique to do it when the list of actions is dynamic.
The idea is somehow populate WrapPanel with buttons dynamically. We can do it by replacing template for ItemsController.
I lave a collection of elements (it will be assigned to the ItemsSource property in runtime) with Key and Value properties.
<ItemsControl x:Name="activitiesControl" Margin="10">
<ItemsControl.Template>
<ControlTemplate>
<WrapPanel Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
FlowDirection="LeftToRight" IsItemsHost="true">
</WrapPanel>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{DynamicResource ActionButton}" HorizontalAlignment="Right" Margin="5"
Content="{Binding Value}" Width="200"
Command="{Binding Path=ViewModel.ActionTypeCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=local:CustomerEditView}}" CommandParameter="{Binding Key}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Note that I am using Commands. Finally, we have it. Not in Silverlight yet though.
Sunday, March 01, 2009
Application Architecture Guide 2.0
I am currently reading Application Architecture Guide 2.0 I wouldn't say that this is a revolutionary document, but I enjoy reading. I find it very aligned with the way I see the subject, and as it is often the case, it helps me organize my thoughts by putting everything into it's place.
One of the things I would recommend this paper for is it's not just theory or collection of "design patterns". With all my respect for the latter, many authors just abuse the term and sound very far from real world of day-to-day developers. Here I find some practical advices, key points that should not be missed when creating application architecture and common mistakes. There is also understanding of the real world by acknowledgment that development became "agile". And again, the term is not abused.
The volume is quite big, and there are many repetitions, so I just somewhere in the first quarter of the document. Hopefully the last three quarters will be as good as first one.
Binding to nullable values (WPF)
I don't usually use nullable types, since my approach is to use them only when there is real difference between zero and null values, and it's not often when such difference exists. However, sometimes you may not really know how the value is going to be used. And then having it nullable may be preferable.
That was the case in one of our custom projects. Naturally, you would want to display empty edit box for null value, which was defined as nullable integer. The problem is that by default binding would not handle empty string as null value. Fortunately, with .NET 3.5 SP1 there is a way. You should use TargetNullValue attribute. The binding would look like this then:
{Binding Path=Customer.ClientYear, TargetNullValue={x:Static sys:String.Empty}}
This, and other attributes for the binding collected in one document here
Tuesday, February 17, 2009
Flickering in WinForms
I used to know these things long time ago. But later, with .NET programming they faded in my memory and it took me more than an hour (I will not tell you how much more) of experimenting to discover it again.
When your screen is flickering, check if DoubleBuffered is on. It may help.
Sunday, February 15, 2009
Implementing netTcpBinding in WCF and security
Usually I post when I solve some problem. I didn't solve this one yet, but was almost there.
We decided to build n-tier application using CSLA. So, this is a desktop WPF application, we just host a server with business objects and desktop client access the server through Internet. I wanted to use WCF for communication. Also, I wanted to host it in my own windows service, not by IIS. Additionally, I wanted to use TCP binding, as it is supposedly faster, if I understand correctly, which is another reason to not use IIS.
It looked very simple, like all I had to do is to change binding to NetTcpBinding. And first, it worked fine until I tried to connect from my home computer, which wasn't member of our Windows domain. It looked that for some reason connection was terminated by the host. The error message did not give me any specifics. Using SvcTraceViewer.exe I identified the problem as related to the security.
Making the long story short, I found this blog post to be the best to help me with my problem. The last step of getting certificate value did not work for me, and the project is on hold now. I hope I will find the time to resolve everything.
Now, let me explain in few words what the problem is. All bindings with exceptions of BasicHttpBinding require some kind of security on the transport level. So, we have to create certificate and apply it somehow. We could register it in the Windows, but I didn't want to go this way.
Another problem is authentication. If I hosted service under IIS, that would provide some mechanism, but this is not what I wanted. To help with that I decided to use custom username authentication. And this is also covered very well in post I found.
Thursday, January 15, 2009
Smart Clients
About four years ago I heard about Smart Clients. Back then this term had particular meaning. Application can be considered Smart Client applications if
- It's a desktop application with rich user interface.
- As desktop application, it can work in disconnected mode.
- When connected, additional functionality may be available.
I still like all these ideas, and still think that the idea of smart client application is valid. But it worth to analyze what went wrong with them, and why web became so popular. Well, analysis may be a too strong word, just some thought.
One of the reasons, I believe, is that it's much easier to develop web application than occasionally connected desktop application. There are so many people involved in web development now, that the choice of technologies, frameworks and examples is huge. In result, there is a new generation of developers who never developed anything by web applications. And these process feeds itself, the more popular web development is, the easier it becomes.
Another reason is that desktop applications were not that good looking. Somehow web became more visually appealing. Why did it happen? For one thing, desktop application development stuck with Win32 windows. (I have to mention that my view are based on my experience, which is development for Windows OS). As much as I love .NET, all we had for user interface were WinForms, and this is just the wrapper around old Win32 windows, where presentation cannot be easily separated from development, by which I mean coding. It's different in Web. HTML, with it's styles, allowed to developers to develop, and designers to design. And these are different talents.
Finally, it appears that many applications just don't need neither rich UI nor ability to work being disconnected. There is just no benefits for them in that.
So, where do we go now? Is it time to bury the idea? After all, even the term Smart Client is deluded. Every desktop application can be named Smart Client today, and I even heard the term applied to a web application with Java applet as a client, that just cannot work disconnected at all. I would argue that we should not just write it off yet. Here is why.
Trends. Let's look at where web applications are going. Many of them remind desktop applications now. Not only very rich UI is available through JavaScript, Flash, or Silverlihgt, but because they are starting to store their data on a client machine. Just look at such things as Google Gears, or Isolated Storage in Silverlight, I am sure there are others.
WPF gives desktop developers what web developers had long time ago. Presentation is finally separated from implementation. Layout of application is not part of the code anymore. With tools like Expression Blend designer can do his job while developer does his. And the results can finally be better than what they are in Web. There are concerns here. After all, WPF is not exactly new already, and adaptation is not going really fast. I would suggest that one of the reason is that XAML is too complicated, another is there are no tools on the market that could much those available for web designers. Expression Blend is definitely not there yet. Hopefully, the latter is just the matter of time, and once those tools are available, the complexity of the XAML will be hidden from designers.
Bottom line, I am optimistic about Smart Client applications. The deployment can be simplified with technologies like ClickOnes, or similar. Automatic updates are already a must. Disconnected mode is not that critical now, but having local cache is easier to do with existing light weight databases. WPF will bring pretty look. Sure, there are so many applications that just belong to web, there are those that can be better with smart clients, particulary business applications (emails, data entry applications, any office application).