tag:blogger.com,1999:blog-83914845390968633152024-03-07T19:55:34.891-08:00public Me : ITyson<b>GOAL</b>: Design great applications.<br><b>PURPOSE</b>: Build better businesses...- Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.comBlogger83125tag:blogger.com,1999:blog-8391484539096863315.post-42604854171394382902020-03-22T13:54:00.003-07:002020-03-22T14:04:32.190-07:00Self Hosting an Old ASMX Web Service<p>Sometimes you’re stuck taking old tech and merging it with new tech.  The other day at work, I found myself wanting to self host an old ASMX web service from an simple WinForms app to support a simple simulator.  I was able to find a great <a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2004/december/service-station-run-asmx-without-iis">post</a> from the co-founders of Pluralsight Aaron Skonnard, all be it an old post, fascinating none the less.  I would recommend reading Aaron Skonnard’s article for more detail, in this post I will paraphrase the example with a link to my example code.</p> <p><a href="http://tysonswing.info/downloads/programs/SelfHostedSoapService.zip">Download SelfHostedSoapService.zip</a></p> <p>The reason why self hosting works so well now goes way back to Windows 2003/XP SP2.  Microsoft had rewritten its protocol stack for HTTP handling, http.sys which is now at the kernel level.  It is important to note that this gave rise to the abstracting .NET applications from being tied to IIS.  This is what all of the cool ASP.NET MVC OWIN stuff is written on top of and allows us to write a “simple” self hosted web server.  .NET 2.0 came out with managed classes to make this possible</p> <ul> <li><a href="https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=netframework-4.8">HttpListener</a> – configures and starts an listener for HTTP requests</li> <li><a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.httpworkerrequest?view=netframework-4.8">HttpWorkerRequest</a>  - abstract class used by ASP.NET to process requests</li> <li><a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.hosting.simpleworkerrequest?view=netframework-4.8">SimpleWorkerRequest</a> – provides a simple implementation of HttpWorkerRequest to handle basic GET requests</li> <li><a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.hosting.applicationhost.createapplicationhost?view=netframework-4.8">ApplicationHost.CreateApplicationHost</a> – creates application domain for hosting ASP.NET (caveat is assemblies must be in the GAC or in the bin folder of relative to running process)</li> </ul> <p>I created 3 projects to hose a simple Calculator.asmx web service example:</p> <ul> <li>Library – contains the HTTP listener and worker class</li> <li>Console – starts the web server on a given port</li> <li>WinFrom – uses the ASMX web service to execute calculator methods</li> </ul> <p> </p> <p>Library contained 2 key classes.</p> <p><strong>HttpListenerWrapper.cs </strong></p> <hr /> <p>This will host the HttpListener class so that we can run our process on a separate thread.  The code for this is below.</p> <div id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4537f016-84dc-4275-9725-4fb8a8da5ddc" class="wlWriterEditableSmartContent" style="margin: 0px; padding: 0px; float: none; display: inline;"><pre style=white-space:normal>
[sourcecode language='csharp' padlinenumbers='true']
/// <summary>
/// A wrapper for the HttpListener so we can start and stop our listener.
/// </summary>
/// <seealso cref="System.MarshalByRefObject" />
public class HttpListenerWrapper : MarshalByRefObject
{
private HttpListener _listener;
private string _virtualDir;
private string _physicalDir;
public void Configure(string[] prefixes, string v, string p)
{
_virtualDir = v;
_physicalDir = p;
Console.WriteLine($"Configuring HTTP listener with virtual directory [{v}] and physical directory [{p}]");
// the HttpListener that will be used to extract request
_listener = new HttpListener();
// listener configuration for how http.sys will map incoming HTTP requests
// can use http://*:8081 or http://+:8081. for production use, wildcards should never be used
foreach (string prefix in prefixes)
_listener.Prefixes.Add(prefix);
}
public void Start()
{
_listener.Start();
}
public void Stop()
{
_listener.Stop();
}
public void ProcessRequest()
{
// receives the incoming request for processing
HttpListenerContext ctx = _listener.GetContext();
Console.WriteLine($"Request: {ctx.Request.RawUrl}");
;
// create our worker that will act as our web server and allow ASP.NET to process its pipeline
HttpListenerWorkerRequest workerRequest = new HttpListenerWorkerRequest(ctx, _virtualDir, _physicalDir);
// process the request
HttpRuntime.ProcessRequest(workerRequest);
}
}
[/sourcecode]
</pre>
</div>
<p><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shCore.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPlain.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushAS3.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushBash.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushColdFusion.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCpp.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCss.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushDelphi.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushErlang.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushFSharp.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushDiff.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushGroovy.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJScript.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJava.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJavaFX.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushMatlabKey.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushObjC.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPerl.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPhp.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPowerShell.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPython.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushRuby.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushScala.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushSql.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushVb.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushXml.js"></script><script type="text/javascript" src="http://s2.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCSharp.js"></script><script type="text/javascript" src="http://s1.wp.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushClojure.js"></script><script type="text/javascript" src="http://s0.wp.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushR.js"></script><script type='text/javascript'>
(function(){
var corecss = document.createElement('link');
var themecss = document.createElement('link');
var corecssurl = "http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shCore.css?m=1370811927g&ver=3.0.83c";
if ( corecss.setAttribute ) {
corecss.setAttribute( "rel", "stylesheet" );
corecss.setAttribute( "type", "text/css" );
corecss.setAttribute( "href", corecssurl );
} else {
corecss.rel = "stylesheet";
corecss.href = corecssurl;
}
document.getElementsByTagName("head")[0].insertBefore( corecss, document.getElementById("syntaxhighlighteranchor") );
var themecssurl = "http://s0.wp.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shThemeDefault.css?m=1363304414g&ver=3.0.83c";
if ( themecss.setAttribute ) {
themecss.setAttribute( "rel", "stylesheet" );
themecss.setAttribute( "type", "text/css" );
themecss.setAttribute( "href", themecssurl );
} else {
themecss.rel = "stylesheet";
themecss.href = themecssurl;
}
//document.getElementById("syntaxhighlighteranchor").appendChild(themecss);
document.getElementsByTagName("head")[0].insertBefore( themecss, document.getElementById("syntaxhighlighteranchor") );
})();
SyntaxHighlighter.config.strings.expandSource = '+ expand source';
SyntaxHighlighter.config.strings.help = '?';
SyntaxHighlighter.config.strings.alert = 'SyntaxHighlighter\n\n';
SyntaxHighlighter.config.strings.noBrush = 'Can\'t find brush for: ';
SyntaxHighlighter.config.strings.brushNotHtmlScript = 'Brush wasn\'t configured for html-script option: ';
SyntaxHighlighter.defaults['pad-line-numbers'] = false;
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all();
</script></p>
<p><strong>HttpListenerWorkerRequest.cs</strong></p>
<hr />
<p>This represents our web server that contains the methods needed to allow ASP.NET to process its pipeline.</p>
<div id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:c554a941-a136-4458-90e5-1fdd4b9eec64" class="wlWriterEditableSmartContent" style="margin: 0px; padding: 0px; float: none; display: inline;"><pre style=white-space:normal>
[sourcecode language='csharp' ]
/// <summary>
/// Represents our web server which sets up the processing for ASP.NET
/// </summary>
/// <seealso cref="System.Web.HttpWorkerRequest" />
public class HttpListenerWorkerRequest : HttpWorkerRequest
{
private HttpListenerContext _context;
private string _virtualDir;
private string _physicalDir;
public HttpListenerWorkerRequest(
HttpListenerContext context, string vdir, string pdir)
{
if (null == context)
throw new ArgumentNullException("context");
if (null == vdir || vdir.Equals(""))
throw new ArgumentException("vdir");
if (null == pdir || pdir.Equals(""))
throw new ArgumentException("pdir");
_context = context;
_virtualDir = vdir;
_physicalDir = pdir;
}
// required overrides (abstract)
public override void EndOfRequest()
{
_context.Response.OutputStream.Close();
_context.Response.Close();
//_context.Close();
}
public override void FlushResponse(bool finalFlush)
{
_context.Response.OutputStream.Flush();
}
public override string GetHttpVerbName()
{
return _context.Request.HttpMethod;
}
public override string GetHttpVersion()
{
return string.Format("HTTP/{0}.{1}",
_context.Request.ProtocolVersion.Major,
_context.Request.ProtocolVersion.Minor);
}
public override string GetLocalAddress()
{
return _context.Request.LocalEndPoint.Address.ToString();
}
public override int GetLocalPort()
{
return _context.Request.LocalEndPoint.Port;
}
public override string GetQueryString()
{
string queryString = "";
string rawUrl = _context.Request.RawUrl;
int index = rawUrl.IndexOf('?');
if (index != -1)
queryString = rawUrl.Substring(index + 1);
return queryString;
}
public override string GetRawUrl()
{
return _context.Request.RawUrl;
}
public override string GetRemoteAddress()
{
return _context.Request.RemoteEndPoint.Address.ToString();
}
public override int GetRemotePort()
{
return _context.Request.RemoteEndPoint.Port;
}
public override string GetUriPath()
{
return _context.Request.Url.LocalPath;
}
public override void SendKnownResponseHeader(int index, string value)
{
_context.Response.Headers[
HttpWorkerRequest.GetKnownResponseHeaderName(index)] = value;
}
public override void SendResponseFromMemory(byte[] data, int length)
{
_context.Response.OutputStream.Write(data, 0, length);
}
public override void SendStatus(int statusCode, string statusDescription)
{
_context.Response.StatusCode = statusCode;
_context.Response.StatusDescription = statusDescription;
}
public override void SendUnknownResponseHeader(string name, string value)
{
_context.Response.Headers[name] = value;
}
public override void SendResponseFromFile(
IntPtr handle, long offset, long length)
{ }
public override void SendResponseFromFile(
string filename, long offset, long length)
{ }
// additional overrides
public override void CloseConnection()
{
//_context.Close();
}
public override string GetAppPath()
{
return _virtualDir;
}
public override string GetAppPathTranslated()
{
return _physicalDir;
}
public override int ReadEntityBody(byte[] buffer, int size)
{
return _context.Request.InputStream.Read(buffer, 0, size);
}
public override string GetUnknownRequestHeader(string name)
{
return _context.Request.Headers[name];
}
public override string[][] GetUnknownRequestHeaders()
{
string[][] unknownRequestHeaders;
System.Collections.Specialized.NameValueCollection headers = _context.Request.Headers;
int count = headers.Count;
List<string[]> headerPairs = new List<string[]>(count);
for (int i = 0; i < count; i++)
{
string headerName = headers.GetKey(i);
if (GetKnownRequestHeaderIndex(headerName) == -1)
{
string headerValue = headers.Get(i);
headerPairs.Add(new string[] { headerName, headerValue });
}
}
unknownRequestHeaders = headerPairs.ToArray();
return unknownRequestHeaders;
}
public override string GetKnownRequestHeader(int index)
{
switch (index)
{
case HeaderUserAgent:
return _context.Request.UserAgent;
default:
return _context.Request.Headers[GetKnownRequestHeaderName(index)];
}
}
public override string GetServerVariable(string name)
{
// TODO: vet this list
switch (name)
{
case "HTTPS":
return _context.Request.IsSecureConnection ? "on" : "off";
case "HTTP_USER_AGENT":
return _context.Request.Headers["UserAgent"];
default:
return null;
}
}
public override string GetFilePath()
{
// TODO: this is a hack
string s = _context.Request.Url.LocalPath;
if (s.IndexOf(".aspx") != -1)
s = s.Substring(0, s.IndexOf(".aspx") + 5);
else if (s.IndexOf(".asmx") != -1)
s = s.Substring(0, s.IndexOf(".asmx") + 5);
return s;
}
public override string GetFilePathTranslated()
{
string s = GetFilePath();
s = s.Substring(_virtualDir.Length);
s = s.Replace('/', '\\');
return _physicalDir + s;
}
public override string GetPathInfo()
{
string s1 = GetFilePath();
string s2 = _context.Request.Url.LocalPath;
if (s1.Length == s2.Length)
return "";
else
return s2.Substring(s1.Length);
}
}
[/sourcecode]
</pre>
</div>
<hr />
<p>The Console application puts it all together.  It’s a big tricky due to the requirements of <a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.hosting.applicationhost.createapplicationhost?view=netframework-4.8">ApplicationHost.CreateApplicationHost</a>, so there are a few post build folder and copy setup needed to allow the ASMX to run correctly.  Namely</p>
<ol>
<li>You must copy our library into a bin folder under where the Console executable will run</li>
<li>You must copy the Calculator.asmx so it will be in the same folder as Console application executable</li>
<li>You must copy the Calculator.asmx.cs file into a App_Code folder under where the Console executable will run</li>
</ol>
<p>Here is the Program.cs of the Console application which fires up the HTTP listener to support the ASMX web service.</p>
<div id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:a58488f8-be8c-4c42-a62a-8138167cfa9e" class="wlWriterEditableSmartContent" style="margin: 0px; padding: 0px; float: none; display: inline;"><pre style=white-space:normal>
[sourcecode language='csharp' ]
class Program
{
static bool run = true;
static string port = ConfigurationManager.AppSettings["port"];
/// <summary>
/// Example 1: self hosted web serivce using System.Web.Hosting.ApplicationHost. Supports full web ASMX web serivce
/// </summary>
static void Main(string[] args)
{
// run our web server
ThreadPool.QueueUserWorkItem(RunListener);
// wait for user to tell us to stop
Console.ReadLine();
run = false;
}
static void RunListener(object state)
{
var currentDir = Directory.GetCurrentDirectory();
HttpListenerWrapper listener = (HttpListenerWrapper)ApplicationHost.CreateApplicationHost(typeof(HttpListenerWrapper), "/", currentDir);
listener.Configure(new[] { $"http://localhost:{port}/", $"http://127.0.0.1:{port}/" }, "/", currentDir);
listener.Start();
Console.WriteLine($"Listening for requests on http://localhost:{port}/");
while (run)
listener.ProcessRequest();
listener.Stop();
}
}
[/sourcecode]
</pre>
</div>
<hr />
<p>Building the Console application will yield the following output:</p>
<a href="https://drive.google.com/uc?id=1Nacey0zi9rYfuWdQbZr0jaCnokafF9uE"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1l-lgvNunty0ViGBwsdqfYeDHTwriDUlD" width="394" height="217" /></a>
<hr />
<p>Running the application will yield the following:</p>
<a href="https://drive.google.com/uc?id=18e-jB6KhAD3GSgVti-unc-M6DJPzxVSi"><img title="CalculateWebServiceConsole" style="display: inline; background-image: none;" border="0" alt="CalculateWebServiceConsole" src="https://drive.google.com/uc?id=1uzQs1SorWJPqtbz0faQo5DsYa9N5MKuS" width="397" height="196" /></a>
<hr />
<p>Opening a browser and navigating to http://localhost:8080/Calculator.asmx will respond with web services definition page</p>
<p><a href="https://drive.google.com/uc?id=16WzCas3Hynx8rUTw74pvTVEoW9vM4Au0"><img title="CalculateWebServicePage" style="display: inline; background-image: none;" border="0" alt="CalculateWebServicePage" src="https://drive.google.com/uc?id=1Y38iplSN8LB5EHXRN_9xMhJe48Hl6iUI" width="407" height="229" /></a></p>
<a href="https://drive.google.com/uc?id=1xxCPnDJki3zwrglJUzDLUD_aX3N0LAwo"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1Yb8eS-3yObArG8wKH-33lDvFJYjSRFWG" width="406" height="316" /></a>
<p><a href="https://drive.google.com/uc?id=1Y0dDiQxUymVHwXZiWmrxItaHbXwck35f"><img title="CalculateWebServiceAddMethodResult" style="display: inline; background-image: none;" border="0" alt="CalculateWebServiceAddMethodResult" src="https://drive.google.com/uc?id=1QXhdWIUm__vtf6AXJ4_gif1VzUfnVF2d" width="406" height="151" /></a></p>
<hr />
<p>The WinForm application used the WSDL from the web service to generate a proxy and call the simple functions on the Calculator.  There is not error handling in the app to keep it simple.</p>
<a href="https://drive.google.com/uc?id=1vqvFJnEfaphzjLyS90qR_3tQWlkwNEAy"><img title="CalculateWinFormApp" style="display: inline; background-image: none;" border="0" alt="CalculateWinFormApp" src="https://drive.google.com/uc?id=10NZiOcmB4P6R55Vn3tr6RvfwsA2vTGto" width="406" height="247" /></a>
<p> </p>
<p>And there you have it.  Self hosting a old school ASMX web service.  If you want to host a WCF web service this is a bit easier as there is plumbing out of the box in the System.ServiceModel library for this purpose.  See Microsoft post <a href="https://docs.microsoft.com/en-us/dotnet/framework/wcf/how-to-host-a-wcf-service-in-a-managed-application">here</a> and <a href="https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.servicehost?view=netframework-4.8">ServiceHost class</a>.</p>
<p><a href="http://tysonswing.info/downloads/programs/SelfHostedSoapService.zip">Download SelfHostedSoapService.zip</a></p>- Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com2tag:blogger.com,1999:blog-8391484539096863315.post-38457290307892245382015-04-30T11:28:00.001-07:002015-04-30T11:29:04.813-07:00Docker - A New Way To Think Virtual But Not Be Virtual<span id="goog_1597008161"></span><a href="https://www.blogger.com/"></a><span id="goog_1597008162"></span><span style="font-family: Arial, Helvetica, sans-serif;">At times you get the pleasure of working with some cutting edge technology that gives you the "wow that's pretty slick" feeling. Other times it can be a rocky unstable mess. <a href="http://www.docker.com/" target="_blank">Docker</a> is one such technology that has not been the later. The concept is simple, run this self contained little unit on bare metal as if it were a virtual machine. The analogy many liken this too is a shipping yard with lots of containers. The containers are the self contained packages and since all containers have the same shape the can be stacked and treated the same even though each container's internals can vary greatly. Hence, one of the reasons Docker calls these units containers.</span><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif;">I've had success setting this up on Windows and a Mac, both of which use a tool called boot2docker. Since Docker only runs on Linux systems, both Windows and Mac need to use Virtual Box to spin up a Linux machine that can host Docker. For Windows check out <span id="goog_1597008163"></span><span id="goog_1597008164"></span><a href="https://docs.docker.com/installation/windows/" target="_blank">https://docs.docker.com/installation/windows/</a> and for Mac see <a href="https://docs.docker.com/installation/mac/" target="_blank">https://docs.docker.com/installation/mac/</a>. I had a little trouble at first on Windows, which required deleting the VM on disk then re-initializing docker. After they are up and running, it's a breeze getting a container started, just type "docker run <i>container name</i>". It's that simple. Of course, if you want your container to expose ports and do other things there's a little more to it, but if you want to test out Linux based products, this is a very slick way to do it. To see a list of docker supported containers go to <a href="https://registry.hub.docker.com/" target="_blank">https://registry.hub.docker.com/</a>. <a href="http://www.pluralsight.com/" target="_blank">Pluralsight</a> also has some good modules on how to use docker.</span><br />
<br />
- Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-52327174711077831692015-02-18T10:35:00.001-08:002015-02-18T10:35:31.539-08:00Atlasian SourceTree : A Great Git Visual Tool<p><a href="http://git-scm.com/" target="_blank">Git</a> is source control system that has risen to new heights.  Even Team Foundation Server no exposes Git.  Many use the Git command line operations but I always prefer the visual tools for day to day work.  Atlasian, produces of Jira, Confluence, Stash, Bamboo, have a tool call SourceTree which is a excellent tool for managing Git.  You can download it for Windows or Mac here <a title="http://www.sourcetreeapp.com/" href="http://www.sourcetreeapp.com/">http://www.sourcetreeapp.com/</a>.</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-40364291433211227982015-02-18T09:55:00.001-08:002015-02-18T09:55:26.891-08:00Install Mongo On Windows As a Service<p>Mongo is a common NoSql database that is flexible and easy to use.  It’s ability to scale and shard across many nodes makes it a great option for load balancing and scaling an application domain that fits a NoSql type schema.</p> <p>1.  <a href="http://www.mongodb.org/downloads" target="_blank">Download</a> the latest version of Mongo that fits your platform (i.e. x86, x64).  Run the installer and place the application files in C:\Tools\MongoDB…  Follow my <a href="http://publicityson.blogspot.com/2015/02/setup-java-development-on-windows-git.html" target="_blank">environment variable setup</a> post for certain development folders.</p> <p>2. Create an environment variable MONGO_HOME to point to the root of the mongo application directory.  If you followed my post on environment variable setup this would be %TOOLS_HOME%\MongoDB…  Add <em>%MONGO_HOME%\bin</em> to the Path environment variable.</p> <p>3.  Create a directory to store the mongo data.  The simple approach is to create the directory C:\data\db.  This is Mongo’s default but can be changed using it’s configuration file.</p> <p>4.  Create a <em>log</em> directory for the Mongo logs.  The simplest is to create “log” directory under the root Mongo directory C:\Tools\Mongo….</p> <p>5.  Create a mongodb.conf file in C:\Tools\MongoDB… root directory.  This put the following minimum information in the file.</p> <pre class="csharpcode">systemLog:
destination: file
path: <span class="str">"/Tools/MongoDB 2.6 Standard/log/mongodb.log"</span>
net:
bindIp: 127.0.0.1
port: 27017
storage:
journal:
enabled: true
dbPath: <span class="str">"/data/db"</span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<p>6.  Open a command window (ensure it’s in Administrator mode) enter the following command.  This will work if your Path variable is set correctly.</p>
<pre class="csharpcode">mongodb.exe --config <span class="str">"C:\Tools\MongoDB 2.6 Standard\mongodb.conf"</span> --install</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-70806424554211525832015-02-18T09:24:00.001-08:002015-02-18T09:24:37.901-08:00Setup Java Development on Windows : Git, Tomcat, Maven, Java JDK<p>This is a Java development setup that is a continuation of a long ago post regarding Eclipse setup. In this post I exclude the IDE and include Git and Tomcat, two common elements in a Java developers toolbox now.</p> <h4>Create the following environment variables (similar to updating you .bashrc file).</h4> <li>HOME = {drive}:\Source </li> <li>SDKS_HOME = {drive}:\SDKs </li> <li>TOOLS_HOME = {drive}:\Tools </li> <h4>Download and extract or install msi/exe.</h4> <ol> <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/" target="_blank">Downloaded Java JDK</a>, the latest or the version of you choice. Make sure you get the correct one for you architecture (i.e. x86, x64,..).  When running the installer, place the JDK in <strong>%TOOLS_HOME%</strong>.  You will end up with something like C:\Tools\jdk_…</li> <li><a href="http://maven.apache.org/download.html">Download Maven</a> latest maven version and extract to <strong>%TOOLS_HOME%</strong>.  You will end up with something like C:\Tools\maven-3.2.5…</li> <li><a href="http://ant.apache.org/">Download Ant</a> latest ant version and extract to <strong>%TOOLS_HOME%.</strong>  You will end up with something like C:\Tools\ant…</li> <li><a href="http://git-scm.com/downloads" target="_blank">Download Git</a> installer for windows. Install complete with git bash.</li> <li><a href="http://tomcat.apache.org/" target="_blank">Download Apache Tomcat</a> version that you’d want and extract to <strong>%TOOLS_HOME%.</strong>  You will end up with something like C:\Tools\apache-tomcat-7.0.59-windows-x64…</li> </ol> <h4>Create the following environments variables</h4> <p>The root directory for these applications will be the directory where you will find the <em>bin</em> folder and other application specific folders.</p> <li>JAVA_HOME = %SDKS_HOME%\jdk_… to the root folder.</li> <li>MAVEN_HOME = %TOOLS_HOME%\maven-… to the root folder.</li> <li>ANT_HOME = %TOOLS_HOME%\ant-… to the root folder.</li> <li><strong>%</strong>CATALINA_HOME% = %TOOLS_HOME%\apache-tomcat-… to the root folder.</li> <h4>Append the following line to the system Path environment variable</h4> <p>Don’t forget a semicolon after each new entry.</p> <ul> <li>%JAVA_HOME%\bin</li> <li>%MAVEN_HOME%\bin</li> <li>%ANT_HOME%\bin</li> <li>%CATALINA_HOME%\bin</li> </ul> <p>At this point you will be able to open the git bash window and run the following.</p> <ul> <li>java -version</li> <li>git --version</li> <li>mvn –version</li> <li>ant -version</li> <li>For tomcat you will have to manually path over to tomcat bin and run “sh version”.  bash shell doesn’t convert c:\Tools\… correctly for this one.</li> </ul> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-2839949923642608662014-08-14T11:26:00.000-07:002014-08-14T11:27:19.831-07:00Getting Revision Number in TFS Team Build<p>If you’ve ever been wondering how to get the value of the $(Rev:r) (or $(Rev:rr)) value in you team build, you can’t.  If you have a pretty boilerplate versioning where you do Major.Minor.Release.Revision then using the $(Rev:r) is pretty handy.  A company I work for now uses Major.Minor.Patch.Revision.  Below is how I was able to extract the revision number during TFS build workflow time.</p> <p>1.  Our BuildNumberFormat is set close to the default:<strong><em> $(BuildDefinitionName)$(Rev:.r).</em></strong>  We can use this fact to extract the revision number.</p> <p>2.  Create a string variable that is scoped to Run On Agent called RevisionNumber.  Don’t use Version or something like that which has a class name in the TFS namespaces (i.e. Version is type being used as int).</p> <p><a href="http://lh6.ggpht.com/-iTMPZ9J4dxA/U-z_ga_galI/AAAAAAAAAaY/p3XYQYN1WIA/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh3.ggpht.com/-Ti28JPbBSP0/U-z_hSXRRqI/AAAAAAAAAag/NrNIVPnBfx4/image_thumb%25255B3%25255D.png?imgmax=800" width="603" height="114" /></a> </p> <p>3.  Near the top of the “Run On Agent” area of you build template, add a Assign task item from the toolbox.  I added mine to the sequence called Initialize Variables because it logically made sense here.</p> <ul> <li>Set To to be RevisionNumber</li> <li>Set Value to be the following expression</li> </ul> <pre class="csharpcode">Int32.Parse(BuildDetail.BuildNumber.Remove(0, BuildDetail.BuildNumber.IndexOf(<span class="str">"."</span>) + 1))</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<p>With this in place you can use the revision number to create any numbering based of this value.</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-70904530581888097362014-07-14T11:25:00.000-07:002014-07-14T15:33:52.003-07:00Quick Way To Create a MSI For You Web Projects Using Wix<p>I’ve know about <a href="http://wixtoolset.org/">Wix (Windows Install Xml) tool set</a> for quite some time but haven’t had much to do with it.  Wix is a great tool for working within the Windows environment.  It is a XML based way of defining how you want you MSI packaged.  It comes with Visual Studio template projects, and few very useful tools.</p> <p>Background of my problem to solve: My company has been using Web Site projects and Visual Studio Deployment/Setup projects for a very long time.  I know, all these project types are the bane of Visual Studio’s ease of use when it comes to projects.  Our requirement is to create MSI installers of our web services.</p> <p>I’ll be assuming you are using a web application project type, web site projects are deprecated after Visual Studio 2010. Below are some simple steps you can take to create a MSI out of your web application projects.</p> <p>NOTE: One thing about Wix that helps a lot, is consistent naming convention for items that are not auto-generated, for example, IIS virtual directory component IDs ending in “.VDir” or folder IDs ending in “Folder”.</p> <p><strong>1.</strong>  Install the latest Wix Toolset, <a href="http://wixtoolset.org/">http://wixtoolset.org/</a>.  To save yourself time, add the the Wix bin (something like <em>C:\Program Files (x86)\WiX Toolset v3.8\bin</em>) folder to your PATH environment variable so the tools can be accessed on the command line.</p> <p><strong>2.</strong>  Go to you web application.  Right click and select Publish.  You will be just publishing to a local folder so if you have other publishing profiles create a new one, call it LocalFolder or something like that.  The publishing properties should look like the following.</p> <p><a href="http://lh4.ggpht.com/-iny_7OP9tdU/U8RarLUjWmI/AAAAAAAAAYg/aDlHOVazZTs/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-cY1knSn6Lis/U8RasO8b4YI/AAAAAAAAAYo/_tqH-R9LOjM/image_thumb%25255B1%25255D.png?imgmax=800" width="399" height="333" /></a> </p> <p>3.  Create a Wix project in the same solution of the web application project.</p> <p>4.  Add the web application project as a reference in the Wix project as shown below.  Yes, Wix has build dependencies, it’s pretty cool!</p> <p><a href="http://lh5.ggpht.com/-9NjNqCAYdEs/U8RaspkOTOI/AAAAAAAAAYw/fP_i4BeYPDw/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh5.ggpht.com/-2FAQJ8j_Cjc/U8RatNIA9vI/AAAAAAAAAY4/k1DL9dB2LGc/image_thumb%25255B3%25255D.png?imgmax=800" width="291" height="132" /></a> </p> <p><strong>4.</strong>  Now we will create a component wix file, a file defining all of our project outputs we want in our MSI (i.e. dlls, asmx, etc.).  Below is the following line I’ve used to quickly generate a wix file, which usually doesn’t need much tweaking after it’s done.</p> <p><strong><em>heat dir "C:\Temp\HtngWebServices" -out "{PathToWhereYouWantYourWixFix}\Components.wxs" -gg -g1 -sreg -sfrag -var var.{ProjectName}.ProjectDir -dr WebServicesFolder -cg HtngWebServicesComponents</em></strong></p> <p><strong>dir</strong> = directory which you will pull files from to generate wxs file</p> <p><strong>out</strong> = the location you want to create the wxs file in, generally this will be your Wix project or a Wix setup library project.</p> <p><strong>var</strong> = variable to place in front of the file location of the file being referenced in wix, this will be apparent when I describe the how the Wix project references work below.</p> <p>dr = Directory reference to root directories, see <a href="http://wixtoolset.org/documentation/manual/v3/overview/heat.html">Wix documentation</a>.</p> <p>gg, g1, sreg, sfrag = see <a href="http://wixtoolset.org/documentation/manual/v3/overview/heat.html">Wix documentation</a>.</p> <p> 5.  Once the Components.wxs is generated (Compnonents.wxs is just a name I choose for simplicity of example), add it to the Wix project.  </p> <p>Opening the Components.wxs that was generated by “heat”, you’ll notice a line like “Source="<em>$(var.HtngWebServices.ProjectDir)</em>\Web.config".  The part I’ve italicized is a variable, see <a href="http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html">Using Project References and Variables</a>, is a project ref so when our dependent project builds all the files we need will be located by Wix, this is handy but may not fit everyone’s situation.</p> <p><a href="http://lh4.ggpht.com/-iwGAylgV_2c/U8Rathy5mHI/AAAAAAAAAZA/h92hN2rlTrA/s1600-h/image%25255B10%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-KVY2jkka99o/U8RauN4zlUI/AAAAAAAAAZI/M1PVSjTBI2w/image_thumb%25255B4%25255D.png?imgmax=800" width="228" height="99" /></a> </p> <p><strong>6.</strong>  In the Wix project, add the following Wix library references, which are found in C:\Program Files (x86)\WiX Toolset v3.8\bin\.</p> <p><a href="http://lh5.ggpht.com/-wZ5hHMjP8NE/U8RauyJR2mI/AAAAAAAAAZQ/UMFJ647Mmt8/s1600-h/image%25255B13%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh5.ggpht.com/-hDqqx-E41xg/U8Rav2qRefI/AAAAAAAAAZY/xUQfB6_4U7M/image_thumb%25255B5%25255D.png?imgmax=800" width="197" height="63" /></a> </p> <blockquote> <p>At the top of your Product.wxs file you will need to add the following XML namespaces.</p> <pre>     xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension"      xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"</pre>
</blockquote>
<p><strong>7.</strong>  Add a wix file (.wxs) to your Wix project called IISConfiguration.wxs.  This is where the IIS settings will go.</p>
<p><strong>8.</strong>  In the IISConfiguration file you will need to add <a href="http://wixtoolset.org/documentation/manual/v3/xsd/wix/directoryref.html">DirectoryRef</a> for virtual directories that you need.  See the <a href="http://wixtoolset.org/documentation/manual/v3/xsd/iis/">IIS documentation</a> for detail, below is what It looks like</p>
<p><a href="http://lh4.ggpht.com/-CP2TGQPMibo/U8RawVbKZXI/AAAAAAAAAZg/oGz-JyrBE1I/s1600-h/image%25255B18%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-EG7eBdXzCJw/U8RaxJFnsNI/AAAAAAAAAZo/PtwJ3mfLNL4/image_thumb%25255B8%25255D.png?imgmax=800" width="711" height="517" /></a> </p>
<p><strong>9.</strong>  You will need to add feature(s) to the Product.wxs file that was generated with the project.  Here we’ve used 2 features, see <a href="http://wixtoolset.org/documentation/manual/v3/xsd/wix/feature.html">Feature documentation</a>.  Each of the <a href="http://wixtoolset.org/documentation/manual/v3/xsd/wix/componentref.html">ComponentRef</a> under the IIS virtual directories section shown below will be linked to the next step, and the item circled in read represents the <a href="http://wixtoolset.org/documentation/manual/v3/xsd/wix/componentref.html">ComponentRef</a> of our web application project components and virtual director.</p>
<p><a href="http://lh3.ggpht.com/-vOxzkdJdWDs/U8RaxxZnSPI/AAAAAAAAAZw/_8xeuBd1CME/s1600-h/image%25255B22%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh5.ggpht.com/-1ihGqtYvJfQ/U8RaycWnnaI/AAAAAAAAAZ4/H-QfUxMHpxY/image_thumb%25255B10%25255D.png?imgmax=800" width="694" height="214" /></a> </p>
<p>10.  A few more fragments will need to be added to you Product.wxs file to complete the installation information that the MSI will need.  Below is a shot of these sections.</p>
<p>First Fragment – this is for IIS extension to know what web site your are targeting, see <a href="http://wixtoolset.org/documentation/manual/v3/xsd/iis/">IIS extensions</a>.</p>
<p>Second Fragment – the first directory structure is the “TARGETDIR” directory which are constants from MSI framework, <a href="http://msdn.microsoft.com/en-us/library/aa370905%28v=vs.85%29.aspx">see MSDN</a>, the rest is nesting for our installation location.  The other DirectoryRef towards the bottom is for permissions for IIS process to access the installed folders.</p>
<p><a href="http://lh6.ggpht.com/-pL96e6u9xNk/U8RazOnFRdI/AAAAAAAAAaA/aUiaC7UfRDQ/s1600-h/image%25255B32%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh3.ggpht.com/-tR8y4Ui1li0/U8RazlKYLnI/AAAAAAAAAaI/z_RIcUpy4Nw/image_thumb%25255B16%25255D.png?imgmax=800" width="709" height="439" /></a> </p>
<p></p>
<p> </p>
<p>To be honest the learning curve is a little steep for Wix at first but once you wrestle it down, you begin to be able to follow what is going on.  The best guide is their documentation <a title="http://wixtoolset.org/documentation/" href="http://wixtoolset.org/documentation/">http://wixtoolset.org/documentation/</a> and Google other examples of specific tasks you are trying to achieve.  This thread is a accumulation of such time spent Googling various specifics of “how-to”’. </p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-44502277916436276562014-07-03T11:57:00.000-07:002014-07-03T11:58:11.872-07:00Errors In TFS Build Definition With Different Version of Visual Studio Installed<p>As <a href="www.visualstudio.com">Visual Studio 2012 and 2013</a> came out, I installed them to try them out and get to know the enhancements and changes.  At work, we use Visual 2010 and <a href="http://msdn.microsoft.com/en-us/vstudio/ff637362.aspx">TFS</a> 2010.  Using the team build workflow is OK, it has it merits with visual layout and .NET code access when using activities like if statements.  The one downside that I ran across after install VS2013 was nearly the whole workflow build definition had errors now!</p> <p>It turns out that there are assembly reference issues between having VS2010 and VS2013 side by side.  Being a little dismayed, and not to mention ugly to look at, I ventured into what to do to fix it.</p> <p>1.  First, you have to manage your build definition in a project just like you would code.  Below is an example.  The project can be a simple class library with not code files, just build definitions.  I do this whenever I setup TFS.</p> <p><a href="http://lh4.ggpht.com/-0R8HA750Qjc/U7WnnqaglXI/AAAAAAAAAXo/lnTuWc2zET0/s1600-h/image%25255B2%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-if4iWdGgPes/U7WnpemRwfI/AAAAAAAAAXs/bf1GTHiQR2M/image_thumb.png?imgmax=800" width="244" height="112" /></a> </p> <p>2.  You need to add a reference to all the libraries being reference in the xaml code.  If you open your xaml by selecting View Code you can see all the references.  To add reference right click project references and navigate to the location of the correct TFS libraries, most of them are in <em>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\</em>, I just search for dll under <em>C:\Program Files (x86)\Microsoft Visual Studio 10.0</em>.</p> <p><a href="http://lh5.ggpht.com/-ZCt38B6AsKQ/U7Wnsr5NCyI/AAAAAAAAAX0/rl1RV6AUTT4/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh5.ggpht.com/-YCEwTsXidu4/U7WntySUbzI/AAAAAAAAAX8/iNwxWYnurto/image_thumb%25255B3%25255D.png?imgmax=800" width="757" height="64" /></a> </p> <p><a href="http://lh5.ggpht.com/-1QqLrw8G3dg/U7Wnu6LIeCI/AAAAAAAAAYE/pNqn8Uuc2cQ/s1600-h/image%25255B11%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh5.ggpht.com/-QWyWqSS1yHQ/U7WnwdM-IWI/AAAAAAAAAYM/TyJDWKcXIwY/image_thumb%25255B5%25255D.png?imgmax=800" width="423" height="259" /></a></p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-84832515920003758152014-07-03T10:44:00.001-07:002014-07-03T10:44:54.862-07:00What is a .winmd and how to use it in a desktop application<p>A .winmd is a file used by Windows 8 WinRT (Windows Run Time).  winmd stands for Windows Meta Data file which is the same format used by the .NET framework for the CLI (common language interface).  As such it can be viewed by .NET tools such as Reflector and the ildasm tool packaged with .NET.  You can find these files in various places but one command place is c:\Windows\System32\WinMetadata.</p> <p>These files are focused on Windows store apps but it doesn’t preclude you from using them in a traditional desktop app.  To do so you need to do the following to your desktop application in order to leverage functionality in these APIs.</p> <p>1.  Unload your application.  Edit the project file and add the tag near target version, “<TargetPlatformVersion>8.0</TargetPlatformVersion>”.</p> <p>2.  Reload your project.  You will need to add a reference to the following DLLs.</p> <p>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\<em><strong>WindowsBase.dll</strong></em></p> <p>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\<strong><em>System.Runtime.dll</em></strong></p> <p>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\<strong><em>System.Runtime.WindowsRuntime.dll</em></strong></p> <p>3.  Now you will be able to leverage functionality provided by the WinRT framework, such as camera, NFC, etc.</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com1tag:blogger.com,1999:blog-8391484539096863315.post-4918486659516576722014-05-22T16:26:00.001-07:002014-05-22T16:26:04.603-07:00Setting Up TFS Team Build To Use TFS Build Extensions<p>The other day I was reminded of how great <a href="http://tfsbuildextensions.codeplex.com/">TFS Build Extensions</a> really are.  I’ve used them in the past and currently use them and still have not tapped there fullest resources but find they are always there to do 99% of what I need done.  If you are using TFS and team build, these are a must.  In this post I’m going to do a quick run through on setting up build extension on your build machine as well as your local development environment.  A more detail version of what I summarize below is found in the <a href="http://tfsbuildextensions.codeplex.com/wikipage?title=How%20to%20integrate%20the%20extensions%20into%20a%20build%20template&referringTitle=Documentation">TFS Build Extensions Documentation</a>.</p> <p><strong><font size="4">1.</font></strong>  Download the TFS Build Extensions from <a href="http://tfsbuildextensions.codeplex.com/">http://tfsbuildextensions.codeplex.com/</a>.  Unzip content into <strong><em>C:\Tools\</em></strong>.</p> <p><strong><font size="4">2.</font></strong>  Follow the directions in <a href="http://tfsbuildextensions.codeplex.com/wikipage?title=How%20to%20integrate%20the%20extensions%20into%20a%20build%20template&referringTitle=Documentation">TFS Build Extensions Documentation</a> to check in these build extension into the {team project}\BuildProcessTemplates\Custom Assemblies.  This will be used by the build controller/build agent as well as you when you are working on the build workflow and need toolbox items.</p> <p>Below is an example of a team project with the Custom Assemblies folder under BuildProcessTemplates and a ProcessTemplates.sln which has 1 project to house our build definitions.</p> <p><a href="http://lh5.ggpht.com/-TfnWgpy3KW0/U36HfSQVz2I/AAAAAAAAAW8/YfClKUfDVWE/s1600-h/image%25255B19%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh3.ggpht.com/-cv72vz7kp6A/U36HgkTyviI/AAAAAAAAAXE/omGTeam_qPg/image_thumb%25255B9%25255D.png?imgmax=800" width="481" height="421" /></a> </p> <p><strong><font size="4">3.</font></strong>  After following the setup steps <a href="http://tfsbuildextensions.codeplex.com/wikipage?title=How%20to%20integrate%20the%20extensions%20into%20a%20build%20template&referringTitle=Documentation">TFS Build Extensions Documentation</a> you will be able to create a workspace to your build templates folder, get latest, and open the build template project the documentation had you create.  The key to being able to work on the template on your development machine is to include the TFS extension in your toolbox.  Following the documentation will have you setup for this so your development will look like the following.  In the toolbox I added the items from the library TfsBuildExtensions.Activities.dll, which should be in your {team project}\BuildProcessTemplates\Custom Assemblies\ folder.</p> <p><a href="http://lh5.ggpht.com/-dWV3nXmF-EE/U36Hhu5YVAI/AAAAAAAAAXM/QBDUnYk2cfo/s1600-h/image%25255B24%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/--vjTcun7kwc/U36HiiNn_XI/AAAAAAAAAXU/3jGEA4Ra8OA/image_thumb%25255B12%25255D.png?imgmax=800" width="705" height="504" /></a></p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-55726057300646496512014-05-04T12:14:00.001-07:002014-05-04T12:14:49.210-07:00Using WPF and Vector Graphics<p>Recently I’ve been taking a look at WPF, Microsoft’s not so new now replacement for WinForms.  With the little free time that I have, I’ve relied heavily on Pluralsight for getting up to speed on various technologies.  In working with WPF, I was trying to leverage their concept of “lookless” controls which is very powerful and much nicer to design with than WinForms.  </p> <p>To summarize my tribulations, I was having a hard time loading a local resource that was a SVG.  Blend Expression, a WPF designer, doesn’t support SVG directly but it does support .pdf (a form of SVG) and .ai (Adobe Illustration).  There are a couple of ways to product .pdf or .ai files.  My approach was to use a tool I’ve used in the past, Inkscape, see <a href="http://publicityson.blogspot.com/2011/12/inkscape-cool-vector-graphics-tool.html">Inkscape A Cool Tool</a>.  Inkscape also support generating a XAML file directly from the SVG file which you can leverage directory or copy the contents of XAML output into a resource dictionary.</p> <p>1.  Open or create your SVG file in Inkscape.</p> <p>2.  PDF format: Select Save As and choose .pdf format.  It will display a dialog as below once you click Save, ensure you select “Convert texts to paths”, then click OK.  Once the file is saved you can rename the file extension from .pdf to .ai.  It will now be recognized in Expression Blend.</p> <p><a href="http://lh4.ggpht.com/-mgo7gdk6Wr4/U2aRpAGFyUI/AAAAAAAAAWk/YoEFneJEvLM/s1600-h/image%25255B2%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-fUwgm_0gi1Y/U2aRpsVnwfI/AAAAAAAAAWs/ZbTF8Mr9Vks/image_thumb.png?imgmax=800" width="244" height="198" /></a></p> <p> </p> <p>3.  XAML format:  Select Save As and choose .xaml format.  This will export it directly to a XAML file.  You can take the content line, element is a ViewBox, and put that directory in a resource file.</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-29857841979443947652014-04-28T13:49:00.000-07:002014-04-28T13:50:03.926-07:00Outlook 2013 Always Prompts for Credentials using Active Directory<p> You ever have those technical issues that aren’t quit annoying enough to deal with in your normal day of busyness?  I really have enjoyed where Microsoft have taken Office in the last few years, but after installing Office 2013 Professional, which has Outlook 2013, I kept receiving a login prompt for my Active Directory credentials every time I open Outlook.  For a while, I thought it was something to do with our IT’s exchange server, but did a little googling to figure it out.  </p> <p>It turns out that if you have Exchange connected through HTTP, it will always prompt, even if you ask it to remember you credentials, or even tell it not to prompt!  How annoying.  Below is the image of the setting you need to uncheck to fix this pest of an issue.</p> <p><a href="http://lh3.ggpht.com/-4E2U0QUR_NI/U16-9xXV_1I/AAAAAAAAAWM/PKT1oVt-AFw/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-2P2JqUeAE3U/U16--s__o8I/AAAAAAAAAWU/ewaZoHZ7F6g/image_thumb%25255B1%25255D.png?imgmax=800" width="283" height="351" /></a></p> <p>You can get to this screen by going to: Account Settings, double click the mail account in question, click the More Settings… button, then click the Connection tab. </p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com1tag:blogger.com,1999:blog-8391484539096863315.post-3263642035466542152014-04-09T17:05:00.001-07:002014-04-09T17:05:47.793-07:00Sass CSS with Compass using Grunt Not Working on Windows<p>My team is using AngularJS, Node.js, Grunt, Sass CSS via Compass, Yoeman, and a few other web toolsets.  The other day when running the serve process to generate the css output from Sass CSS, the css wasn’t able to generate.  It turned out that Compass was setting the permissions on the .tmp folder where it puts the CSS to a state that didn’t all the process to write the file, hence a Permission Denied error.  To fix this issue I followed the StackOverflow thread <a title="http://stackoverflow.com/questions/22596760/yeoman-error-errnoeacces-on-line-897-of-c-permission-denied" href="http://stackoverflow.com/questions/22596760/yeoman-error-errnoeacces-on-line-897-of-c-permission-denied">http://stackoverflow.com/questions/22596760/yeoman-error-errnoeacces-on-line-897-of-c-permission-denied</a> which did these steps.</p> <p>Open a command prompt and run the following.</p> <ol> <li>gem uninstall sass (if you have multiple version, select all)</li> <li>gem uninstall compass</li> <li>gem install compass --pre</li> <li>gem install sass --pre</li> </ol> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-82999033831295308312014-03-09T08:56:00.000-07:002014-03-09T09:19:00.355-07:00Setting Up PhoneGap/Cordova for Visual Studio<p>It’s always a struggle to find time to invest in side projects when you work and play an active role in your kids lives.  I appreciate when installing tools is just simple and you don’t have to google “why doesn’t …. do …” or “where is…” because the instructions aren’t straight forward or are missing steps/pieces.  I found this the case with the latest phonegap instructions as of 2014-3-9.</p> <ol> <li>Install Windows SDK.  I’m using Windows 7.1 because I have a Win7 machine, I found SDK <a href="http://www.microsoft.com/en-us/download/details.aspx?id=27570">here</a>.  This installed Visual Studio 2010 Express for Windows Phone (VS2010). </li> <li>Download PhoneGap SDK and unzip in C:\Tools.  PhoneGap SDK is on github <a href="https://github.com/phonegap/phonegap">here</a>. </li> <li>In the C:\Tools\phonegap-master (you might have to drill down a bit) there will be a <strong>lib</strong> folder, and in it there are folders for the different target frameworks one of which is “windows-phone”.  As of recent the Visual Studio template .zip is not there.  I had to run a batch filed called “createTemplates.bat” which created templates for WP8 and WP7. </li> <li>Once you have the Visual Studio .zip file template(s), copy those to your <strong>\Documents\Visual Studio 2010\Templates\ProjectTemplates\Visual C#</strong>. </li> <li>Open VS2010 and create a new project.  You will now see a project template as shown below.  The template name may change at some point. </li> </ol> <p><a href="http://lh6.ggpht.com/-y81pxzPjnpw/UxyQ90NibKI/AAAAAAAAAVg/pTnQPMMZjrc/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-GUVRuBTWB1k/UxyQ-XfytzI/AAAAAAAAAVo/FLYSz9kWUfA/image_thumb%25255B1%25255D.png?imgmax=800" width="450" height="194" /></a></p> <p> </p> <p>The project structure will look like the following.</p> <ul> <li>cordova – build tools</li> <li>cordovalib – code for browser engine interaction</li> <li>www – folder for html/js/css of your app</li> <li>plugins – plugins for interfaces on your phone (i.e. camera, contacts)</li> </ul> <p><a href="http://lh5.ggpht.com/-jvfAbFgBYzo/UxyUcRknVFI/AAAAAAAAAV0/xk16yNVmOyo/s1600-h/image%25255B4%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-MsT8Zs8EgFs/UxyUcgHh7DI/AAAAAAAAAV8/xab1qyUu9dM/image_thumb%25255B1%25255D.png?imgmax=800" width="210" height="261" /></a></p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-70423141580470413972014-01-10T17:12:00.000-08:002014-01-10T17:13:43.872-08:00Installing Node.js and Other Packages<p>Keeping up with technology can be a job in itself.  Learning is fun, but is quickly forgotten so writing things down can always save you time later.  This thread goes over various was of installing Node.js and other packages.</p> <p><strong><u>Installing Node.js</u></strong></p> <p>There are 2 ways in which you can install Node.js.  Node.js comes with node package manager now so it will not need to be installed independently.</p> <p><strong>Installer</strong> (recommended): Go to node.js.org and use the installer for your OS.  Run the installer.</p> <p>Homebrew (Mac only): Run the command “brew install node”.  You will have to have <a href="http://brew.sh/">homebrew</a> installed.</p> <p> </p> <p><strong><u>Other Node packages</u></strong> t</p> <p>Installation will use node package manager.  You can list the node modules for your node application by listing the directory of “node_modules”.</p> <p><strong>Express –</strong> web application framework for node</p> <blockquote> <p>npm install -g express --save</p> <p>NOTE: once you create a application with express (i.e. express AppName) you will have to navigate to AppName folder and run the command “npm install” to install the components defined in node’s package.json.</p> </blockquote> <p><a href="http://yeoman.io/">Yeoman</a> – front end tool focused on scaffolding (yo), building/testing (grunt), and dependency management (bower)</p> <blockquote> <p>npm install -g yo --save</p> <p>npm install -g generator-webapp --save</p> </blockquote> <p><a href="http://coffeescript.org/">coffee-script</a> – scripting language that builds down to javascript.</p> <blockquote> <p>npm install coffe-script --save</p> </blockquote> <p><a href="https://github.com/fgnass/node-dev">node-dev</a> – a tool for node that will monitory files and auto restart the node app when a file has changed.</p> <blockquote> <p>npm install node-dev –save</p> <p>NOTE: When using this you will want to separate development dependencies from production ones.  In the package.json, you can create a “devDependencies” like so:</p> <div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">{<br /> <span style="color: #006080">"name"</span>: <span style="color: #006080">"application-name"</span>,<br /> ...,<br /> <span style="color: #006080">"dependencies"</span>: {<br /> <span style="color: #006080">"express"</span>: <span style="color: #006080">"2.5.8"</span>,...<br /> },<br /> <span style="color: #006080">"devDependencies"</span>: {<br /> <span style="color: #006080">"node-dev"</span>: <span style="color: #006080">"~0.2.2"</span><br /> }<br />}</pre>
<br /></div>
</blockquote>
<p><a href="http://visionmedia.github.io/mocha/">mocha</a> – javascript test framework for node</p>
<blockquote>
<p>npm install mocha –save</p>
<p>NOTE: put this in your dev dependencies</p>
<p>REQUIRES: request</p>
</blockquote>
<p><a href="https://github.com/mikeal/request">request</a> – modeule that simplifies the process of making http calls</p>
<blockquote>
<p>npm install requets --save</p>
</blockquote>
<p>Redis – open source advanced key-value store</p>
<blockquote>
<p>npm install redis hiredis connect-redis --save</p>
<p>REQUIRES: Installation of Redis backend.  On a Mac use homebew “brew install redis”, Windows see <a href="http://redis.io/">redis.io</a>.</p>
</blockquote>
<p><a href="https://github.com/adunkman/connect-assets">connect-assets</a> – transparent file compilation and dependency management for Node’s connect framework</p>
<blockquote>
<p>npm install connect-assets --save</p>
</blockquote>
<p><a href="http://socket.io/">socket-io</a> – simplifies the use of IO on all browsers.  See <a href="http://en.wikipedia.org/wiki/WebSocket">WebSockets</a> for information on this topic. </p>
<blockquote>
<p>npm install socket-io --save</p>
</blockquote>
<p><a href="http://angularjs.org/">AngularJS</a> – front end web application framework dealing with models, views, collections, and events</p>
<blockquote>
<p>npm install angular --save</p>
</blockquote>
<p><a href="http://backbonejs.org/">Backbone</a> – front end structured for web applications dealing with models, views, collections, and events</p>
<blockquote>
<p>npm install backbone --save</p>
<p>RELATED: <a href="http://marionettejs.com/">Marionettejs</a> (npm install backbone.marionette --save)</p></blockquote> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-39844429513873223332013-11-07T08:41:00.001-08:002013-11-07T08:41:43.233-08:00ASP.NET Debugging in Visual Studio 2013 IIS Express Not Continuing<p>Looking at <a href="http://www.microsoft.com/visualstudio/eng/downloads#d-2013-editions">VS2013</a>, I’m impressed with it’s speed over VS2012 not to mention that Microsoft appears to be releasing more often and taking into consideration a lot of community feedback.   Other than the quickly visible improvements, I noticed that the virtual web server would stop working when debugging was stopped in Visual Studio. To fix this open you ASP.NET project properties and uncheck “Enable Edit and Continue”.  Once this is unchecked IIS Express will run after debugging has stopped.</p> <p><a href="http://lh6.ggpht.com/-W7yS0CPDfTg/UnvCwSPxZwI/AAAAAAAAAVE/VjxvXjtiigU/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh3.ggpht.com/-09lUrccXJ-I/UnvCxIO_P6I/AAAAAAAAAVM/kjeLia4qens/image_thumb%25255B1%25255D.png?imgmax=800" width="488" height="284" /></a></p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-13611881416271461532013-02-26T11:48:00.000-08:002013-02-26T14:32:12.876-08:00Mocking ASP.NET MVC HttpConext and Sessions<p>Unit testing ASP.NET MVC controllers can be difficult when you start to use the HttpContext and Session state.  The following snippet of code will allow you to mock, using the Moq framework, the HttpContext properties.  Add this to your test project.</p> <div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">using</span> System.Collections.Generic;<br /><span style="color: #0000ff">using</span> System.Web;<br /><span style="color: #0000ff">using</span> Moq;<br /><span style="color: #0000ff">using</span> System.Collections.Specialized;<br /><span style="color: #0000ff">using</span> System.Web.Routing;<br /><span style="color: #0000ff">using</span> System.Web.Mvc;<br /><br /><span style="color: #0000ff">namespace</span> WebBackOffice.Tests<br />{<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ContextMocks<br /> {<br /> <span style="color: #0000ff">public</span> Mock<HttpContextBase> HttpContext { get; <span style="color: #0000ff">private</span> set; }<br /> <span style="color: #0000ff">public</span> Mock<HttpRequestBase> Request { get; <span style="color: #0000ff">private</span> set; }<br /> <span style="color: #0000ff">public</span> Mock<HttpResponseBase> Response { get; <span style="color: #0000ff">private</span> set; }<br /> <span style="color: #0000ff">public</span> RouteData RouteData { get; <span style="color: #0000ff">private</span> set; }<br /><br /> <span style="color: #008000">/// <summary></span><br /> <span style="color: #008000">/// Initializes a new instance of the <see cref="ContextMocks"/> class.</span><br /> <span style="color: #008000">/// </summary></span><br /> <span style="color: #008000">/// <param name="controller">The controller to add mock context to.</param></span><br /> <span style="color: #0000ff">public</span> ContextMocks(Controller controller)<br /> {<br /> <span style="color: #008000">// define all the common context objects, plus relationsips between them</span><br /> HttpContext = <span style="color: #0000ff">new</span> Mock<HttpContextBase>();<br /> Request = <span style="color: #0000ff">new</span> Mock<HttpRequestBase>();<br /> Response = <span style="color: #0000ff">new</span> Mock<HttpResponseBase>();<br /> RouteData = <span style="color: #0000ff">new</span> RouteData();<br /><br /> HttpContext.Setup(m => m.Request).Returns(Request.Object);<br /> HttpContext.Setup(m => m.Response).Returns(Response.Object);<br /> HttpContext.Setup(m => m.Session).Returns(<span style="color: #0000ff">new</span> FakeSessionState());<br /><br /> Request.Setup(m => m.Cookies).Returns(<span style="color: #0000ff">new</span> HttpCookieCollection());<br /> Request.Setup(m => m.QueryString).Returns(<span style="color: #0000ff">new</span> NameValueCollection());<br /> Request.Setup(m => m.Form).Returns(<span style="color: #0000ff">new</span> NameValueCollection());<br /><br /> Response.Setup(m => m.Cookies).Returns(<span style="color: #0000ff">new</span> HttpCookieCollection());<br /><br /> <span style="color: #008000">// apply the mock context to the supplied controller instance</span><br /> RequestContext rc = <span style="color: #0000ff">new</span> RequestContext(HttpContext.Object, <span style="color: #0000ff">new</span> RouteData());<br /> controller.ControllerContext = <span style="color: #0000ff">new</span> ControllerContext(rc, controller);<br /> }<br /><br /> <span style="color: #008000">/// <summary></span><br /> <span style="color: #008000">/// Sets the ajax request header so that mocked HttpRequest shows as a ajax call.</span><br /> <span style="color: #008000">/// </summary></span><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SetAjaxRequestHeader()<br /> {<br /> Request.Setup(f => f[<span style="color: #006080">"X-Requested-With"</span>])<br /> .Returns(<span style="color: #006080">"XMLHttpRequest"</span>);<br /> }<br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">class</span> FakeSessionState : HttpSessionStateBase<br /> {<br /> Dictionary<<span style="color: #0000ff">string</span>, <span style="color: #0000ff">object</span>> _items = <span style="color: #0000ff">new</span> Dictionary<<span style="color: #0000ff">string</span>, <span style="color: #0000ff">object</span>>();<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">object</span> <span style="color: #0000ff">this</span>[<span style="color: #0000ff">string</span> name]<br /> {<br /> get<br /> {<br /> <span style="color: #0000ff">return</span> _items.ContainsKey(name) ? _items[name] : <span style="color: #0000ff">null</span>;<br /> }<br /> set<br /> {<br /> _items[name] = <span style="color: #0000ff">value</span>;<br /> }<br /> }<br /> }<br /> }<br />}<br /></pre>
<br /></div>
<p>Below is an example of using this in a unit test, based on nunit test framework.  During the setup, create the ContextMock and associated with the controller under test.</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">namespace</span> MySite.Tests<br />{<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> AccountControllerTests<br /> {<br /> <span style="color: #0000ff">private</span> MyAccountController myAccountController;<br /> <span style="color: #0000ff">private</span> ContextMocks contextMock;<br /> <span style="color: #0000ff">private</span> Mock<IAccountService> accountServiceMock;<br /><br /> [SetUp]<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Setup()<br /> {<br /> <span style="color: #008000">// create new controller under test</span><br /> myAccountController = <span style="color: #0000ff">new</span> MyAccountController();<br /><br /> <span style="color: #008000">// create mock HttpContext</span><br /> contextMock = <span style="color: #0000ff">new</span> ContextMocks(myAccountController);<br /><br /> accountServiceMock = <span style="color: #0000ff">new</span> Mock<IAccountService>();<br /> myAccountController.AccountService = accountServiceMock.Object;<br /> }<br /><br /> [TearDown]<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Cleanup()<br /> {<br /> myAccountController = <span style="color: #0000ff">null</span>;<br /> contextMock = <span style="color: #0000ff">null</span>;<br /> accountServiceMock = <span style="color: #0000ff">null</span>;<br /> }<br /><br /> [Test]<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SignUp_AjaxRequest_Returns_JsonResult()<br /> {<br /> <span style="color: #008000">// arrange</span><br /> <span style="color: #0000ff">string</span> email = <span style="color: #006080">"test@test.com"</span>;<br /> <span style="color: #0000ff">string</span> password = <span style="color: #006080">"Some#rei!23"</span>;<br /><br /> <span style="color: #008000">// configure ajax mock request</span><br /> contextMock.SetAjaxRequestHeader();<br /><br /> accountServiceMock.Setup(f => f.CreateAccount(It.IsAny<<span style="color: #0000ff">string</span>>(), It.IsAny<<span style="color: #0000ff">string</span>>()))<br /> .Returns(<span style="color: #0000ff">new</span> SignUpResponse(SignUpResponse.ReturnCodeType.Success));<br /><br /> <span style="color: #008000">// act</span><br /> ActionResult actual = myAccountController.SignUp(email, password);<br /><br /> <span style="color: #008000">// assert</span><br /> Assert.IsInstanceOf<JsonResult>(actual);<br /> }<br /> }<br />}</pre>
<br /></div> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com1tag:blogger.com,1999:blog-8391484539096863315.post-75039366543696438092012-11-26T14:49:00.001-08:002012-11-26T14:49:56.592-08:00Fixing 'mscorlib.dll' targets a different processor When Building x86<p>Currently I’m working on a product that has been around for a long time, and will be for a lot longer.  Even thought 64bit has been out for a long time, this application has it roots in 32bit.  This is not necessarily a bad thing, as 64bit will not provide any real processing performance enhancements.  Prior to Visual Studio 2010, building with AnyCPU platform configuration was straight forward.  Now that we support purely 64bit OS on our server side, things because a little more difficult.  Long story short, we needed to configure everything to specify x86.  In doing so, we continued to get build errors on our TFS team build server.  The error “<em>error CS1607: Assembly generation -- Referenced assembly 'mscorlib.dll' targets a different processor</em>” would show up all over the place.  After ensuring that all our projects were set to x86 and the Configuration Manager for debug/release specified x86, we eventually found that the build process <strong>MSBuild Platform</strong> needed to be set to X86.</p> <p>As an interesting note, in our researching over x86 and x64, we came across this article <a href="http://blogs.msdn.com/b/rmbyers/archive/2009/06/09/anycpu-exes-are-usually-more-trouble-then-they-re-worth.aspx">AnyCPU Exes are usually more trouble than they're worth</a>.  If you’ve been adding new projects in Visual Studio 2010, you’ll notice that they all default to x86.  </p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-30893631810379240462012-10-19T10:38:00.000-07:002012-10-19T10:41:57.695-07:00Office Communicator Is Cool Check This Out<p>So being a somewhat Microsoft shop, we use Office Communicator which is a pretty dandy little piece of software for inter company screen sharing and instant messaging.  The other day a colleague had a theory that we could create an infinite loop with Office Communicator by doing  a three way share.  Well it worked and was quite humorous, here is our result.</p> <p><a href="http://lh6.ggpht.com/-mebDSdUnKcw/UIGQ3-4NvcI/AAAAAAAAASU/MlftxcMeoe8/s1600-h/image%25255B7%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-bOu3lyEWzLQ/UIGQ4-bHEWI/AAAAAAAAASc/sSPc6zjMsFQ/image_thumb%25255B3%25255D.png?imgmax=800" width="734" height="460" /></a></p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-19645279453986239962012-10-04T10:57:00.000-07:002012-10-04T10:58:13.899-07:00Alter Visual Studio Template Files<p>Out of the box, I’ve found Visual Studio template files to be just fine.  Recently I was doing some researching into using StyleCop so I installed in on my machine.  Little did I know, it went behind the scenes and altered some if now all template files.  In particular, I don’t care for their Interface and Class file templates, I tend to use <a href="http://www.jetbrains.com/resharper/">ReSharper</a> and <a href="http://submain.com/download/ghostdoc/">GhostDoc</a> to do cleanup and documentation.  If you want to change or revert your templates, your in luck, Visual Studio has backups.  Follow the steps below to restore whatever templates you need to.  In the example I will be restoring the C# class file for Visual Studio 2010 (10.0).</p> <p>1.  Go to the template folder you desire.  You will find the templates in the Program Files folder (Program Files (x86) on 64 bit system) and the particular version  here <strong><em>C:\Program Files\Microsoft Visual Studio {Version of VS, 10.0, 9.0…}\Common7\IDE\ItemTemplates.</em></strong>  In the case of the C# class you will have to drill down into \CSharp\Code\1033\ folder, and in there you will find a file called <em>Class.zip.bak</em>.  Delete the existing Class.zip file, copy the Class.zip.bak and rename it to Class.zip.  Do this process for any other templates you wish to revert.</p> <p>2.  Reset the IDE environment.  Open a Visual Studio command prompt (I do it in administrator mode on Windows 7).  It’s found in All Programs^Microsoft Visual Studio {Version 2010, 2008,…}^Visual Studio Tools.  Once the command windows is open run “<strong><em>devenv /setup</em></strong>” and you’re all set!</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-68302976718236113252012-07-11T14:03:00.001-07:002012-07-11T14:03:49.372-07:00Things To Improve Visual Studio Development<p>Visual Studio has come a long way since I started working with the first version of it.  Currently I’m on Visual Studio 2010.  Below lists some additions you can do to make you development experience better.</p> <p><a href="http://www.jetbrains.com/resharper/">ReSharper</a> : productivity tool that all developers should use.  Promotes good coding practices and makes refactoring a breeze!</p> <p><strong>Extensions</strong></p> <p>Extensions can be added by going to Tools^Extension Manager… and searching the online gallery.</p> <ul> <li><a href="http://submain.com/products/ghostdoc.aspx?utm_campaign=ghostdoc&utm_medium=listing&utm_source=visualstudiogallery">GhostDoc</a></li> <li><a href="http://visualstudiogallery.msdn.microsoft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef/">Productivity Power Tools</a></li> <li><a href="http://msdn.microsoft.com/en-us/vstudio/bb980963">Team Foundation Server Power Tools</a></li> <li>NuGet Package Manager</li> <li><a href="http://visualstudiogallery.msdn.microsoft.com/872d27ee-38c7-4a97-98dc-0d8a431cc2ed?SRC=VSIDE">JScript Editor Extensions</a></li> <li><a href="http://visualstudiogallery.msdn.microsoft.com/bb424812-f742-41ef-974a-cdac607df921?SRC=VSIDE">WoVS Default Browser Switcher</a></li> <li><a href="http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx">Entity Framework POCO Generator</a></li> <li><a href="http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-model-amp-database-first-walkthrough.aspx">Entity Framework DBContext Generator</a></li> </ul> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-7823208977755507882012-02-27T12:44:00.000-08:002012-02-27T12:44:04.927-08:00Team Foundation Server Custom Controls<p>So we’ve installed TFS 2010, and now the company is starting to pick up the pace with all types of users performing different roles.  So far, most of our modifications to the process template have been cosmetic, like moving tabs around, or adding fields.  A group of users came to us the other day, asking why the history tab has comments interwoven with the historical changes.  At that point all I could say is “Whatever you say in the past is history man.”  No, I didn’t say that, but it did get me thinking why there isn't a clear way to view the comments in chronological order.  </p> <p>In comes the Custom Control.  A custom control is a way to extend the process template in a way you see fit.  I definitely wouldn’t jump to using this as my first choice but in this case it fits.  Our end result would be another tab next to the history tab called “Comment History”, and in the tab would be a readonly window displaying only the comments from the work items history.  Before I start, I would like to list all the sites I used in researching this, as I didn’t just pull this out of a black hat.</p> <ul> <li><a href="http://www.ewaldhofman.nl/post/2010/08/10/Create-custom-work-item-control-for-TFS-Web-Access-2010-%28TWA%29.aspx?wwparam=1329942299&wwparam=1330116778" target="_blank">Create custom work item control for TFS Web Access 2010 (TWA)</a></li> <li><a href="http://msmvps.com/blogs/vstsblog/archive/2007/07/07/starting-using-custom-work-item-controls.aspx?wwparam=1329942287&wwparam=1330116656" target="_blank">Getting started using Custom Work Item Controls</a></li> </ul> <p>One of the key items which I will discuss which isn’t found in these threads is a way keep you work item layout xml to a minimum.</p> <p>NOTE: You should do all this work on the TFS server as it will make referencing certain DLLs much easier.</p> <p><strong><font size="4">1.</font></strong>  Open Visual Studio 2010, create 2 new class library projects, one called <strong><em>WitCustomControls</em></strong>, and one called <strong><em>WitCustomControls.WebAccess</em></strong>.  Set both projects to .NET 3.5.  The reason why we have 2 libraries will become clear in a bit.</p> <p><strong><font size="4">2.</font></strong>  In the <strong><em>WitCustomControls </em></strong>library, add a windows form User Control called CommentHistoryControl.  In the the <strong><em>WitCustomControls.WebAccess</em></strong> create a class called HistoryCommentControl.  For each project, create a file called HistoryCommentControl.wicc (this is a work item custom control file), and a class called WorkItemHistoryComment.  Right click the .wicc file and go to Properties; set the Build Action to Content (do this in both projects).  (NOTE: I know I’m doing a little duplicate coding here, but for the concept of the example I’m keeping it simple).  Remove any default class files like Class.cs.</p> <p><a href="http://lh3.ggpht.com/-07SK01OZHfI/T0vqfcGqq1I/AAAAAAAAARE/uzbF5I8gqRU/s1600-h/image%25255B11%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-TswAjdIERLs/T0vqfuNsbyI/AAAAAAAAARM/k6yFQxZPHAs/image_thumb%25255B5%25255D.png?imgmax=800" width="399" height="485" /></a></p> <p><strong><font size="4">3.</font></strong>  Let’s fill in the .wicc files real quick.  When the work item UI is loaded, whether it be in Visual Studio (winform) or team web access, the control that is referenced in the work item layout xml is searched for by that name, in our case HistoryCommentControl. The file defines the library and class to load to render the control.  Do the following:</p> <ul> <li>In the <strong><em>WitCustomControls</em></strong> project .wicc file add:</li> </ul> <div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff"><?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">="utf-8"</span> ?<span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">CustomControl</span> <span style="color: #ff0000">xmlns:xsi</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: #ff0000">xmlns:xsd</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema"</span><span style="color: #0000ff">></span><br /> <span style="color: #0000ff"><</span><span style="color: #800000">Assembly</span><span style="color: #0000ff">></span>WitCustomControls.dll<span style="color: #0000ff"></</span><span style="color: #800000">Assembly</span><span style="color: #0000ff">></span><br /> <span style="color: #0000ff"><</span><span style="color: #800000">FullClassName</span><span style="color: #0000ff">></span>WitCustomControls.HistoryCommentControl<span style="color: #0000ff"></</span><span style="color: #800000">FullClassName</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"></</span><span style="color: #800000">CustomControl</span><span style="color: #0000ff">></span></pre>
<br /></div>
<ul>
<li>In the <strong><em>WitCustomControls.WebAccess</em></strong> project .wicc file add:</li>
</ul>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff"><?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">="utf-8"</span> ?<span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">CustomControl</span> <span style="color: #ff0000">xmlns:xsi</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: #ff0000">xmlns:xsd</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema"</span><span style="color: #0000ff">></span><br /> <span style="color: #0000ff"><</span><span style="color: #800000">Assembly</span><span style="color: #0000ff">></span>WitCustomControls.WebAccess.dll<span style="color: #0000ff"></</span><span style="color: #800000">Assembly</span><span style="color: #0000ff">></span><br /> <span style="color: #0000ff"><</span><span style="color: #800000">FullClassName</span><span style="color: #0000ff">></span>WitCustomControls.WebAccess.HistoryCommentControl<span style="color: #0000ff"></</span><span style="color: #800000">FullClassName</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"></</span><span style="color: #800000">CustomControl</span><span style="color: #0000ff">></span></pre>
<br /></div>
<p><strong><font size="4">4.</font></strong>  Now the references we will need to inherit and implement the IWorkItemControl interface.  This is a little tricky, part of the DLLs are from Visual Studio install, and the other part come from TFS install.  </p>
<p>For both projects you will need:</p>
<ol>
<li><font size="1">C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll</font></li>
<li><font size="1">C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.WorkItemTracking.Controls.dll</font> </li>
</ol>
<p>For the <strong><em>WitCustomControls.WebAccess</em></strong> project you will need these additional ones:</p>
<ol>
<li><font size="1">C:\Windows\assembly\GAC_MSIL\Microsoft.TeamFoundation.WebAccess.Controls\10.0.0.0__b03f5f7f11d50a3a\Microsoft.TeamFoundation.WebAccess.Controls.dll</font></li>
<li><font size="1">C:\Windows\assembly\GAC_MSIL\Microsoft.TeamFoundation.WebAccess.WorkItemTracking\10.0.0.0__b03f5f7f11d50a3a\Microsoft.TeamFoundation.WebAccess.WorkItemTracking.dll</font> </li>
</ol>
<p><strong><font size="4">5.</font></strong>  I created a helper class to group the comment history data.  In the WorkItemHistoryComment file for both projects, add the following:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> WorkItemHistoryComment<br />{<br /> <span style="color: #0000ff">public</span> DateTime ChangedDate;<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> ChangedBy;<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Comment;<br />}</pre>
<br /></div>
<p><strong><font size="4">6.</font></strong>  The real work happens because these controls implement an interface called <a href="http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.workitemtracking.controls.iworkitemcontrol_members%28v=vs.90%29.aspx" target="_blank">IWorkItemControl</a>.  Below shows the code needed to create the content for the controls display.  In a nutshell, because we implement the interface, we get a reference to the WorkItem.  From that we can iterate over the revisions of the work item and look at all the fields that were modified.  The comment that is associated with a work item is in the WorkItem.History property.  For the winform control I used a WebBrowser control docked in the control.  The core of what we were trying to accomplish is in the method ExtractCommentsFromWorkItem(…) and AppendHtmlCommentSection(…).</p>
<p><strong><em>WitCustomControls</em></strong> user control code:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">partial</span> <span style="color: #0000ff">class</span> HistoryCommentControl : UserControl, IWorkItemControl<br />{<br /> <span style="color: #0000ff">private</span> IServiceProvider _serviceProvider;<br /><br /> <span style="color: #0000ff">public</span> HistoryCommentControl()<br /> {<br /> InitializeComponent();<br /> }<br /><br /> <span style="color: #cc6633">#region</span> IWorkItemControl Members<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">event</span> EventHandler BeforeUpdateDatasource;<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">event</span> EventHandler AfterUpdateDatasource;<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Clear() { }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> FlushToDatasource()<br /> {<br /> <span style="color: #008000">// do nothing because this is a readonly control</span><br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> InvalidateDatasource()<br /> {<br /> <span style="color: #0000ff">if</span> (IsInitialized())<br /> {<br /> <span style="color: #008000">// fill in the text box</span><br /> IEnumerable<WorkItemHistoryComment> comments = ExtractCommentsFromWorkItem(WorkItemDatasource <span style="color: #0000ff">as</span> WorkItem);<br /><br /> <span style="color: #0000ff">if</span> (comments.Count() > 0)<br /> {<br /> StringBuilder sb = <span style="color: #0000ff">new</span> StringBuilder(<span style="color: #006080">"<html><head>"</span>);<br /><br /> sb.Append(<span style="color: #006080">"<style rel=\"stylesheet\" type=\"text/css\">body {font-family: Tahoma,Geneva,Arial,Helvetica,Sans-serif; font-size:0.8em; } .comment-title { font-weight:bold; background-color:#EEEEEE; } .comment { font-size:0.8em; }</style>"</span>);<br /> sb.Append(<span style="color: #006080">"</head><body>"</span>);<br /><br /> AppendHtmlCommentSection(comments, sb);<br /><br /> sb.Append(<span style="color: #006080">"</body></html>"</span>);<br /><br /> <span style="color: #008000">// set web browser box</span><br /> webBrowserCommentHistory.DocumentText = sb.ToString();<br /> }<br /> }<br /> }<br /><br /> <span style="color: #0000ff">public</span> System.Collections.Specialized.StringDictionary Properties { get; set; }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> ReadOnly<br /> {<br /> get { <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>; }<br /> set { }<br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SetSite(IServiceProvider serviceProvider)<br /><br /> {<br /> <span style="color: #0000ff">this</span>._serviceProvider = serviceProvider;<br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">object</span> WorkItemDatasource { get; set; }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> WorkItemFieldName { get; set; }<br /><br /> <span style="color: #cc6633">#endregion</span><br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> IsInitialized()<br /> {<br /> <span style="color: #008000">// this control doesn't need a field name becasue it's readonly</span><br /> <span style="color: #0000ff">return</span> (!IsDisposed<br /> && WorkItemDatasource != <span style="color: #0000ff">null</span>);<br /> }<br /><br /> <span style="color: #0000ff">private</span> IEnumerable<WorkItemHistoryComment> ExtractCommentsFromWorkItem(WorkItem wi)<br /> {<br /> List<WorkItemHistoryComment> comments = <span style="color: #0000ff">new</span> List<WorkItemHistoryComment>();<br /><br /> <span style="color: #0000ff">foreach</span> (Revision rev <span style="color: #0000ff">in</span> wi.Revisions)<br /> {<br /> <span style="color: #0000ff">foreach</span> (Field f <span style="color: #0000ff">in</span> rev.Fields)<br /> {<br /> <span style="color: #008000">// determine if this revision has a the history field changed</span><br /> <span style="color: #008000">// if so and not empty show it</span><br /> <span style="color: #0000ff">if</span> (0 == <span style="color: #0000ff">string</span>.Compare(f.Name, <span style="color: #006080">"History"</span>, <span style="color: #0000ff">true</span>)<br /> && !<span style="color: #0000ff">string</span>.IsNullOrEmpty(f.Value <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>))<br /> {<br /> comments.Add(<span style="color: #0000ff">new</span> WorkItemHistoryComment<br /> {<br /> ChangedBy = (<span style="color: #0000ff">string</span>)rev.Fields[<span style="color: #006080">"Changed By"</span>].Value,<br /> ChangedDate = (DateTime)rev.Fields[<span style="color: #006080">"Changed Date"</span>].Value,<br /> Comment = (<span style="color: #0000ff">string</span>)f.Value<br /> });<br /> }<br /> }<br /> }<br /> <br /> <span style="color: #0000ff">return</span> comments.OrderByDescending(c => c.ChangedDate);<br /> }<br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> AppendHtmlCommentSection(IEnumerable<WorkItemHistoryComment> comments, StringBuilder sb)<br /> {<br /> <span style="color: #008000">// help verbage</span><br /> sb.Append(<span style="color: #006080">"<div>To add a comment, use the History tab where the comment input is located.</div><br/<br/>"</span>);<br /> <br /> <span style="color: #008000">// start container for comments</span><br /> sb.Append(<span style="color: #006080">"<div><div><table style=\"width:100%;table-layout:fixed;\" cellspacing=\"1\" cellpadding=\"0\"><tbody>"</span>);<br /> <br /> <span style="color: #0000ff">foreach</span> (WorkItemHistoryComment comment <span style="color: #0000ff">in</span> comments)<br /> {<br /> <span style="color: #008000">// row that indicates comment header</span><br /> sb.Append(<span style="color: #006080">"<tr><td> <table style=\"width:100%;font-size:0.8em;\" cellspacing=\"0\" cellpadding=\"1\"> <tbody> <tr>"</span>);<br /><br /> <span style="color: #008000">// from TFS history header row onclick=\"_ctl00_c_we_ctl48_wc.onExpandCollapseChangeTitle(this);\"</span><br /> <span style="color: #008000">// wish we could pigback on this collapsing behavior</span><br /> sb.Append(<span style="color: #006080">"<td width=\"16\" align=\"center\"><img border=\"0\" align=\"absMiddle\" style=\"width:18px;height:17px;cursor:pointer\" src=\"https://tfs.pcbancorp.com:8443/tfs/web/Resources/Images/minus.gif\"></td>"</span>);<br /> sb.AppendFormat(<span style="color: #006080">"<td class=\"comment-title\">{0} [{1}]</td>"</span>, comment.ChangedBy, comment.ChangedDate);<br /> sb.Append(<span style="color: #006080">"</tr> </tbdody> </table> </td></tr>"</span>);<br /> <span style="color: #008000">// row that represents the actual comment</span><br /> sb.AppendFormat(<span style="color: #006080">"<tr class=\"comment\"><td><div>{0}</div></td></tr>"</span>,<br /> comment.Comment);<br /> }<br /><br /> <span style="color: #008000">// finish container for comments</span><br /> sb.Append(<span style="color: #006080">"</tbody></table></div></div>"</span>);<br /> }<br />}</pre>
<br /></div>
<p><strong><em>WitCustomControls.WebAccess</em></strong> user control code:</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> HistoryCommentControl : BaseWorkItemWebControl<br /><br /> <span style="color: #0000ff">public</span> HistoryCommentControl()<br /><br /> : <span style="color: #0000ff">base</span>(HtmlTextWriterTag.Div) { }<br /><br /> <span style="color: #0000ff">public</span> System.Web.UI.HtmlControls.HtmlGenericControl HtmlControl { get; <span style="color: #0000ff">protected</span> set; }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> InitializeControl()<br /> {<br /> <span style="color: #0000ff">base</span>.InitializeControl();<br /><br /> <span style="color: #008000">// Create control</span><br /> EnsureInnerControls();<br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> EnsureInnerControls()<br /> {<br /> <span style="color: #0000ff">if</span> (HtmlControl != <span style="color: #0000ff">null</span>)<br /> <span style="color: #0000ff">return</span>;<br /><br /> HtmlControl = <span style="color: #0000ff">new</span> System.Web.UI.HtmlControls.HtmlGenericControl(<span style="color: #006080">"div"</span>);<br /><br /> <span style="color: #0000ff">base</span>.Controls.Clear();<br /> <span style="color: #0000ff">base</span>.Controls.Add(HtmlControl);<br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> InvalidateDatasource()<br /> {<br /> <span style="color: #0000ff">base</span>.InvalidateDatasource();<br /><br /> EnsureInnerControls();<br /><br /> <span style="color: #008000">// set control value</span><br /> IEnumerable<WorkItemHistoryComment> comments =<br /> ExtractCommentsFromWorkItem(<span style="color: #0000ff">this</span>.WorkItemDatasource <span style="color: #0000ff">as</span> WorkItem);<br /><br /> <span style="color: #0000ff">if</span> (comments.Count() > 0)<br /> {<br /> StringBuilder sb = <span style="color: #0000ff">new</span> StringBuilder();<br /><br /> <span style="color: #008000">// get html with comments embedded</span><br /> AppendHtmlCommentSection(comments, sb);<br /><br /> <span style="color: #008000">// set contents of html control</span><br /> HtmlControl.InnerHtml = sb.ToString();<br /> }<br /> }<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> FlushToDatasource()<br /> {<br /> <span style="color: #0000ff">base</span>.FlushToDatasource();<br /><br /> HtmlControl.InnerHtml = <span style="color: #0000ff">string</span>.Empty;<br /> }<br /><br /> <span style="color: #0000ff">private</span> IEnumerable<WorkItemHistoryComment> ExtractCommentsFromWorkItem(WorkItem wi)<br /> {<br /> List<WorkItemHistoryComment> comments = <span style="color: #0000ff">new</span> List<WorkItemHistoryComment>();<br /><br /> <span style="color: #0000ff">foreach</span> (Revision rev <span style="color: #0000ff">in</span> wi.Revisions)<br /> {<br /> <span style="color: #0000ff">foreach</span> (Field f <span style="color: #0000ff">in</span> rev.Fields)<br /> {<br /> <span style="color: #008000">// determine if this revision has a the history field changed</span><br /> <span style="color: #008000">// if so and not empty show it</span><br /> <span style="color: #0000ff">if</span> (0 == <span style="color: #0000ff">string</span>.Compare(f.Name, <span style="color: #006080">"History"</span>, <span style="color: #0000ff">true</span>)<br /> && !<span style="color: #0000ff">string</span>.IsNullOrEmpty(f.Value <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>))<br /> {<br /> comments.Add(<span style="color: #0000ff">new</span> WorkItemHistoryComment<br /> {<br /> ChangedBy = (<span style="color: #0000ff">string</span>)rev.Fields[<span style="color: #006080">"Changed By"</span>].Value,<br /> ChangedDate = (DateTime)rev.Fields[<span style="color: #006080">"Changed Date"</span>].Value,<br /> Comment = (<span style="color: #0000ff">string</span>)f.Value<br /> });<br /> }<br /> }<br /> }<br /><br /> <span style="color: #0000ff">return</span> comments.OrderByDescending(c => c.ChangedDate);<br /> }<br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> AppendHtmlCommentSection(IEnumerable<WorkItemHistoryComment> comments, StringBuilder sb)<br /> {<br /> <span style="color: #008000">// help verbage</span><br /> sb.Append(<span style="color: #006080">"<div>To add a comment, use the History tab where the comment input is located.</div><br/<br/>"</span>);<br /><br /> <br /><br /> <span style="color: #008000">// start container for comments</span><br /><br /> sb.Append(<span style="color: #006080">"<div class=\"tswa-compositectrl\"><div class=\"tswa-historyctrl-changeshost\"><table style=\"width:100%;table-layout:fixed;\" cellspacing=\"1\" cellpadding=\"0\"><tbody>"</span>);<br /><br /> <br /><br /> <span style="color: #0000ff">foreach</span> (WorkItemHistoryComment comment <span style="color: #0000ff">in</span> comments)<br /><br /> {<br /><br /> <span style="color: #008000">// row that indicates comment header</span><br /><br /> sb.Append(<span style="color: #006080">"<tr><td> <table width=\"100%\" cellspacing=\"0\" cellpadding=\"1\"> <tbody> <tr class=\"tswa-historyctrl-revhead\">"</span>);<br /><br /> <span style="color: #008000">// from TFS history header row onclick=\"_ctl00_c_we_ctl48_wc.onExpandCollapseChangeTitle(this);\"</span><br /><br /> <span style="color: #008000">// wish we could pigback on this collapsing behavior</span><br /><br /> sb.Append(<span style="color: #006080">"<td width=\"16\" align=\"center\"><img border=\"0\" align=\"absMiddle\" style=\"width:18px;height:17px;cursor:pointer\" src=\"https://tfs.pcbancorp.com:8443/tfs/web/Resources/Images/minus.gif\"></td>"</span>);<br /><br /> sb.AppendFormat(<span style="color: #006080">"<td>{0} [{1}]</td>"</span>, comment.ChangedBy, comment.ChangedDate);<br /><br /> sb.Append(<span style="color: #006080">"</tr> </tbdody> </table> </td></tr>"</span>);<br /><br /> <span style="color: #008000">// row that represents the actual comment</span><br /> sb.AppendFormat(<span style="color: #006080">"<tr><td><div class=\"tswa-historyctrl-description\">{0}</div></td></tr>"</span>,<br /> comment.Comment);<br /> }<br /><br /> <span style="color: #008000">// finish container for comments</span><br /> sb.Append(<span style="color: #006080">"</tbody></table></div></div>"</span>);<br /> }<br />}</pre>
<br /></div>
<p><strong><font size="4">7.</font></strong>  Now that we have our libraries created, we have to package them up so they can be installed in the correct location.  We at the point of understanding why we created 2 libraries.  When Visual Studio opens it loads the control from <em>C:\Documents and Settings\All Users\Application Data\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\10.0</em> and when TFS web access loads the control it does it from <em>%ProgramFiles%\Microsoft Team Foundation Server 2010\Application Tier\Web Access\Web\App_Data\CustomControls.</em>  Because of this, we will create a setup package that will install our libraries in different locations, the winform control will go in the all user’s app data, and the web control will go in the TFS web application folder.  </p>
<p>Create 2 setup projects (found in Other Project Types^Setup and Deployment^Visual Studio Installer^Setup Project).  One call WitCustomControlsSetup (for the 32-bit version) and one called WitCustomControlsSetup.x64 (for the 64-bit version).  The key difference is that on the 64-bit version, the files need to go in the 64-bit program files directory.  Both will follow the steps below and I will note when the 64-bit version differs.</p>
<p><strong>a.</strong>  Right click the setup project and select View^file System.  Create the folder TWAAppDataFolder, the Application Folder will already exist.</p>
<p><strong>b.</strong>  Select the Application Folder.  Right click in the output area and add the <strong><em>WitCustomControls</em></strong> libraries project output, repeat this and add it’s Content output as well.</p>
<p><a href="http://lh4.ggpht.com/-vcIBjl8H2vs/T0vqfyQB0II/AAAAAAAAARU/YcbhNl8ugWw/s1600-h/image%25255B16%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-yzqFkGwOdQ8/T0vqgFZ9aXI/AAAAAAAAARc/6BeiIgCSdnA/image_thumb%25255B8%25255D.png?imgmax=800" width="591" height="195" /></a></p>
<p><strong>c.</strong>  Select the TWAAppDataFolder.  Like before, right click in the output area and add the <strong><em>WitCustomControls.WebAccess</em></strong> libraries project output, repeat this and add it’s Content output as well.  The final should be similar to the following.</p>
<p><a href="http://lh6.ggpht.com/-eSz2OQUZ_Vw/T0vqgXAtV8I/AAAAAAAAARk/UPB_u2PEEww/s1600-h/image%25255B32%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-Y1oWie7-nP0/T0vqguRDp6I/AAAAAAAAARs/Uy2j_tbObi8/image_thumb%25255B16%25255D.png?imgmax=800" width="780" height="179" /></a></p>
<p><strong>d.</strong>  Now right click on the Application Folder and select Properties Window. Set the DefaultLocation value to <em>[CommonAppDataFolder]\All Users\Application Data\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\10.0.</em>  Right click on the TWAAppDataFolder and go to the properties.  Set it’s DefaultLocation to <em>[ProgramFilesFolder]\Microsoft Team Foundation Server 2010\Application Tier\Web Access\Web\App_Data\CustomControls</em> (IMPORTANT: on the 64-bit setup project replace <em>[ProgramFilesFolder]</em> with <em>[ProgramFiles64Folder]</em>).</p>
<p><a href="http://lh6.ggpht.com/-JA7hIBJ8vvo/T0vqgwQjNKI/AAAAAAAAAR0/8VSgv1XyxYk/s1600-h/image%25255B37%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-jVg7On0CmdQ/T0vqg5-8J_I/AAAAAAAAAR8/rTWBs7izmUI/image_thumb%25255B19%25255D.png?imgmax=800" width="605" height="204" /></a></p>
<p><strong>e.</strong>  Set the project property InstallAllUsers and RemovePreviousVersion to true.</p>
<p><strong>f.</strong>  For the 64-bit version, you must change the setup projects property TargetPlatform to x64.</p>
<p><strong>g.</strong>  Remove the TFS DLL dependencies.</p>
<p><a href="http://lh4.ggpht.com/-_YV8zRofkTE/T0vqhTOf9cI/AAAAAAAAASE/nukw5KrGLBM/s1600-h/image%25255B23%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-i3zvgDPwU5E/T0vqhg_2QrI/AAAAAAAAASM/K7m1YqF-NHU/image_thumb%25255B11%25255D.png?imgmax=800" width="278" height="319" /></a></p>
<p><strong><font size="4">8.</font></strong>  Install the 64-bit version on your TFS server.  Install the 32/64 –bit on any client machines you want this control to be used in by Visual Studio.</p>
<p><font size="4"><strong>9.</strong></font>  The very last thing we need to do is modify our work item xml file and add our new control to the layout section.  The reason we have 2 libraries and 2 wicc files is so we don’t have to duplicate our layout setup for winform and web access.  If we didn’t we’d have to use the <Layout Target=”Web”> and <Layout Target=”WinForm”>, which is a pain.  Below is the tab I added to our work item layout.  Notice the Type attribute, this is the same name as the wicc file, and there lies the magic of it all!</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff"><</span><span style="color: #800000">Tab</span> <span style="color: #ff0000">Label</span><span style="color: #0000ff">="Comment History"</span><span style="color: #0000ff">></span><br /> <span style="color: #0000ff"><</span><span style="color: #800000">Control</span> <span style="color: #ff0000">Type</span><span style="color: #0000ff">="HistoryCommentControl"</span> <span style="color: #ff0000">Label</span><span style="color: #0000ff">=""</span> <span style="color: #ff0000">LabelPosition</span><span style="color: #0000ff">="Top"</span> <span style="color: #ff0000">Dock</span><span style="color: #0000ff">="Fill"</span> <span style="color: #0000ff">/></span><br /><span style="color: #0000ff"></</span><span style="color: #800000">Tab</span><span style="color: #0000ff">></span></pre>
<br /></div> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-25635317059091550742012-01-30T20:20:00.000-08:002014-01-10T09:31:08.691-08:00Things I Keep In My Toolbox<p>This thread is my ongoing attempt to remind myself of the tools I keep somewhere in my toolbox.</p> <p><strong><u>IDE Tools</u></strong></p> <ul> <li><a href="http://www.microsoft.com/visualstudio/" target="_blank">Visual Studio</a> </li> <li><a href="http://www.eclipse.org/" target="_blank">Eclipse</a> </li> <ul> <li><a href="http://spring.io/tools">Spring Tool Suite</a></li> </ul> <li><a href="http://xamarin.com/">Xamarin Studio</a> (Mono IDE)</li> <li><a href="http://www.jetbrains.com/webstorm/">WebStorm</a> (javascript IDE)</li> <li><a href="http://www.nunit.org/" target="_blank">NUnit</a> </li> <li><a href="http://developer.android.com/" target="_blank">Android SDK</a> </li> <li><a href="http://www.ultrapico.com/Expresso.htm" target="_blank">Expresso Regular Expression Tool</a> </li> <li><a href="http://code.google.com/p/moq/" target="_blank">MOQ .Net Mocking</a> </li> <li><a href="http://en.wikipedia.org/wiki/SQL_Server_Management_Studio" target="_blank">SQL Management Studio</a> </li> <li><a href="http://www.microsoft.com/sqlserver/en/us/editions/compact.aspx" target="_blank">SQL Compact Edition</a> </li> </ul> <p><u><strong>Web</strong></u></p> <ul> <li><a href="http://jquery.com/" target="_blank">jQuery</a> </li> <li><a href="http://www.iis.net/download/seotoolkit" target="_blank">SEO Tool by IIS Team</a> </li> <li><a href="http://www.mozilla.org/" target="_blank">Firefox</a> </li> <ul> <li><a href="http://getfirebug.com/" target="_blank">Firebug</a> </li> <li><a href="https://addons.mozilla.org/en-US/firefox/addon/colorzilla/" target="_blank">ColorZilla</a> </li> <li><a href="https://addons.mozilla.org/en-US/firefox/addon/user-agent-switcher/" target="_blank">User Agent Switcher (Firefox)</a> </li> </ul> <li><a href="https://www.google.com/intl/en/chrome/browser/">Chrome</a></li> <ul> <li><a href="https://chrome.google.com/webstore/detail/user-agent-switcher/lkmofgnohbedopheiphabfhfjgkhfcgf?hl=en">User Agent Switcher</a></li> <li><a href="https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en">Postman</a></li> </ul> </ul> <p><strong><u>Cryptography</u></strong></p> <ul> <li><a href="http://code.google.com/p/cryptophane/" target="_blank">Cryptophane</a> </li> <li><a href="http://www.openssl.org/" target="_blank">OpenSSL</a> </li> </ul> <p><u><strong>Design Tools</strong></u></p> <ul> <li><a href="http://inkscape.org/" target="_blank">Inkscape</a> </li> <li><a href="http://www.gimp.org/" target="_blank">GIMP</a> </li> </ul> <p><strong><u>Development Other</u></strong></p> <ul> <li><a href="http://msdn.microsoft.com/en-us/vstudio/bb980963" target="_blank">Visual Studio Power Tools</a> </li> <li><a href="https://tfsalerts.codeplex.com/" target="_blank">TFS Global Alerts</a> </li> <li><a href="http://www.teamprise.com/" target="_blank">Team Explorer Everywhere (Eclipse plugin)</a> </li> <li><a href="http://xcaptcha.codeplex.com/" target="_blank">XCaptcha</a> </li> <li><a href="http://code.google.com/apis/recaptcha/intro.html" target="_blank">Google reCAPTCHA</a> </li> <li><a href="http://tortoisesvn.net/" target="_blank">TortoiseSVN</a> </li> <li><a href="http://www.fiddler2.com/fiddler2/" target="_blank">Fiddler</a> </li> </ul> <p><strong><u>Windows General Tools</u></strong></p> <ul> <li><a href="http://www.slysoft.com/download.html" target="_blank">Virtual Clone Drive</a> </li> <li><a href="http://www.7-zip.org/" target="_blank">7-Zip</a> </li> <li><a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/" target="_blank">PuTTY Telnet/SSH Tool</a> </li> <li><a href="http://filezilla-project.org/" target="_blank">Filezilla (client and server)</a> </li> <li><a href="http://www.xmarks.com/" target="_blank">xmarks</a> </li> <li><a href="https://lastpass.com/" target="_blank">LastPass</a> </li> <li><a href="http://www.digsby.com/" target="_blank">Digsby IM Chat Client</a> </li> <li><a href="http://notepad-plus-plus.org/" target="_blank">Notepadd++</a> </li> <li><a href="http://explore.live.com/" target="_blank">Windows Live</a> </li> <li><a href="http://getgreenshot.org/" target="_blank">Greenshot</a> </li> </ul> <p><strong><u>Mac General Tools</u></strong></p> <ul> <li><a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a></li> </ul> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com1tag:blogger.com,1999:blog-8391484539096863315.post-25546582000601477682012-01-25T13:23:00.000-08:002012-01-25T13:38:25.298-08:00Cropping Images In .NET The Easy Way<p>I’ve been working on a pet project of mine <a href="http://www.sitetravelers.com" target="_blank">Site Travelers</a>, and I needed a easy way to crop images that were uploaded to the server (ASP.NET).  Obviously I knew how to do this the manual way, but this is one of those all too common cases of functionality that many people require.  So, using my trusty search engine, I went shopping.  There are quite a few good examples out there on how to do it, including writing helper functions, but I wanted something already packaged.  I hit the jackpot when I came across a library from <a href="http://codecarvings.com/" target="_blank">Code Carvings</a>. They have a really slick image manipulation library called <a href="http://piczard.com/" target="_blank">piczard</a>.  Their documentation is fantastic and easy to read with plenty of examples to get you down the road.  Using this library reduced everything I needed to do, crop and get bytes of data, down to the following 2 lines!</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">FixedResizeConstraint constraint = <span style="color: #0000ff">new</span> FixedResizeConstraint(180, 120);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">byte</span>[] bytes = constraint.SaveProcessedImageToByteArray(</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> file.InputStream, </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">new</span> JpegFormatEncoderParams(60));</pre>
<!--CRLF--></div>
</div> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0tag:blogger.com,1999:blog-8391484539096863315.post-78864165915529624332012-01-25T12:19:00.001-08:002012-01-25T12:19:41.153-08:00Automate Work Item Modification To Team Projects<p>I’ve successfully rolled out a full implementation of TFS at the company I work for and it’s been very smooth and rewarding.  The best part was that we spent time with the company and determined their work flows which we then used to created a process template to fit company not the company trying to fit an existing template.  As always, you need to tune it slightly as you start to use it.  As we’ve added more team projects and a few team collections, one thing we quickly realized is that updating team project with modified work item definitions needed to be automated.  Luckily there is most of the leg work was done for us already provided by this blog <a href="http://www.edsquared.com/2010/06/18/deploying+process+template+changes+using+tfs+2010+build.aspx" target="_blank">Deploying Process Template Changes Using TFS 2010 Build</a> which contains the build process template.  Below I provide the steps we went through to achieve the desired results.</p> <p>NOTE: We stored this automated build in a team project called TFS.  The team project was a source control repository for all of our team project process templates.</p> <p>1.  Ensure that your TFS build service account (we kept it simple and had an AD account <i>tfsbuild)</i> is part of the Team Foundation Administrators group; this is done at the Application Tier level in the TFS administration console.  See article <a href="http://msdn.microsoft.com/en-us/library/dd236912.aspx">Managing Global Lists for Work Item Types [witadmin]</a> for the reason why.</p> <p>2.  Create a new build definition and give it a meaningful name, we named it to be that of the team project collection since all our team projects in most collections used the same process template.</p> <p>3.  Set the workspace location, this will be the version control folder that contains your process template.  This will be a path like: <i>$/TFS/ProcessTemplates/Test/My Template/Process Template</i>. </p> <p><a href="http://lh3.ggpht.com/-UkFNSDExL9Q/TyBj0BkaOgI/AAAAAAAAAPg/KluudyTYlx0/s1600-h/image%25255B3%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-INpQ9JNifj0/TyBj0bNr5jI/AAAAAAAAAPo/CoBdfb50mmY/image_thumb%25255B1%25255D.png?imgmax=800" width="499" height="235" /></a></p> <p>4.  Define a drop location for you build items.  It will be a UNC path like.</p> <p><a href="http://lh4.ggpht.com/-Ah8oqKnQoUs/TyBj01ZsTcI/AAAAAAAAAPw/B-d3ZCuA1rg/s1600-h/image%25255B7%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-72xVntG3Sxw/TyBj1HXiLvI/AAAAAAAAAP4/HXb-m-LP94k/image_thumb%25255B3%25255D.png?imgmax=800" width="499" height="235" /></a></p> <p>5.  On the process tab set the process template to the ProcessTemplateDeploymentTemplate.xaml.  If this process template is not in the list,  you need to use the New button to select this existing template like <i>$/TFS/BuildProcessTemplates/ProcessTemplateDeploymentTemplate.xaml</i>.</p> <p><a href="http://lh3.ggpht.com/-px0ZoX8YAlU/TyBj1ebBgJI/AAAAAAAAAQA/b3IWqlWmaYk/s1600-h/image%25255B12%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-HJrSCa6f46o/TyBj10EF0qI/AAAAAAAAAQI/Y8qm_g_Oo1Y/image_thumb%25255B6%25255D.png?imgmax=800" width="522" height="194" /></a></p> <p>6.  Fill in the required build process parameters. </p> <ul> <li><b>Team Projects</b>: this is a string list of team project names contained within the collection being updated. </li> <li><b>TFS Server Collection URL</b>: enter in the TFS url for the team collection being updated.  This will be like: https://tfs.pcbancorp.com:{port}/tfs/{Team Project Collection Name}.  </li> <li><b>Work Item Type Definition Files</b>:  a list of the work item type definition files which will be updated.  NOTE:  This list must be in the same order as the type name list defined in the step next bullet.</li> <li><b>Work Item Type Name</b>:  a string list of work item type names.  This must be in the same order as the file list defined in step previous bullet</li> </ul> <p><a href="http://lh3.ggpht.com/-4mbVULjRpkQ/TyBj2J-G3MI/AAAAAAAAAQQ/FTjm_4yGDVU/s1600-h/image%25255B16%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-eDV_2iIYKh4/TyBj2eKOchI/AAAAAAAAAQY/LittBqeVIg8/image_thumb%25255B8%25255D.png?imgmax=800" width="535" height="132" /></a></p> <p>7.  Save the build definition.</p> <p>8.  Ensure that the [{TeamCollectionName}]\Project Collection Build Service Accounts role has the following permissions:</p> <ul> <li>For the team collection the following highlighted permissions.</li> </ul> <p><a href="http://lh5.ggpht.com/-FochfTo1-sI/TyBj2cTrk9I/AAAAAAAAAQg/R8WCtezrfDA/s1600-h/image%25255B20%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-pNGsrKzdu8M/TyBj2pA8WjI/AAAAAAAAAQk/gjCCrpQUpV4/image_thumb%25255B10%25255D.png?imgmax=800" width="317" height="353" /></a></p> <ul> <li>For each team project that is to be updated.</li> </ul> <p><a href="http://lh6.ggpht.com/-TTniLZdSszA/TyBj2-82QgI/AAAAAAAAAQs/-TdWSDJPvJE/s1600-h/image%25255B24%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-VfzjY6Ca-Bo/TyBj3LHuQ4I/AAAAAAAAAQ4/VjN4sL-V2co/image_thumb%25255B12%25255D.png?imgmax=800" width="451" height="246" /></a></p> <p>9.  You can now queue this build and watch your team projects within the given project collection updated with you process template changes!  Man, that beets manual work.</p> - Tyson -http://www.blogger.com/profile/05531361909020836097noreply@blogger.com0