I've run across a strange situation where I have recently modified a WCF service and service contract adding new functionality. All I have done so far is stub in a new method with the appropriate updates to the service, the service contract, & the proxy (which is hand coded). When I try to run my existing unit tests, I am now getting the following error:
Class Initialization method <namespace>.<classname>_UnitTests.MyClassInitialize threw exception. System.MissingMethodException: System.MissingMethodException: Method not found: '<namespace>.<returntype> <namespace>.<contractinterface>.<methodname>()'.
<namespace><classname><namespace><returntype><namespace><contractinterface><methodname>
Ironically, the method does exist and if I run the unit test in debug mode, the exception does not occur. If I run all the tests in debug mode, they all pass without a problem (expected result)...but if I just run the tests without being in debug mode, they fail with the MissingMethodException. IF I run the tests in debug mode, get them to all pass, then run them without restarting visual studio and being in debug mode, they pass. This is obviously some kind of a caching issue.
As it turns out, the issue appeared to be related to the *.testrunconfig file. Initially, code coverage was enabled. I disabled code coverage then deleted the testrunconfig file. I then cleaned the solution, closed visual studio, re-opened visual studio, & rebuilt the solution. The unit tests then began passing
System.MissingMethodException while UnitTesting in VS 2008
Team System Web Access: Time Entry Host Custom Control
Previously, Michael Ruminer had created a Silverlight TFS TimeEntry control for use within Team Explorer. His project is hosted within the MSDN Code Gallery at: "http://code.msdn.microsoft.com/SilverlightWITimeEnt". His project creates everything needed for a rudimentary time tracking system within TFS. One of the remaining open issues was how to utilize the same Silverlight TimeEntry control through Team System Web Access (TSWA).
I have created a simple server side web control that will host Michael's TimeEntry control. When I first tried to tackle this issue, I had to learn about the Work Item Templates used by TSWA and what controls already existed. I found the existing controls to be quite limited. As a result, I opted to create my own custom web control. To my surprise, the code changes ended up being extremely simple. First, let me explain what is required to create a custom web control that can be used by a work item template in TSWA.
For TSWA to render a custom control, the control must:
1. Inherit from System.Web.UI.WebControls.WebControl
2. The control must have a default constructor
3. Implement Microsoft.TeamFoundation.WorkItemTracking.Controls.IWorkItemControl *
4. Implement Microsoft.TeamFoundation.WebAccess.WorkItemTracking.Controls.IWorkItemWebControl *
* Note: These two interfaces can both be found in: "C:\Program Files\Microsoft Visual Studio 2008 Team System Web Access\Web\bin\". My initial struggles with getting the control render related to the fact I failed to implement BOTH interfaces. Creating a custom windows control only requires the "IWorkItemControl" interface be implemented.
I had wanted to keep the control as simple as possible so all it does is render a simple HTML page with an IFrame. The IFrame source points to the silverlight control. At first, I tried to just render an IFrame on it's own. The control seemed to load and function properly, however, I was getting a javascript error indicating "this.m_buttonsTable.offsetLeft" was null. I found this somewhat confusing since I hadn't written any javascript and the error occured regardless of what the IFrame pointed to. I then realized the script was in a WebResource.axd file, therefore, it must have been generated by the .NET framework. I resolved the javascript issue by wrapping the IFrame in a fully valid HTML page. The control continued to work but without throwing any javascript errors.
Once the control has been built, you have to deploy it. Create a "wicc" file by the same name as the library. Copy both the wicc file and the dll to "C:\Program Files\Microsoft Visual Studio 2008 Team System Web Access\Web\App_Data\CustomControls\" on the server hosting TSWA (assuming you used the default install for TSWA). TSWA will look in the CustomControls folder by default when trying to resolve the assemblies. In my example, my library name was "TimeEntryHost" so my wicc file was titled "TimeEntryHost.wicc".
Its contents are:
- <?xml version="1.0"?>
- <CustomControl xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <Assembly>TimeEntryHost.dll</Assembly>
- <FullClassName>TFS.TimeEntryHost</FullClassName>
- </CustomControl>
The template itself renders the control in a tab. Here is the snippet showing how that should be:
- <Tab Label="Time Entry">
- <Control Type="TimeEntryHost" Label="" LabelPosition="Top" Dock="Left" />
- </Tab>
This control could be used to host any web page as well. I'm actually surprised that it wasn't one of the standard pre-built controls due to its simplicity. There is, however, a caveat to the whole thing IF you are rendering DIFFERENT custom controls in Team Explorer (windows) and TSWA (web). Simply put, the work item template has a layout tag. Well, the layout tag needs to be duplicated each with a target attribute. For windows, it should read and for TSWA it should read . I had found this useful tidbit on Shai Raiten's blog at http://blogs.microsoft.co.il/blogs/shair/archive/2008/10/22/how-to-manage-custom-controls-in-team-system-and-web-access.aspx.
The final issue I ran into was importing the template into TFS so it rendered in both Team Explorer and TSWA. If you use the "Process Editor" tool in Visual Studio, you will lose one of the layouts you created causing the control to only render in one of the environments. To get around this issue, import the template from the commmand line. I don't recall where I found that information otherwise I would give proper credit. The import command will look something like the one below:
witimport /f "C:\\Task.xml" /t http:// /p ""
Below is the source code to the control itself. I'm sure it is not the most efficient and there is definitely room to improve, but it simple working example of how you can host a Silverlight control in a Work Item Template.
- using System;
- using System.ComponentModel;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using Microsoft.TeamFoundation.WorkItemTracking.Controls;
- using Microsoft.TeamFoundation.WebAccess.WorkItemTracking.Controls;
- using Microsoft.TeamFoundation.WorkItemTracking.Client;
- namespace TfsImplementation {
- [Serializable]
- public class TimeEntryHost : WebControl, IWorkItemControl, IWorkItemWebControl {
- public TimeEntryHost() {
- SetDefaults();
- }
- private void SetDefaults() {
- this.Width = 843;
- this.Height = 493;
- }
- protected override void RenderContents(HtmlTextWriter output) {
- string iframeHtml = "<iframe src=\"{0}\" style=\"WIDTH: {1}; HEIGHT: {2};\"></iframe>";
- string urlPath = string.Format("http://TimeControl_TFS.Web/TimeControl_TFSTestPage.aspx?name={0}&wi={1}",
- Environment.UserName,
- _workItem.Id);
- output.Write("<html>");
- output.Write("<head>");
- output.Write("<title></title>");
- output.Write("</head>");
- output.Write("<body>");
- output.Write("<form id=\"form1\">");
- output.Write("<div>");
- output.Write(string.Format(iframeHtml, urlPath, Width, Height));
- output.Write("</div>");
- output.Write("</form>");
- output.Write("</body>");
- output.Write("</html>");
- }
- #region IWorkItemControl Members
- public event EventHandler AfterUpdateDatasource;
- public event EventHandler BeforeUpdateDatasource;
- public void Clear() {
- RenderContents(new HtmlTextWriter(new System.IO.StringWriter()));
- }
- public void FlushToDatasource() {
- RenderContents(new HtmlTextWriter(new System.IO.StringWriter()));
- }
- public void InvalidateDatasource() {
- RenderContents(new HtmlTextWriter(new System.IO.StringWriter()));
- }
- public void SetSite(IServiceProvider serviceProvider) {
- //throw new NotImplementedException();
- }
- public System.Collections.Specialized.StringDictionary Properties { get; set; }
- public bool ReadOnly { get; set; }
- public string WorkItemFieldName { get; set; }
- private WorkItem _workItem;
- public object WorkItemDatasource {
- get { return _workItem; }
- set { _workItem = value as WorkItem; }
- }
- #endregion
- #region IWorkItemWebControl Members
- public string ClientEditorObjectId { get; set; }
- public string ClientObjectId { get; private set; }
- public string ControlId { get; set; }
- public string Label { get; set; }
- public string ThemeUrl { get; set; }
- public string GetClientUpdateScript() {
- return string.Empty;
- }
- public void InitializeControl() {
- //throw new NotImplementedException();
- }
- #endregion
- }
- }
TFS / TSWA Custom Controls - "Unable to create workitem control 'ControlName'." - Part 2
As it turns out, I had missed one of the required interfaces. When creating the web control, it requires that it inherits from WebControl and implements IWorkItemControl & IWorkItemWebControl. My initial attempts were missing the IWorkItemWebControl implementation. Once I had that resolved, my control began rendering. Still have some bugs to work out but those should be relatively easy. Once I have the control complete, I will post it with a link to the actual silverlight control I am hosting!
TFS / TSWA Custom Controls - "Unable to create workitem control 'ControlName'."
I have been trying to create a fairly simple custom control to be used by the TFS Web Access application. At my day job, we use TFS extensively and are working towards a solution that allows us to use it exclusively too. One of the major drawbacks we are currently facing is the lack of a built in time entry control. Another colleague of mine has created a time entry control in Silverlight to facilitate use in the two environments. In Team Explorer, a simple browser control was added to a tab to house the Time Entry component. It works well though it still has some minor quirks. I have been assigned to port the same concept (preferably to use the same Silverlight control) to the web side.
The issue I have run into is that the Work Item Template does not have any controls to support Silverlight or any other web site redirection. My thought was to use an IFrame to embed the Silverlight right in but I am not aware of any way to use the existing controls to support it. My next thought was to create a very simple server side control that will just render an IFrame directed to the appropriate URL. The new control is working in test environments (dummy pages), however, when I try to integrate it into the Work Item Template, it fails every time.
I have received numerous errors simply indicating that the control can not be created. Using FUSLOGVW.exe, I began to dig into the issue. I've verified in some cases that the library, dependencies, and the .wicc file are all properly located and found. Still, the control can't be created. I've tried modifiying the wicc file, changing namespaces, and updating the web.config (restarting IIS after every change). Every attempt still fails but now I'm getting different errors.
In the wicc file for the assembly name, if I include the ".dll" at the end of the assembly name, it searches for "assembly.dll.dll" and/or "assembly.dll.exe". Obviously it will not find a file by either of those names. If I remove the ".dll" at the end of the assembly name, it searches for just the assembly name with no extension at all....which again, it will never find.
So the million dollar question is what is going on here? I'm sure it is something stupid that I am overlooking. These things usually turn out that way which only raises the frustrations, but I will figure it out and post my resolution when I do.
The Worst Job I've Had...
...was likely the best thing possible for my professional career. Though this may seem strange, let me explain the reasoning. I am currently one of the Senior Web Developers within my organization. This is a far cry from the Bachelors Degree in Management I originally graduated with.
I started as a self-taught programmer with my first job out of college. I began my career with a small medical software company (2 developers, < 10 employees total) writing low-level communication drivers and APIs (using Delphi, C, & SQL). Being such a small company, alot was demanded from me. I had to design, code, test (with some help), and deploy all of the code I wrote myself to the external customers whom I worked with daily. After 3 years and a greatly expanded set of responsibilities, I was feeling confident. I felt that I knew what I needed to make the next step in my career. With confidence brewing, I moved on to a much larger corporation in the middle of trying to attain Sarbanes-Oxley (SOX) compliance.
Needless to say, it was a drastic environmental change for me. I needed to learn to work more as a member of a team rather than being the whole team. I needed to learn new processes and how to formally document my analysis, development plans, and testing plans. The code base was over 100x bigger than anything I had ever worked with deep object inheritance (most of my prior experience had more of a functional form). My manager was new at the role and lacked the experience to recognize how much I struggled...or just didn't have the know how to help me adapt. I worked through it for one year before I moved on again.
In preparation for moving on, I recognized that Delphi was a dying language. I wanted to enter the .NET realm and pursue a Masters Degree in Software Engineering. Luck was in my favor and I actually went back to my former employer to work on a new project in .NET with the opportunity to work from home. I found the lackadaisical environment to be comforting having just left a place with significant turbulence. Not to mention, working from home was a great experience and it provided the flexibility I need to attend grad school.
Over the next 3 years, I worked towards a Masters in Software Engineering and always found myself reading technical books outside of the classroom. I have taken on the challenge of trying to learn best practices and keep up with new technologies while gaining deeper understanding of existing technologies. I had also discovered how informative podcasts can be (.NET Rocks, Hanselminutes, & ALT.NET to name a few). I recognized that reading the blogs of the industry gurus and my peers provided priceless information, examples, and viewpoints. I've become more of a proponent for open-source and have spent significant time looking at open-source code.
Since finishing my Masters, I have moved on to my current employer (which is again a large, highly structured organization). Our development team consists of about 50 employees and contractors. Here I have taken a strong interest in continuous integration, automated builds, and utilizing aspects of agile methodologies in my daily development practices. I am still always reading at least one technical book at a time (often 2 - 3) and follow numerous blogs on a daily basis. I try to be more aware of the things I do not know. I've come to believe that relentless education is the only way to be successful in the software development industry because of it's accellerated rate of growth. For anybody that thinks they know enough to carry them through to retirement, they better plan on retiring soon! Technology is simply changing too fast. If we don't pursue it, we will just be left behind with future prospects fading quickly.
So, back to the original statement. The worst job I've had was likely the best thing possible for my professional career. It was quite the humbling experience. I try to remain humble and am always eager to learn something new. I suggest that, you too, implement a relentless pursuit for continued education in the areas you find most interesting. Never consider yourself to THE expert. Be humble, yet confident. There is always something left to be learned no matter how good everything seems.
Too Many Stored Procedures
Like many others before me, the code base I am working on has been in existence for many years. It is massive in scope and in actual source code. Behind it all lies a massive database structure with a single common means of accessing all of the data from the application: stored procedures (sprocs). While this may seem like a good idea, there is a point where things get out of control. Our current system has about 2,000 tables and nearly 14,000 sprocs. The only logical grouping of the sprocs is found in the naming conventions used, though this proven itself inconsistent as well. To make matters worse, there is far too much business logic in many of the sprocs. Now, I understand that number of lines of code is not a very reliable metric, but some of the sprocs are in excess of 2,000 lines with many of the sprocs at least 300 - 500 lines long.
I recently did a trace through a stored procedure that didn't appear too bad on the surface (it was only 640 lines long). The trace revealed a disturbing revelation. The shortest path through that stored procedure involved calls to 4 additional sprocs. That is acceptable, but that is to determine that it has nothing to do. The shortest functional path through involves calls to over 80 additional sprocs...one of which calls itself recursively. Needless to say, it was a painful experience to trace through to figure out what it is actually doing (oh, I forgot to mention that our specs and documentation are virtually non-existent).
So this all brings me to my current point. There is a time when there are too many stored procedures and any benefit gained by them are lost through the loss in maintability. With the exorbitant number of sprocs, most of my co-workers (myself included) will take a short look to see if one already exists meeting our needs, but typically just take the easy road and write a new sproc further propagating the problem. I would like to spearhead an effort to bring some sort of control to this situation and to bring it back to a maintainable state. The million dollar question is simply "How?".
Starting my blog...
I've been putting off creating my own blog for about a year or so. I've had good intentions but I never seem to give myself the time to do so. So, why now? What makes today so different? Nothing really. I've just become fed up with how I'm utilizing my own time. Life is too short to not go after the things you want in life. My driving motive for this blog is to provide a place for me to document lessons learned (often the hard way), my thoughts on new technologies, and provide a running dialog of my professional growth. I also intend to use this blog as one of many means to help improve my knowledge on any topics discussed while improving my communication skills (hopefully). I tend to be over-ambitious but we will see how this chapter turns out. My goal is to post new messages every few days. I think that is a reasonable expectation but only time will tell.