Thursday, June 04, 2015

Getting started with Azure in PowerShell

As it turns out, Azure has a ton of cmdlets available in the PowerShell command line to help you quickly and easily manage aspects of Azure.


  • Install the Azure PowerShell from the Microsoft Web Platform Installer
  • Install the Azure AD Module from the links on this page.
  • After installing the Microsoft Online pack, you may have to copy the 'MSOnline' and 'MSOnlineExtended' folders from 'C:\windows\system32\WindowsPowerShell\v1.0\Modules' to 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules' if you're running a server version of Windows
  • Open a PowerShell session as Administrator
  • Run the command "Import-Module azure"
  • Run the command "Import-Module MSOnline"
Here are some of the ones you'll need to get started:

  • Add-AzureAccount -- Allows you to enter credentials and register your account with PowerShell so that you can manage it
  • Get-AzureAccount -- shows you the currently active accounts
  • Get-AzureSubscription -- shows the subscriptions available for the currently selected azure account
Also, to manage the roles in your Azure Active Directory, check out this page on Microsoft's Azure section.

Beginning in version 0.8.0, the Azure PowerShell installation includes more than one PowerShell module. You must explicitly decide whether to use the commands that are available in the Azure module or the Azure Resource Manager module. To make it easy to switch between them, we have added a new cmdlet, Switch-AzureMode, to the Azure Profile module.
When you use Azure PowerShell, the cmdlets in the Azure module are imported by default. To switch to the Azure Resource Manager module, use the Switch-AzureMode cmdlet. It removes the Azure module from your session and imports the Azure Resource Manager and Azure Profile modules.
To switch to the AzureResoureManager module, type:
PS C:\> Switch-AzureMode -Name AzureResourceManager
To switch back to the Azure module, type:
PS C:\> Switch-AzureMode -Name AzureServiceManagement
By default, Switch-AzureMode affects only the current session. To make the switch effective in all PowerShell sessions, use the Global parameter of Switch-AzureMode.

To start log streaming for a specific web application, use this command:
PS C:\> Get-AzureWebsiteLog -Tail -Name mywebsitenamehere

Sunday, May 31, 2015

Getting access to roles and group claims in Azure AD using the Graph API

Check this link out. It contains a tutorial on how to get Roles and Groups in Azure AD, so that you can have a single code-base for checking roles and groups regardless of whether you're using Azure AD or on-prem AD.

Also check out this link to an Azure AD example on GitHub for getting Group access in your applications

Tuesday, May 26, 2015

Implementing delegated authentication from an Azure MVC web app to an Azure Web API web service

Follow the information on this tutorial. Contained within that link, is this tutorial on authenticating a web app with delegated user identity to a web API service.

Authenticating users on an Azure web site (MVC) using Azure Active Directory (AAD)

Follow this guide provided on Github. It provides all of the information you need to enable the simplest form of Azure AD authentication in an MVC app. It can be used as the beginning step to getting a fully authenticated MVC web app / web API stack.

Monday, May 18, 2015

Creating an Intranet MVC 5 application using Windows Authentication that connects to a separate Intranet Web API 2 application also using Windows Authentication

Recently I wanted to create an Intranet MVC application using Windows Authentication that connects to a separate, pre-existing Intranet Web API 2 web service that also uses Windows Authentication. In order to get the Windows Authentication of the MVC application propagated to authenticate with the Web API 2 web service, I had to do the following:

1) Place the following in both applications' <system.web> sections in their respective configuration files.

        <authentication mode="Windows" />
        <authorization>
            <deny users="?" />
        </authorization>
2) Update the .NET aspnet.config file located at "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Aspnet.config" to change the following settings to the following values:

        <legacyImpersonationPolicy enabled="false"/>
        <alwaysFlowImpersonationPolicy enabled="true"/>
 3) In the code for the MVC app that wants to call the Web API 2 app, do the following:

            WindowsIdentity identity = (WindowsIdentity) this.HttpContext.User.Identity;

            using (identity.Impersonate())
            {
                searchModel.SearchResults = this.webApiService.FindWebApiItems(searchModel.SearchCriteria);
            }

This last bit is necessary to ensure that the currently authenticated user in the MVC app gets correctly propagated to the Web API 2 app. In the service that's mentioned in the code above, you'll also need to do the following for interacting with Web API 2:

4) Use the following to connect to Web API 2:

            HttpClientHandler handler = new HttpClientHandler
            {
                PreAuthenticate = true, 
                UseDefaultCredentials = true, 
                Credentials = CredentialCache.DefaultNetworkCredentials
            };

            using (HttpClient client = new HttpClient(handler))
            {
                string result = client.GetStringAsync(uriBuilder.Uri).GetAwaiter().GetResult();

                IList<MyWebApiModel> webApiModels = JsonConvert.DeserializeObject<MyWebApiModel[]>(result);

                return webApiModels;
            }
You should now have working code to propagate Windows Authentication via services.

As a side note, apparently there's also a way to change the settings so that you don't have to modify the global aspnet.config file, you can do it on a per-AppPool basis. The technique is described here, though I've never tried it myself.

Monday, April 27, 2015

A little gotcha with the Microsoft Task Parallel Library (TPL) Dataflow library

I've recently started using the Microsoft TPL Dataflow library in order to help improve the performance of some of our product's scheduled jobs. However, today, I ran into a little gotcha that's pretty important. When you're linking one block to another block, you must always ensure that the source block links to at least one target block that accepts its messages, otherwise it'll most likely deadlock!

Wednesday, April 08, 2015

Resolving "Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'" in IIS with WCF web services

If you get an error that looks like "Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'" in IIS while testing WCF web services, it most likely means that you haven't correctly specified the certificate for your service in IIS. If you're certain you've correctly specified the certificate, it most likely means that the IIS user doesn't have access to it, so you'll have to go in and manually grant permissions for it.

Removing a certificate binding from a port in Windows

As many people don't know, in Windows certificates can be bound to ports for securing content transferred over those ports. IIS happens to be particularly negatively affected by this if another program has a certificate bound to a port that you want to use, e.g. 443 for serving web pages.

Use the information at the following page to find the certificate binding and delete it :

https://msdn.microsoft.com/en-us/library/ms733791(v=vs.110).aspx

The short version:

Find the port: netsh http show sslcert | grep -C 5 443

This command will show all the SSL certificates that are bound to ports on your machine.

Delete the port: netsh http delete sslcert ipport=0.0.0.0:443

This should help deal with some of the more annoying (and less verbose) errors when doing things like trying to configure WCF services to use SSL.

Friday, March 20, 2015

Creating ChannelFactory instances that are configured with Custom credentials in WCF

Check this out: Setting Client Credentials

I just discovered this wonderful piece of information on how to properly create ChannelFactory instances in WCF for clients.

Sunday, March 15, 2015

Using Ninject in an IIS-hosted environment to create a WCF service instance that's in a shared assembly (i.e. not the web application assembly)

Recently I wanted to create several WCF services for some of our internal applications and host these services in multiple different servers. There'd be no difference in the code between the locations where they'd be hosted. In order to avoid code duplication, I wanted to make these WCF services common and then just host them in the IIS applications. However, it's not as simple as creating a new (shared) assembly, creating the WCF service in that assembly and then sharing it between the different services. When I tried this, I ran into the problem where even though I specified the service in the config section:

<system.serviceModel>
         ....
</system.serviceModel> 
 
... it still wouldn't find my service and load it (I'm using Ninject as a dependency injection container for my WCF services).  They key to getting the shared services to be found and loaded properly was to create a .svc file in each of the services where the WCF services were shared, and it looked something like this in each case:

<%@ ServiceHost Language="C#" Debug="false" Service="MyWcfSharedServices.MySharedWebService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>

After adding the .svc file and using the path to it in the system.serviceModel configuration in the configuration file, everything worked perfectly.

Wednesday, January 28, 2015

Resolving "The agent process was stopped while the test was running" on a TFS build agent

I'm currently working on a project that uses TFS for automated builds. Recently, our builds started failing with the error "The agent process was stopped while the test was running" while running unit tests. It wouldn't always happen during the same test, though it did frequently.

After inspecting the Event Viewer on the build machines, we found an error in the .NET Runtime that was taking down the build agent:

Application: QTAgent32_40.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: Moq.MockException
Stack:
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__5(System.Object)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
The exception that was being thrown on a ThreadPoolThread (always extremely bad, never good) was a MockException: our unit testing framework was throwing an exception that was taking down the build agent.  But where?

How We Solved It

By some miracle, one of our developers decided to run our problematic tests with mstest on the command line on his local machine. As it turns out, this was great because it showed the stack traces for the loose threads on the command line. Turns out we had a lot more loose threads than just the one that was taking down our test agent on the build machine. The command the developer used was (similar to) the following:

mstest.exe /testcontainer:"C:\path\to\my\test.dll" /noisolation

After auditing all of the errors by rooting them out with command line runs of mstest, the solutions to our problems all boiled down to one thing:

*ALWAYS* wrap the contents of 'async void' methods with a try-catch block!

Thursday, January 22, 2015

Implementing a WCF service on an Active Directory domain using a ServiceHost in a Windows Service with Windows authentication and a non-system user service account

So, as it turns out, when you want to implement a WCF service on an Active Directory domain using a ServiceHost in a Windows Service with Windows authentication and a non-system user service account, you have to jump through a few hoops for the configuration. I kept getting the error message "A call to SSPI failed. see inner exception". The inner exception is "The target principal name is incorrect.". Like many other people, I kept thinking it had to do with authentication of the *client*. As it turns out, like those other people, I was wrong. It was to do with *verification of the service account running the service*. This is presumably because the *service user is a domain user service account*. To get this scenario working, you have to specify the name of the service user account as the 'userPrincipalName' in the 'identity' element of the 'endpoint' element for your service, like so:

<configuration>
<system.serviceModel>
<services>
<service name="MyProject.MyService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:12345/MyService"/>
</baseAddresses>
</host>
<endpoint name="MyServiceTcpEndpoint"
 address=""
 binding="netTcpBinding"
 bindingConfiguration="MyServiceTcpBinding"
 contract="MyProject.IMyService">
<identity>
<userPrincipalName value="MyDomainName\MyServiceUserName"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="MyServiceTcpBinding"
transferMode="Buffered"
maxReceivedMessageSize="65535">
<security mode="Transport">
<!-- Use Windows authentication to ensure that we at least have authentication if not encryption -->
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
Now you'll get proper connections and authentication via Windows.

Adding files generated at build time to your ClickOnce deployment

So, it used to be that I didn't really like ClickOnce deployment, but it turns out it has a lot of benefits:

  • It provides infrastructure that makes it *exceedingly* easy for your average lay-user to upgrade. All they have to do is start the program as normal, and it automatically updates for them (when configured properly)
  • It bundles everything up nicely and is easy to install and uninstall (if you're a real person. If you're a script, not so much)
I recently encountered the problem of including files generated at build time (e.g. transformed configuration files) in the ClickOnce deployment package. I found the following that I could include in my ClickOnce project's .csproj MSBuild file:

 <Content Include="Path\To\My.file" Condition=" Exists('Path\To\My.file') ">
<Visible>false</Visible>
 </Content>
 The key part to getting it to work properly is that your build has to do a Build target first, then a Publish target (usually with two separate invocations of MSBuild via a build script, rather than building with a Solution). Fortunately, I was already set up for that, so getting the extra files included was a dream.

Friday, January 16, 2015

Querying XML with namespaces in PowerShell

Apparently it's ridiculously easy to parse XML in PowerShell once you have the right objects set up:

[xml] $xml = Get-Content .\DeploymentProfile.PRODUCTION.xml
$ns = new-object Xml.XmlNamespaceManager $xml.NameTable
$ns.AddNamespace('dns', 'http://www.mycompany.com/Some/Namespace/Deployment/DeploymentProfiles.xsd')
$xml.SelectNodes("//@dns:ServerHostName", $ns) | ForEach-Object { $_.Value } | sort | Get-Unique

In this example, I query a deployment configuration for attributes called "ServerHostName" within the XML namespace "http://www.mycompany.com/Some/Namespace/Deployment/DeploymentProfiles.xsd". This was exceptionally useful today when I quickly needed to figure out what servers my system was using and send that information to others to configure those servers.

Implementing Code Analysis with Team Foundation Server 2012 and later

I've been looking to get Code Analysis going on our team project at work. I found this helpful MSDN article.

Adding a computer to the local machine's list of PowerShell TrustedHosts

Retrieve the current list:

$curValue = (get-item wsman:\localhost\Client\TrustedHosts).value

Set the new list, appending the new host onto the old list:

set-item wsman:\localhost\Client\TrustedHosts -value "$curValue, Server01.Domain01.Fabrikam.com"

Tuesday, December 09, 2014

Things I've learned (forcibly) on 2014-12-09


  1. There are database systems that are actually implemented using the Julian (sort of) calendar. Why ?!
  2. It is perfectly legitimate to use script types other than type="text/javascript" in a

Saturday, December 06, 2014

Adding less to your MVC 5 project

I'm going to have to just redirect to this post, because I'm in a rush. Hopefully it's still around when you read this.

Note: In order to get this to work, I had my application pool running in 'Integrated Pipeline Mode' and IIS 8 didn't like that, so I had to get rid of the system.web/httpHandlers sections for the dotLess configuration.

Wednesday, November 26, 2014

Creating Azure Services with Visual Studio 2013 and Windows 8.1


  1. Download and install Visual Studio 2013
  2. Download and install the Web Platform Installer, v5.0 or greater
  3. From the Web Platform Installer, install:
    1. Windows Azure SDK and related Powershell utilities and command line tools
  4. Start a new solution (or open an existing one)
  5. From the NuGet package manager in your solution, ensure that you've installed the 'WindowsAzure.Storage' package, or at least have it in your cache. This is going to be required by the New Project wizard when generating the project.
  6. Add a new project
  7. In the 'Add new project' wizard, select the C# projects -> Cloud -> Windows Azure Cloud Service
  8. Follow this absurdly easy tutorial on implementing an ErrorHandler interceptor (behavior)
  9. Add logging to your application using the Microsoft Patterns & Practices Enterprise Library Logging Application Block (which can be found here). 
  10. Create a SQL server database in Azure using this tutorial on MSDN. When designing the user roles and authentication, it's recommended that you use the ASP.NET Identity membership design and design your tables accordingly around this.
    1. Microsoft has provided an extension to the ASP.NET Identity membership framework specifically for EntityFramework. They recommend that you use a code-first model for generating entities.
    2. Log in to Azure through the management portal: http://manage.windowsazure.com/
    3. Configure all of your connections and permissions to the database. e.g. you may want to have multiple users: one for read-only operations, another for read-write operations.
    4. Generate or write your data model. This article will show you how to create a code-first data model with Entity Framework. Ensure that you include users so that you can support proper application authentication and authorization via the ASP.NET Identity membership framework.
    5. The link above also includes instructions on using code-first migrations for when you update your data model.
    6. TODO: Elaborate on how to properly set up the database when performing a code-first database design
  11. Add an IoC container to your WCF service to enable you to easily develop and unit test it. I've chosen to use Ninject because despite a few minutes of inital frustration, it's actually exceedingly easy to integrate with WCF, especially now that there's the Ninject WCF extensions NuGet package. To integration Ninject with your WCF service, perform the following steps:
    1. Install-Package Ninject.Extensions.Wcf -Version 3.2.1.0 (Ninject and Ninject.Web.Common are installed as dependencies for you automatically).
    2. Create a NinjectModule descendant to bind your interfaces to concrete implementations. It should look something like the following:
      namespace MyService.CloudStorage.Support
      {
          using System.Diagnostics.CodeAnalysis;
          using System.ServiceModel;
          using Common.Interfaces;
          using global::Ninject.Modules;
          using global::Ninject.Syntax;
          using Services;
          using NinjectServiceHost = global::Ninject.Extensions.Wcf.NinjectServiceHost;
      
          /// <summary>
          /// A <see cref="NinjectModule"/> descendant for bootstrapping our application
          /// </summary>
          public class MyServiceCloudStorageNinjectModule : NinjectModule
          {
              /// <inheritdoc/>
              [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1604:ElementDocumentationMustHaveSummary", Justification = "InheritDoc")]
              public override void Load()
              {
                  this.Bind<IResolutionRoot>().ToConstant(Kernel);
                  this.Bind<ServiceHost>().To<NinjectServiceHost>();
                  this.Bind<IMyServiceStorage>().To<MyServiceStorage>();
                  this.Bind<ILoggingService>().To<MicrosoftEnterpriseLoggingBlockLoggingService>();
              }
          }
      }
      
    3. Create a Global Application Class (global.asax) if one's not already created: Right-click on your project -> Add -> New Item ... and in the window that comes up, go to Visual C# -> Web -> Global Application File
    4. Update your Global class to extend from Ninject.Web.Common.NinjectHttpApplication and override the CreateKernel() method and return a new CustomNinjectModule (as created above). The method should look something like this:
      namespace MyService.CloudStorage
      {
          using System.Diagnostics.CodeAnalysis;
          using System.Web;
          using Ninject;
          using Ninject.Web.Common;
          using Support;
      
          /// <summary>
          /// A global <see cref="HttpApplication"/> class for managing the lifecycle
          /// of the application
          /// </summary>
          public class Global : NinjectHttpApplication
          {
              /// <inheritdoc/>
              [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1604:ElementDocumentationMustHaveSummary", Justification = "InheritDoc")]
              [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1615:ElementReturnValueMustBeDocumented", Justification = "InheritDoc")]
              protected override IKernel CreateKernel()
              {
                  return new StandardKernel(new NinjectSettings(), new MyServiceCloudStorageNinjectModule());
              }
       }
      }
      
    1. Update your .svc file for your service(s) and add an extra XML attribute that looks like this: <%@ ServiceHost Service="HelloNinjectWcf.Service.GreetingService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
  12. Implement your business logic
    1. If you're designing your service properly, you'll need to ensure that communications between clients and your service are secure. Toward that end, you'll need to use SSL to encrypt your communications. There's a number of things involved in this:
      1. Generate certificates for your server and your client
      2. Ensure that your IIS server is correctly configured to use 'https' bindings on your site, along with the server-side certificate that you've generated.
      3. If you're using Windows Store Apps to access a WCF service, you'll need to ensure that you use a CustomBinding correctly configured with the right *BindingElement objects to create an SSL secured, HTTPS-transported binding.
        • For the server, in your service's concrete implementation, you'll need to remove any .config file configuration, and add a method specified according to a convention that WCF recognizes that looks like the following:
          /// <summary>
          /// The service certificate store name
          /// </summary>
          private const StoreName ServiceCertificateStoreName = StoreName.My;
          
          /// <summary>
          /// The service certificate store location
          /// </summary>
          private const StoreLocation ServiceCertificateStoreLocation = StoreLocation.LocalMachine;
          
          /// <summary>
          /// Configures the specified configuration.
          /// </summary>
          /// <param name="config">The configuration.</param>
          /// <remarks>
          /// A service endpoint configuration method determined by convention.
          /// <see href="http://msdn.microsoft.com/en-us/library/hh205277(v=vs.110).aspx"/>
          /// </remarks>
          public static void Configure(ServiceConfiguration config)
          {
           ServiceEndpoint serviceEndpoint = new ServiceEndpoint(
            ContractDescription.GetContract(typeof(IMyServiceStorage), typeof(MyServiceStorage)), 
            new CustomBinding(
             new TransportSecurityBindingElement(),
             new SslStreamSecurityBindingElement { RequireClientCertificate = false },
             new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8),
             new HttpsTransportBindingElement()
            ), 
            new EndpointAddress("https://localhost/MyService.CloudStorage/MyServiceStorage.svc")
           );
          
           config.AddServiceEndpoint(serviceEndpoint);
          
           const string ServiceCertificateThumbprint = "[a 40 digit hexadecimal certificate thumbprint here]";
          
           X509Store certificateStore = new X509Store(ServiceCertificateStoreName, ServiceCertificateStoreLocation);
          
           certificateStore.Open(OpenFlags.ReadOnly);
          
           X509Certificate2Collection x509Certificate2Collection = certificateStore.Certificates.Find(
            findType: X509FindType.FindByThumbprint,
            findValue: ServiceCertificateThumbprint,
            validOnly: false
            );
          
           certificateStore.Close();
          
           X509Certificate2 serviceCertificate = x509Certificate2Collection.Cast<X509Certificate2>().FirstOrDefault();
          
           if (serviceCertificate == null)
           {
            throw new ConfigurationErrorsException(String.Format("No certificate representing the service with thumbprint {0} could be found in {1} store at {2} location", ServiceCertificateThumbprint, ServiceCertificateStoreName, ServiceCertificateStoreLocation));
           }
          
           ServiceCredentials serviceCredentials = new ServiceCredentials
           {
            IdentityConfiguration = new IdentityConfiguration
            {
             // TODO: Change this to authenticate the clients
             CertificateValidationMode = X509CertificateValidationMode.None
            },
            ServiceCertificate =
            {
             Certificate = serviceCertificate
            }/*,
            ClientCertificate =
            {
             // TODO: Resolve the client certificate
             Certificate = serviceCertificate
            }*/
           };
          
           config.Description.Behaviors.Add(serviceCredentials);
           // config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpsGetEnabled = true });
          }
          

        • For the Windows Store App client, you'll need to have a similarly configured counterpart channel factory and binding for connecting to the service:
          this.channelFactory = new ChannelFactory<IMyServiceStorageChannel>(
           binding: new CustomBinding(
            new TransportSecurityBindingElement(),
            new SslStreamSecurityBindingElement(),
            new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8),
            new HttpsTransportBindingElement()
           ),
           remoteAddress: new EndpointAddress(serviceUri)
          );
          
          this.passwordVault = new PasswordVault();
          
          // This IDispatchMessageInspector is a custom addition for our own brand of authentication
          this.channelFactory.Endpoint.EndpointBehaviors.Add(new ClientAuthenticationDispatchMessageInspector(this.passwordVault));
          
        • For the Windows Store App, you'll also need to have the server's public key (assuming it's not trusted, e.g. a self-signed certificate) added to the app's certificate declarations in the package manifest. There's a video on how to do it here on Channel 9. For the sake of convenience, I'll reproduce the steps here:
          1. Obtain your server's public key in DER-encoded .cer format.
          2. Open the Package.appxmanifest file for your App in Visual Studio
          3. Go to the Declarations tab.
          4. Under the 'Available Declarations' box, select 'Certificates' and click 'Add' if there's no Certificates declaration already added.
          5. Select the 'Certificates' declaration in the 'Supported Declarations' box.
          6. In the 'Certificates' group on the large pane, click 'Add New'.
          7. In the certificate parameters box that comes up, enter 'Root' in the 'Name' field, and select your public key file. Once you do this, Visual Studio will automatically import it into your project.
          8. Save the manifest.
  13. Publish it to Azure Services
    1. If you've designed your application correctly, you'll be using HTTPS for communicating with your clients. Read Microsoft's guide on MSDN to uploading a certificate with your service.
  14. Implement your Windows 8.1 client // TODO: Elaborate on this
  15. Unit test your Windows 8.1 client on your own local machine.
    1. Visual Studio 2012 / .NET 4.5 added the ability to do asynchronous unit tests to MSTest!
    2. In order to unit test the Windows 8.1 Metro client against services on your localhost, you'll have to read this. It describes the new security features in Windows 8(.1) and how to explicitly enable your application to communicate through the network loopback interface. 
    3. You can also read this. Bottom line, you have to ensure that you enable a loopback exemption for your unit tests.
  16. Unit / integration test it against your Azure service
    1. Ensure that you've created a 'Staging' area in your Azure configuration panel and you're not testing against production! Testing against production is extremely poor practice!
  17. Publish your App on the Windows Store if you so choose


Tuesday, October 28, 2014

Correcting the default check-in action for associated work items in Team Foundation Server

I've found that it's a giant pain in the ass in TFS when associating work items to checkins because the default assocation action is 'Resolve' rather than 'Associate'. When I'm working on features, I like to do bits of functionality in units and check them in to source control in small batches to make my changes more manageable. Unfortunately, many times I've forgotten to change the association action when associating work items with change sets and it's resolved my issue instead of just associating the work item with the change set. This becomes problematic because it skews my records and metrics for how much time is spent working on a task. Fortunately one can change this in the registry:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\[Version Number]\TeamFoundation\SourceControl\Behavior

Quick fix.