tag:blogger.com,1999:blog-26124799011767675012024-03-14T00:27:29.894+13:00Blog.Rees.Biz<br><br><br><br>
Welcome to my blog site. This is my notepad and soap-box of ramblings on all things .Net. Ascendancy to simplicity is a long and complicated journey.Benhttp://www.blogger.com/profile/13689311571100426106noreply@blogger.comBlogger208125tag:blogger.com,1999:blog-2612479901176767501.post-43264030097677367592016-09-14T21:58:00.002+12:002016-09-14T21:58:55.392+12:00Accessing an authenticated S3 file in Xamarin<h2>
Context</h2>
I have a S3 JSON file that I need to access from a Xamarin Forms mobile application. My S3 resource is not a public resource, its protected and requires credentials to be able to access it. There is another Windows Desktop application that will upload this file periodically, and the mobile app must only have read only access to the file.<br />
<br />
Note: no special authentication is required to access public (unprotected) S3 files.<br />
<br />
<h2>
Setting up S3 and Credentials</h2>
<div>
The AWS portal offers a <a href="https://aws.amazon.com/free/">free plan</a> to store up to 5GB of storage for 12 months. After that it'll depend on number of requests and storage size. For me, for a 100Kb file accessed maybe 100 times a month, it'll be approximately 5 cents per month based on the <a href="https://calculator.s3.amazonaws.com/index.html">calculator</a>.</div>
<div>
<br /></div>
<div>
To access protected (non-public) data in S3 you'll need to set up users and access tokens.</div>
<div>
Users are created with the AWS IAM service. This is a pretty straight forward process, I needed two users, one with full access, and one with read only access. To do this you need to attach an appropriate policy to the user, the read only policy is shown here:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-FDO5OljkG_0/V9kOjSzGW7I/AAAAAAAAHuA/abGaLCFHwQkAhP4C0fSoRaBrEbkLd6qIwCLcB/s1600/AWS%2BIAM.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="102" src="https://3.bp.blogspot.com/-FDO5OljkG_0/V9kOjSzGW7I/AAAAAAAAHuA/abGaLCFHwQkAhP4C0fSoRaBrEbkLd6qIwCLcB/s320/AWS%2BIAM.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
Once this policy is attached, user will have read only access to everything stored in the S3 account. </div>
<div>
The next step is to generate an access token. This is done with the Security Credentials tab.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-v1tELMOEqTE/V9kPZfEIcFI/AAAAAAAAHuE/p0BAd83tZrE0adEMWujvg6pHvgvKp2WjwCLcB/s1600/AccessToken.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="215" src="https://4.bp.blogspot.com/-v1tELMOEqTE/V9kPZfEIcFI/AAAAAAAAHuE/p0BAd83tZrE0adEMWujvg6pHvgvKp2WjwCLcB/s320/AccessToken.PNG" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Managing Files in S3</h3>
<div>
Again this is very simple so not much detail here. There are a couple of basics to be aware of. You first choose where your data is stored geographically (ie Sydney, Oregon, Tokyo to name a few) and is not mirrored between regions (but this can be set up). Data is stored inside "Buckets" - think folder. Although you can't nest. Files can then be uploaded and accessed inside these buckets.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-7iwI2S8HyE0/V9kRICPZHZI/AAAAAAAAHuY/5kx7q14eFe84tIcQvKEsIfEPqv1CShKGgCLcB/s1600/S3%2BConsole.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="46" src="https://1.bp.blogspot.com/-7iwI2S8HyE0/V9kRICPZHZI/AAAAAAAAHuY/5kx7q14eFe84tIcQvKEsIfEPqv1CShKGgCLcB/s320/S3%2BConsole.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
The red line is obscuring my chosen bucket name (because its top secret), and you can see the file name shown in the list.</div>
<div>
<br /></div>
<h2>
Using the AWS S3 SDK</h2>
Writing a C# desktop application is pretty easy with the AWS SDK, certainly no challenges. <br />
<br />
To be able to access the file created above here's all we need:<br />
<pre style="background: url("http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif") rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828px;"><code style="word-wrap: normal;"> private const string AwsBucketName = "XXXXXXXXXsummary";
private const string AwsBucketFileName = "MobileDataExport.json";
public async Task UploadDataFileAsync(string data, string storageKeyId, string storageSecret, string region)
{
var regionIdentifier = RegionEndpoint.GetBySystemName(region);
using (var client = new AmazonS3Client(storageKeyId, storageSecret, regionIdentifier))
{
try
{
var response = await client.GetObjectAsync(AwsBucketName, AwsBucketFileName);
using (var reader = new StreamReader(response.ResponseStream))
{
Debug.WriteLine(await reader.ReadToEndAsync());
}
}
catch (AmazonS3Exception amazonS3Exception)
{
if (amazonS3Exception.ErrorCode != null &&
(amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
{
throw new SecurityException("Invalid Amazon S3 credentials - data was not uploaded.", amazonS3Exception);
}
throw new HttpRequestException("Unspecified error attempting to upload data: " + amazonS3Exception.Message, amazonS3Exception);
}
} </code></pre>
<br />
<ul>
<li>storageKeyId is the access token generated earlier. AWS IAM calls this the Access Key ID.</li>
<li>storageSecret is the access token secret generated ealier. AWS IAM calls this the Secret Access Key.</li>
</ul>
<div>
Easy, huh. <br />
<br />
The bad news, is that this doesn't work in Xamarin, as the AWS SDK has an incomplete portable class library port. If you try to use the SDK in a PCL or a Xamarin native project you will get NotImplementedExceptions.</div>
<br />
<br />
<h2>
AWS Mobile Recommended Approach</h2>
AWS recommend you use their <a href="https://aws.amazon.com/cognito/">Cognito </a>service to authenticate for Mobile and for Xamarin. There's a good set of instructions here:<br />
<a href="http://docs.aws.amazon.com/mobile/sdkforxamarin/developerguide/setup.html">http://docs.aws.amazon.com/mobile/sdkforxamarin/developerguide/setup.html</a><br />
<br />
There's a couple of issues with this however. At the time of writing the docs are a little out of date and don't match the Cognito console web site, which makes things a little difficult to follow. (I have sent them feedback on this issue). <br />
Also, more importantly, AWS Cognito is currently only available in the US East (N. Virginia), EU (Ireland), and Asia Pacific (Tokyo) regions. This doesn't work for me as I need to use AWS Sydney.<br />
<br />
<h2>
The Solution</h2>
Fortunately, AWS does have some comprehensive instructions how to craft and pass in the right HTTP headers so you can do everything yourself. Also, its worth noting that <a href="https://www.getpostman.com/">Postman</a> supports AWS authentication natively which is pretty handy for testing and to see example requests.<br />
<br />
<a href="http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html">The AWS Roll Your Own Headers Instructions</a><br />
<br />
This approach, I think, has a couple of redeeming attributes: Its lightweight, and no extra dependencies are required. Its also easy to take the headers and use your favourite REST testing tool.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: 600px; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> using System;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using BAXMobile.Model;
using JetBrains.Annotations;
using Newtonsoft.Json;
namespace BAXMobile.Service
{
public class AmazonS3BaxSummaryDataService : IBaxSummaryDataService
{
private readonly IHashingAlgorithm hashingAlgorithm;
private readonly string accessKey;
private readonly string secret;
private const string TargetAwsRegion = "ap-southeast-2";
private const string TargetAwsService = "s3";
private const string Aws4HasingAlgorithm = "AWS4-HMAC-SHA256";
private const string Aws4Request = "aws4_request";
private const string Host = "XXXXXXXXsummary.s3-ap-southeast-2.amazonaws.com";
private static string resourcePath = "/MobileDataExport.json";
public AmazonS3BaxSummaryDataService([NotNull] IHashingAlgorithm hashingAlgorithm, [NotNull] string accessKey, [NotNull] string secret)
{
if (hashingAlgorithm == null) throw new ArgumentNullException(nameof(hashingAlgorithm));
if (accessKey == null) throw new ArgumentNullException(nameof(accessKey));
if (secret == null) throw new ArgumentNullException(nameof(secret));
this.hashingAlgorithm = hashingAlgorithm;
this.accessKey = accessKey;
this.secret = secret;
}
public async Task<SummarisedLedgerMobileData> DownloadDataAsync()
{
string jsonData;
// following instructions from http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Get, "https://" + Host + resourcePath))
{
var dateTime = DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ");
var date = DateTime.UtcNow.ToString("yyyyMMdd");
client.BaseAddress = new Uri("https://" + Host);
var requestPayloadHash = CalculateHash(string.Empty); // My request, as its a GET, will be empty, so hash an empty string. Yep thats correct.
var canonicalisedResource = GetCanonicalisedResource(Host, dateTime, requestPayloadHash);
var hashedCanonicalisedRequest = CalculateHash(canonicalisedResource);
var stringToSign =
$"{Aws4HasingAlgorithm}\n"
+ $"{dateTime}\n"
+ $"{date}/{TargetAwsRegion}/{TargetAwsService}/{Aws4Request}\n"
+ hashedCanonicalisedRequest;
var signature = GetSignatureKey(this.secret, date, TargetAwsRegion, TargetAwsService, stringToSign);
var authHeaderString = $"{Aws4HasingAlgorithm} Credential={this.accessKey}/{date}/{TargetAwsRegion}/{TargetAwsService}/{Aws4Request}, SignedHeaders=host;x-amz-date, Signature={signature}";
request.Headers.Host = Host;
request.Headers.Add("X-Amz-Date", dateTime);
request.Headers.Add("X-Amz-Content-Sha256", requestPayloadHash);
request.Headers.TryAddWithoutValidation("Authorization", authHeaderString);
// Note that Content-Type cannot be added to GET request using HttpClient - using Content-Type does seem to be common in examples found on the web including GET requests.
var response = await client.SendAsync(request);
jsonData = await response.Content.ReadAsStringAsync();
}
return JsonConvert.DeserializeObject<SummarisedLedgerMobileData>(jsonData);
}
private string CalculateHash(string canonicalisedResource)
{
return ToHex(hashingAlgorithm.ComputeSha256Hash(Encoding.UTF8.GetBytes(canonicalisedResource)));
}
private string GetCanonicalisedResource(string host, string date, string requestPayloadHash)
{
var canonicalisedResource = "GET\n" // Http Request Method
+ $"{resourcePath}\n" // Url to file
+ "\n" // Query string - blank in this case
+ $"host:{host}\n"
+ $"x-amz-date:{date}\n\n"
+ "host;x-amz-date\n" // headers that will be included in the request and signature calc
+ requestPayloadHash; // Hashed payload of the request - in my case empty string
return canonicalisedResource;
}
private string ToHex(byte[] data)
{
string hex = BitConverter.ToString(data);
return hex.Replace("-", "").ToLower();
}
private byte[] HmacSha256(string data, byte[] key)
{
return this.hashingAlgorithm.ComputeHmacSha256Hash(data, key);
}
private string GetSignatureKey(string key, string dateStamp, string regionName, string serviceName, string stringToSign)
{
var secret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
var date = HmacSha256(dateStamp, secret);
var region = HmacSha256(regionName, date);
var service = HmacSha256(serviceName, region);
var derivedSigningKey = HmacSha256(Aws4Request, service);
var signature = ToHex(HmacSha256(stringToSign, derivedSigningKey));
return signature;
}
}
}
</code></pre>
<br />
The AWS Access Key and its Secret are passed into the function.<br />
I also pass in a IHashingAlgorithm. While .NET does have the correct SHA hashing classes these classes are <a href="http://stackoverflow.com/questions/7794446/is-system-security-cryptography-namespace-supported-by-the-portable-class-librar">not available</a> in PCL. However they are available in Mono, so using Dependency Injection, you can defer the hashing to the iOS or Android projects.<br />
<br />
<pre style="background: url("http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif") rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828px;"><code style="word-wrap: normal;"> //Note: System.Security.Cryptography is not PCL compliant and cannot be used in any PCL. But, it can be used from the Android project because a port of it is available in Mono.
public interface IHashingAlgorithm
{
byte[] ComputeSha256Hash(byte[] data);
byte[] ComputeHmacSha256Hash(string data, byte[] key);
} </code></pre>
<br />
<pre style="background: url("http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif") rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828px;"><code style="word-wrap: normal;"> public class AndroidHashingAlgorithm : IHashingAlgorithm
{
private static readonly SHA256 HashingFunction = SHA256.Create();
public byte[] ComputeSha256Hash(byte[] data)
{
return HashingFunction.ComputeHash(data);
}
public byte[] ComputeHmacSha256Hash(string data, byte[] key)
{
var algorithm = "HmacSHA256";
var kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
} </code></pre>
<br />
Hope that helps someone.<br />
<br />Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-45841718391647075582016-07-25T22:45:00.000+12:002016-07-25T22:58:18.254+12:00Android xbuild: 'OutputPath' property is not set<h3>
Background</h3>
My team and I are building a Xamarin Forms mobile application that includes iOS and Android projects. I've set up automated CI builds and I've created some custom build configurations for CI and Production (Store) builds. The idea is to use one solution level build configuration that configures both iOS and Android projects appropriately with one build script.<br />
<br />
Here's the Ad-hoc (deploy to test devices) Build Config:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-KdFNoEgo2uM/V5XevEMgJCI/AAAAAAAAG5o/-wc4unonT90gtXliNa7D0qFhT0CsCzlNwCLcB/s1600/BuildCOnfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://3.bp.blogspot.com/-KdFNoEgo2uM/V5XevEMgJCI/AAAAAAAAG5o/-wc4unonT90gtXliNa7D0qFhT0CsCzlNwCLcB/s400/BuildCOnfig.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
(The first project is the <a href="https://msdn.microsoft.com/en-us/library/gg597391(v=vs.110).aspx">PCL</a> which simply the App name with no suffix).</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Here's the Production (Store) Build Config:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-flwQOPrn0_0/V5Xgo0OxmII/AAAAAAAAG50/KnpruhCiAvUHVuepWq-4O9Odee1U-iWXQCLcB/s1600/StoreBuildCOnfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://3.bp.blogspot.com/-flwQOPrn0_0/V5Xgo0OxmII/AAAAAAAAG50/KnpruhCiAvUHVuepWq-4O9Odee1U-iWXQCLcB/s400/StoreBuildCOnfig.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />
This all works great in Visual Studio. But not in <a href="https://www.bitrise.io/">Bitrise </a>(my chosen online mobile build system).<br />
<br />
<h3>
The Error Message</h3>
Here's the command line used to build the Android project extracted from the build output in Bitrise:<br />
<span style="background-color: #34495e; color: #2980b9; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">xbuild /t:PackageForAndroid /p:Configuration"PlayStore" "./XXXXXXXX/XXXXXXXX.Droid/XXXXXXXX.Droid.csproj" /verbosity:minimal /nologo</span><br />
<br />
Within a few seconds produces this error message.<br />
<span style="background-color: #34495e; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">/Library/Frameworks/Mono.framework/Versions/4.4.0/lib/mono/4.5/Microsoft.Common.targets: error : 'OutputPath' property is not set for this project. Usually this is caused by invalid Configuration/Platform combination. Original values: Configuration: PlayStore Platform: AnyCPU.</span><br />
<br />
There's been reports of this error on the <a href="http://forums.xamarin.com/discussion/comment/73222">Xamarin Forums</a> (and <a href="http://forums.xamarin.com/discussion/31250/outputpath-property-is-not-set-for-this-project-xamlsamples">here</a>) that include other build system like <a href="https://jenkins.io/">Jenkins</a>. It looks like there has been bugs in xbuild and Xamarin Studio that have been investigated and fixed. So its no fault of Bitrise.<br />
<div>
<br /></div>
<div>
The build is given "AppStore" as the target build config, and "RealDevices" as the platform. The solution file is successfully parsed and based on what we can see from the command line above, it has passed the right target and platform to xbuild (see Store Build Config screenshot above).<br />
<div>
<br /></div>
<div>
The iOS project builds fine.<br />
<br /></div>
</div>
<h3>
The diagnostic process on Bitrise</h3>
<div>
It seems unlikely that the bugs discussed in the forum posts mentioned above are still a problem, the posts are dated some time ago. The suggestions center around App code problems rather than real bugs with Xamarin or Mono.<br />
<br />
Bitrise only offers limited options to pass parameters to the Xamarin-Builder step. Basically only build configuration, platform, and solution path. This is where their generic Script step comes in handy. Delete the Xamarin-Builder step and replace it with the Script step and use the command line to invoke xbuild directly:</div>
<div>
<br /></div>
<div>
<span style="background-color: #34495e; color: #2980b9; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">xbuild /t:PackageForAndroid /p:Configuration="PlayStore" /p:Platform="AnyCPU" "./XXXXXX/XXXXXXXX.Droid/XXXXXXXX.Droid.csproj" /verbosity:detailed /nologo /p:OutputPath="bin/PlayStore"</span><br />
<br />
This produced the same results, with nothing new of value.</div>
<div>
Running it locally on a Mac also produced the same results.</div>
<div>
<br /></div>
<div>
I then realised that because the build of the Android project is triggered with a build config of "PlayStore" it is passing this value to the its dependency the PCL project. But its supposed to be built in "Store" config according to the solution file. It doesn't have a config in it's csproj file named "PlayStore" hence the error.</div>
<div>
<br /></div>
<h3>
The Solution</h3>
<div>
xbuild is not building the solution in the same was as msbuild, Visual Studio or Xamarin Studio. It is using the Android csproj file as its entry point not the solution file. So the Build Config name provided to build the Android project has to be the same Config name provided to build the PCL.</div>
<div>
<br />
I added a "PlayStore" Build Config to the PCL and bingo. </div>
<div>
The only downside is that I have two Build Configs to maintain for the PCL: PlayStore and AppStore.</div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-85121322780940086262016-07-21T20:46:00.000+12:002016-07-21T20:46:46.847+12:00AndroidDeploymentException: [INSTALL_FAILED_UPDATE_INCOMPATIBLE]Xamarin.AndroidTools.AndroidDeploymentException: InternalError ---> Mono.AndroidTools.InstallFailedException: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]<br />
<br />
I've come across this problem several times with different physical Android devices. This message is thrown when a real production Google Play App with the same App Id has been installed and then you try to install a debug version. It will happen with any means of deploying a debug version including with Visual Studio, Xamarin Studio, and the command tools.<br />
<br />
I think what is happening is that Android is not happy with a debug version being deployed over the top of a properly signed and deployed version of a Play Store App. Android stores a flag to block further install attempts for that App Id. When an App deployment attempt is made, the flag that Android created is not reset.<br />
<br />
To fix this, you will need to reinstall the App from Google Play and then uninstall it normally. After that you'll be able to debug your App with Visual Studio.<br />
<br />Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-36267578487825751252016-07-19T18:01:00.001+12:002016-07-19T18:01:44.274+12:00How to create a signed and aligned APK using Visual StudioThis article guides you through creating an APK file for your Xamarin.Android App that is ready to publish on Google Play.<br />
<br />
Creating an Android APK that is signed and aligned can mostly be achieved with Visual Studio. To sign it and align it, command line tools must be used, but the APK can be created with Visual Studio.<br />
<br />
You're App does need to be signed to be submitted to Google Play, but it doesn't necessarily need to be "<a href="https://developer.android.com/studio/command-line/zipalign.html">aligned</a>". It is highly recommended however. Its basically a very cheap optimisation that will minimise the amount of RAM your App will need at runtime.<br />
<br />
<h3>
Step 1 - Prepare your App for Release</h3>
<div>
This is out of scope for this article. Check out this link:</div>
<div>
<a href="https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/part_1_-_preparing_an_application_for_release/">Xamarin Guide</a></div>
<h3>
Step 2 - Build a Release build of your App</h3>
Build your Android App in Release Mode. Ensure the platform drop down is set to "Any CPU".<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-2sk9iTti8SA/V424CYM1XpI/AAAAAAAAG1o/e1u2kjvTLu4XjHKZDddZAYFDxCp0KH3AwCLcB/s1600/VisualStudioReleaseBuild.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="268" src="https://4.bp.blogspot.com/-2sk9iTti8SA/V424CYM1XpI/AAAAAAAAG1o/e1u2kjvTLu4XjHKZDddZAYFDxCp0KH3AwCLcB/s400/VisualStudioReleaseBuild.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Step 3 - Export to APK</h3>
<div class="separator" style="clear: both; text-align: left;">
This does not automatically occur when you build a Release build. Creating the APK must be triggered manually by selecting a context menu item when you right click the Android Project in Solution Explorer.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-IbXTL1wXPF8/V4245wjdmXI/AAAAAAAAG10/zegwhNkr7jYJvacTm7soZPVo_FbccXhxwCLcB/s1600/VisualStudioExportApk.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="https://3.bp.blogspot.com/-IbXTL1wXPF8/V4245wjdmXI/AAAAAAAAG10/zegwhNkr7jYJvacTm7soZPVo_FbccXhxwCLcB/s400/VisualStudioExportApk.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The APK will be created in your bin\Release\ folder for the Android project.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-5nPwU3GjEqQ/V428vLSLZwI/AAAAAAAAG2I/yjy73HN2XMcNym6T92qXe1gzBNB-fhQ0wCLcB/s1600/FileExplorer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="135" src="https://1.bp.blogspot.com/-5nPwU3GjEqQ/V428vLSLZwI/AAAAAAAAG2I/yjy73HN2XMcNym6T92qXe1gzBNB-fhQ0wCLcB/s320/FileExplorer.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Step 4 - Sign the APK</h3>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://developer.android.com/studio/publish/app-signing.html">Google Reference</a></div>
Ensure you have the JDK path in your environment Path variable. My JDK is installed here:<br />
<span style="font-family: Courier New, Courier, monospace;">C:\Program Files (x86)\Java\jdk1.7.0_55\bin</span><br />
<br />
The "signed" file you see in the folder has been automatically signed with a Developer certificate. This isn't suitable for publishing purposes, so you'll need a certificate that identifies you as a developer.<br />
<br />
To sign your APK, you'll need your Java KeyStore (JKS) file. These files usually have a JKS extension or a keystore extension. If you don't have one you can create one using the instructions in the Google reference above. In summary the command line is: <span style="font-family: Courier New, Courier, monospace;">keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000</span><br />
<br />
Once you have a JKS file you need to keep it in a safe place you must use the same file to sign your App everytime. This file uniquely identifies you as a developer.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.jks my_application.apk alias_name</span><br />
<br />
There are three things you need to specify in this command: <br />
Replace "<span style="font-family: Courier New, Courier, monospace;">my-release-key.jks</span>" with the filename to your JKS file.<br />
Replace "my_application.apk" with your app's APK filename.<br />
Replace the "alias_name" with the alias name you used when creating your JKS file.<br />
You'll also be prompted for the keystore password.<br />
<br />
<h3>
Step 5 - Align the APK</h3>
Finally use the Zipalign tool to optimise your APK file.<br />
Zipalign isn't in the same folder as the JDK, for me its in the Android tools folder here:<br />
<span style="font-family: Courier New, Courier, monospace;">C:\Program Files (x86)\Android\android-sdk\build-tools\22.0.1</span><br />
This also should be added to your environment path if it isn't already.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">zipalign -v 4 my_application.apk my_application_aligned.apk</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
That's it.Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-41586731766208343612016-07-19T11:46:00.001+12:002016-07-19T11:47:31.115+12:00Verify an APK is signed with correct certificateHow do I determine if the APK produced by the build system has been signed correctly with the production certificate?<br />
<br />
<pre class="default prettyprint prettyprinted" style="background-color: #eff0f1; border: 0px; color: #393318; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 13px; margin-bottom: 1em; max-height: 600px; overflow: auto; padding: 5px; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; margin: 0px; padding: 0px; white-space: inherit;"><span class="pln" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">jarsigner </span><span class="pun" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">verify </span><span class="pun" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">verbose </span><span class="pun" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">certs my_application</span><span class="pun" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">.</span><span class="pln" style="border: 0px; color: #303336; margin: 0px; padding: 0px;">apk >output.txt</span></code></pre>
You will need to ensure that the java jdk is included in your Path. You'll find it, here:<br />
<span style="font-family: Courier New, Courier, monospace;">C:\Program Files (x86)\Java\jdk1.7.0_55\bin\jarsigner.exe</span><br />
If you don't then its likely you haven't correctly installed the Android SDK.<br />
<br />
This will produce a lot of output that will show the certificate used to sign each file, which is usually the same certificate. Open the output.txt file with a text editor.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">s 98829 Mon Jul 18 15:45:06 NZST 2016 META-INF/MANIFEST.MF</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> X.509, CN=<span style="background-color: yellow;">CERTIFICATE_NAME</span>, OU=Department, O=Company Ltd, L=Auckland, ST=Auckland, C=NZ</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> [certificate is valid from 01/01/16 10:06 PM to 31/12/43 11:06 PM]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 98950 Mon Jul 18 15:45:06 NZST 2016 META-INF/CERT.SF</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 1408 Mon Jul 18 15:45:06 NZST 2016 META-INF/CERT.RSA</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">sm 7364 Wed Dec 31 16:00:00 NZDT 1980 AndroidManifest.xml</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> X.509, CN=<span style="background-color: yellow;">CERTIFICATE_NAME</span>, OU=</span><span style="font-family: "courier new" , "courier" , monospace;">Department</span><span style="font-family: "courier new" , "courier" , monospace;">, O=Company Ltd, L=Auckland, ST=Auckland, C=NZ</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> [certificate is valid from 01/01/16 10:06 PM to 31/12/43 11:06 PM]</span><br />
<br />
<span style="font-family: inherit;">Ensure the certificate name is what you expect, and there is no mention of "Debug" in the output file.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">I find it useful to do a search and replace for the "CN=CERTIFICATE_NAME" part, and replace with "@@@@@@" or whatever. Then search for "CN=", and find any, that means some files are signed with a different certificate.</span>Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-64799211429776906822016-07-17T17:07:00.000+12:002016-07-19T11:47:44.603+12:00A fun build trist: Xamarin.iOS, a provisioning profile, and a certificateA [sarcasm]fun[/sarcasm] problem to have:<br />
<br />
<span style="background-color: #2c3e50; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets : error: No installed provisioning profiles match the installed iOS signing identities.</span><br />
<span style="background-color: #2c3e50; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;"><br /></span>
I use <a href="http://bitrise.io/">Bitrise </a>for my mobile CI. While its a great system, sometimes opaque errors can increase your blood pressure. Honestly, its not any fault of Bitirse, its more a Xamarin problem in general and the maturity of the tool-sets.<br />
<div>
<br /></div>
<div>
For my error I had created my Apple certificate and provisioning profile in the Apple Developer portal with no issues. I always download and install the certificate (a development certificate in my case) onto my Mac's Keychain.</div>
<div>
<br /></div>
<div>
For Bitrise you need to export the p12 file for the certificate and upload into Bitrise:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-wIDE1GNGkgk/V4sOb1CCV2I/AAAAAAAAGz0/1aYr9f54dw0DLkeWvtqY3Zr3ez9oOvqXgCLcB/s1600/2016-07-17%2B%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://3.bp.blogspot.com/-wIDE1GNGkgk/V4sOb1CCV2I/AAAAAAAAGz0/1aYr9f54dw0DLkeWvtqY3Zr3ez9oOvqXgCLcB/s400/2016-07-17%2B%25281%2529.png" width="383" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Here you can see I've uploaded both the certificate and the provisioning profile and I've saved the password. All good so far.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
After still getting the error from Bitrise:</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="background-color: #2c3e50; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets : error: No installed provisioning profiles match the installed iOS signing identities.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I forced the selection of the correct certificate in the iOS project properties:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-1MJ4rwr2Djo/V4sPZOQwEEI/AAAAAAAAGz8/iZUqpIY5pjIV2-XGcHfZ4cNkOVYdc_YEwCLcB/s1600/2016-07-17%2B%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://4.bp.blogspot.com/-1MJ4rwr2Djo/V4sPZOQwEEI/AAAAAAAAGz8/iZUqpIY5pjIV2-XGcHfZ4cNkOVYdc_YEwCLcB/s400/2016-07-17%2B%25282%2529.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Still no luck.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Next I decided to explicitly set the provisioning profile so it's not using "magic" to determine which profile to use.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-6PF8_GNojYI/V4sP5jQ1B3I/AAAAAAAAG0E/yWmZwlnSyUYc1IXRrfCM7ZVIJQAuGtpMgCLcB/s1600/shia-magic.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://1.bp.blogspot.com/-6PF8_GNojYI/V4sP5jQ1B3I/AAAAAAAAG0E/yWmZwlnSyUYc1IXRrfCM7ZVIJQAuGtpMgCLcB/s1600/shia-magic.gif" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Visual Studio doesn't seem to understand or recognise the list of valid provisioning profiles however, as for me, the drop down list is blank. Nevermind, it can be set in the XML.</div>
<div class="separator" style="clear: both; text-align: left;">
First get the provisioning profile ID from your provisoning profile file. Its a file with the extension .mobileprovision, that you download from the Apple Developer portal. Find a section in the XML that has a key "UUID". Next to it is the Provisioning Profile ID. Copy this value.</div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <key>UUID</key></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><string>19000000-aaaa-bbbb-cccc-ddddeeeeffff</string></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Paste the value into your Xamarin.iOS project csproj file. You'll need to know which build configuration it will be building on the CI server. For me its, Ad-Hoc/iPhone</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' "></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <DebugType>none</DebugType></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <Optimize>True</Optimize></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <OutputPath>bin\iPhone\Ad-Hoc</OutputPath></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <ErrorReport>prompt</ErrorReport></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <WarningLevel>4</WarningLevel></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <ConsolePause>False</ConsolePause></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <MtouchArch>ARMv7, ARM64</MtouchArch></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <CodesignEntitlements>Entitlements.plist</CodesignEntitlements></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <BuildIpa>True</BuildIpa></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <b><CodesignProvision></b></span><span style="font-family: "courier new" , "courier" , monospace;"><b>19000000-aaaa-bbbb-cccc-ddddeeeeffff</b></span><span style="font-family: "courier new" , "courier" , monospace;"><b></CodesignProvision></b></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> <b><CodesignKey>iPhone Developer: Ben Rees (XABCDEFGHI)</CodesignKey></b></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> </PropertyGroup></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
Paste the value into the CodesignProvision element. This will force the Xamarin Builder to go looking for that exact provisioning profile.</div>
<div>
<br /></div>
<div>
But still no luck. </div>
<div>
<span style="background-color: #2c3e50; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets : error: No installed provisioning profiles match the installed iOS signing identities.</span></div>
<div>
<br /></div>
<div>
I also turned on some extra debugging in Bitrise and found this:</div>
<div>
<span style="background-color: #2c3e50; color: #ebebeb; font-family: "source code pro" , monospace; font-size: 14px; white-space: pre-wrap;">/Users/vagrant/git/iOS/Info.plist : error: Project bundle identifier 'biz.rees.CorporateBs' does not match specified provisioning profile '19000000-aaaa-bbbb-cccc-ddddeeeeffff'</span></div>
<div>
<br /></div>
<div>
AHA! The Bundle App ID must be case sensitive! In the Apple Developer Portal I specified it as </div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">biz.rees.CorporateBS</span></div>
<div>
<br /></div>
<div>
Problem solved.</div>
<div>
<br /></div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-25295170147280103782016-07-17T14:42:00.000+12:002016-07-17T14:42:54.269+12:00Icon Design and ToolingI have to give a shout out to <a href="https://inkscape.org/en/">Inkscape</a> what a fantastic tool for drawing and editing vector based icons (such as SVG files). Thoroughly recommend it. Its free and open source!<br />
<br />
If it isn't suitable or you're looking for a cost effective way of producing professional icons or UI design check out <a href="https://www.fiverr.com/">https://www.fiverr.com/</a>. Its a market place to find, connect with, and hire services of just about any kind. <br />
<br />
While you're waiting for your designer to draw your new icons, you can hire someone to pop balloons for you, or take a bath in baked beans.Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-26548495815763465302016-07-17T14:33:00.003+12:002016-07-17T14:33:29.924+12:00More Common Xamarin Forms Project problemsAs a follow on from <a href="http://blog.rees.biz/2016/04/resolving-common-issues-loading-xamarin.html">Resolving Common Issues Loading Xamarin Samples</a> here are some other issues I seem to be commonly running into. These issues are not only referring to Xamarin samples, but to any Xamarin project.<br />
<br />
<h3>
Corrupt Xamarin-Android ZIP files</h3>
Another common problem seems to be with corrupt Xamarin-Android SDK zip files located here:<br />
C:\Users\<Your Username>\AppData\Local\Xamarin\zips<br />
You'll see an error message similar to "...zip file "C:\Users\<Your Username>\AppData\Local\Xamarin\zips\1FD832DCC1792D8ACA07FAC3259FC5A9.zip" is corrupt.<br />
<br />
Deleting all the zip files in that folder will cause them to be downloaded again during the next build within Vs. This will make the next build very slow for obvious reasons. Let it run its course, and resist the temptation to cancel it. It could take 20minutes or more. After they are downloaded and cached in that folder again, build speed will be back to normal.<br />
<br />
<br />
<br />
<h3>
Error<span class="Apple-tab-span" style="white-space: pre;"> </span>"aapt.exe" exited with code -1073741819.<span class="Apple-tab-span" style="white-space: pre;"> </span></h3>
Another common symptom is build errors in the Android generated file Resource.cs file.<br />
The following error will be generated if there are dashes "-" in any file in the Resource/Drawables folders.<br />
<br />
<h3>
Android SDK Updates</h3>
Generally if an error follows an Android SDK update it is most likely related to new build and SDK tools being used just installed/updated. Like the above error the most likely symptom of this is errors from the generated file Resource.cs file in your Android project.<br />
First try running a Clean build then a Rebuild.If that doesn't work the best bet might be to revert back to a previous version of the SDK Build tools. Also check <a href="http://forums.xamarin.com/categories/android">forums.xamarin.com</a>.<br />
<br />
<br />
<h3>
Error<span class="Apple-tab-span" style="white-space: pre;"> </span>The "XamlCTask" task failed unexpectedly.</h3>
System.IO.FileNotFoundException: Could not load file or assembly 'Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' or one of its dependencies. The system cannot find the file specified.<br />
File name: 'Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756'<br />
Resolved by Deleting the entire packages folder contents and allowing a build to restore all packages.Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-5595263934486766392016-06-18T16:51:00.000+12:002016-06-18T16:51:21.286+12:00CheckOut a Pull Request in Git<br />
<h3 style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
Set-Up your Local Git Config</h3>
<div style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
Locate the section for your github remote in the <code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;">.git/config</code> file. It looks like this:</div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; word-break: normal; word-wrap: normal;">[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@github.com:joyent/node.git
</code></pre>
<div style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
Now add the line <code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;">fetch = +refs/pull/*/head:refs/remotes/origin/pr/*</code> to this section. Obviously, change the github url to match your project's URL. It ends up looking like this:</div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; word-break: normal; word-wrap: normal;">[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@github.com:joyent/node.git
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
</code></pre>
<div style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
<br /></div>
<h3 style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
Use the Command Line to Checkout a Pull Request</h3>
<div style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
Now fetch all the pull requests:</div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; word-break: normal; word-wrap: normal;">$ git fetch origin
From github.com:joyent/node
* [new ref] refs/pull/1000/head -> origin/pr/1000
* [new ref] refs/pull/1002/head -> origin/pr/1002
* [new ref] refs/pull/1004/head -> origin/pr/1004
* [new ref] refs/pull/1009/head -> origin/pr/1009
...
</code></pre>
<div style="box-sizing: border-box; color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
To check out a particular pull request:</div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; word-break: normal; word-wrap: normal;">$ git checkout pr/999
Branch pr/999 set up to track remote branch pr/999 from origin.
Switched to a new branch 'pr/999'</code></pre>
<div>
<br /></div>
<h3>
<span style="color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px;">Use Source Tree to Checkout a Pull Request</span></h3>
<div>
<span style="color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px;">First, fetch all the open Pull Requests:</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-SVDZdMLtmS4/V2TSucoys3I/AAAAAAAAGfg/WQ1j21GqFHY0TDNonYSwO5uQ2LwoQEBYACLcB/s1600/St1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://4.bp.blogspot.com/-SVDZdMLtmS4/V2TSucoys3I/AAAAAAAAGfg/WQ1j21GqFHY0TDNonYSwO5uQ2LwoQEBYACLcB/s320/St1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Then, simply right click the appropriate Pull Request and select Checkout.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-S66nmDWCN9k/V2TSvmwzu-I/AAAAAAAAGfo/0TJ8UKnHEIQGxpJQDNlYUENPg-NWF94XwCLcB/s1600/St2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://1.bp.blogspot.com/-S66nmDWCN9k/V2TSvmwzu-I/AAAAAAAAGfo/0TJ8UKnHEIQGxpJQDNlYUENPg-NWF94XwCLcB/s320/St2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Done.</span></div>
<div>
<span style="color: #333333; font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 25.6px;"><br /></span></div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-17965775405575124572016-04-30T09:20:00.003+12:002016-04-30T09:20:53.453+12:00A couple of odd questions in a Xamarin University course<div class="separator" style="clear: both; text-align: left;">
These answers don't seem correct to me. Anyone agree, disagree?</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-IVV_4hFVi7I/VyPP97oCtsI/AAAAAAAAGBo/XeeK1fB5zmQCHzIswJS0rVVFzNWc3u8sgCLcB/s1600/image%2B%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://3.bp.blogspot.com/-IVV_4hFVi7I/VyPP97oCtsI/AAAAAAAAGBo/XeeK1fB5zmQCHzIswJS0rVVFzNWc3u8sgCLcB/s320/image%2B%25281%2529.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-YyqOcKj2tIE/VyPP98Rh7jI/AAAAAAAAGBs/e39U9PPyYdcFQnXXdXaIc40myyV1kXC3QCLcB/s1600/image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://2.bp.blogspot.com/-YyqOcKj2tIE/VyPP98Rh7jI/AAAAAAAAGBs/e39U9PPyYdcFQnXXdXaIc40myyV1kXC3QCLcB/s320/image.png" width="320" /></a></div>
<br />Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com1tag:blogger.com,1999:blog-2612479901176767501.post-113965177249507912016-04-24T09:23:00.002+12:002016-04-24T10:24:39.426+12:00Resolving common issues loading Xamarin Forms 2.0+ examplesAfter downloading and trying to run through a few Xamarin Forms demos, I've found that upgrading them to Forms 2.x seems to create errors. Also you can encounter these errors even if you don't upgrade to the latest version of Forms. These issues will tend to focus on Android.<br />
<br />
<h2>
Issue 1: System.IO.FileNotFoundException: </h2>
<div>
Could not load assembly 'Microsoft.Windows.Design.Extensibility, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Perhaps it doesn't exist in the Mono for Android profile?</div>
<br />
Just delete the references which ends with *.Design. In my project it was: Xamarin.Forms.Core.Design,<br />
<div>
Xamarin.Forms.Xaml.Design, </div>
<div>
Xamarin.Android.Support.Design.</div>
<div>
<br /></div>
<div>
<div>
<a href="http://danielhindrikes.se/xamarin/how-to-solve-xamarin-forms-android-build-error-after-updated-to-forms-2-0/">See Also</a><br />
<br />
<br />
<h2>
Issue 2: Resources.String.ApplicationName and Resources.String.Hello are not defined</h2>
<div>
<span class="kwd" style="border: 0px; color: #0000dd; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">global</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">::</span><span class="pln" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">MYNAMESPACE</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Resource</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">String</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">ApplicationName</span><span class="pln" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="pln" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="kwd" style="border: 0px; color: #0000dd; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">global</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">::</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">MYNAMESPACE</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Android</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Resource</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">String</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="border: 0px; color: #660066; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">ApplicationName</span><span class="pun" style="border: 0px; color: #666600; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: 1.5; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">;</span></div>
<br />
If you are getting an undefined error for either a resource string "Hello" or "ApplicationName" you have this issue. These strings do not appear to be defined anywhere in the application code. Deleting it from the Resources.cs doesn't resolve the issue as it will just come back next time you build.</div>
<div>
Fix it by running a clean and rebuild.<br />
<br />
<a href="https://forums.xamarin.com/discussion/17732/resource-string-does-not-contain-a-definition-for-hello">See also</a></div>
</div>
<h2>
Issue 3: Unsupported Android Target version.</h2>
<div>
If either the targeted version, or compile using version are set to a version of Android that your locally installed Android SDK doesn't support. This is fixed either by installing that version using the Android SDK Manager or setting the Target and Compile versions in the Android project properties to something you do have locally installed.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-F0vC6oxaaF0/VxvmJ6wQJJI/AAAAAAAAF_g/K-jnpBfhk10mwZkS6tw1cX-IBEKxGbiTACLcB/s1600/Issue3a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://4.bp.blogspot.com/-F0vC6oxaaF0/VxvmJ6wQJJI/AAAAAAAAF_g/K-jnpBfhk10mwZkS6tw1cX-IBEKxGbiTACLcB/s320/Issue3a.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="text-align: center;">This App has an unsupported compile target.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-GvLhpsGOm-c/Vxr2IcLbAcI/AAAAAAAAF-w/VKctYlFijoo0JAQBYwug7s1Yx-Qxtny3ACLcB/s1600/Issue3b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://2.bp.blogspot.com/-GvLhpsGOm-c/Vxr2IcLbAcI/AAAAAAAAF-w/VKctYlFijoo0JAQBYwug7s1Yx-Qxtny3ACLcB/s320/Issue3b.png" width="320" /></a></div>
<div class="" style="clear: both; text-align: center;">
Start the Android SDK Manager from Visual Studio</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-3O0EIZ_Il-Q/Vxr2Ie2L8fI/AAAAAAAAF-0/SjERQ216GGM8RIbWBlLZm5OEx_n-Q_1VACLcB/s1600/Issue3c.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://3.bp.blogspot.com/-3O0EIZ_Il-Q/Vxr2Ie2L8fI/AAAAAAAAF-0/SjERQ216GGM8RIbWBlLZm5OEx_n-Q_1VACLcB/s320/Issue3c.png" width="193" /></a></div>
<div class="" style="clear: both; text-align: center;">
Or from Windows Start.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-QH_dXe0_6dY/Vxr2I0g-6LI/AAAAAAAAF-4/whiy5mYuWJQ16amM4IN8E4wgjKixCLZ9gCLcB/s1600/Issue3d.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="299" src="https://1.bp.blogspot.com/-QH_dXe0_6dY/Vxr2I0g-6LI/AAAAAAAAF-4/whiy5mYuWJQ16amM4IN8E4wgjKixCLZ9gCLcB/s320/Issue3d.png" width="320" /></a></div>
<div class="" style="clear: both; text-align: center;">
You can see here my current setup doesn't support Jelly Bean. </div>
<div class="" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-JWavD5sr7SQ/VxvmJ7XCbuI/AAAAAAAAF_k/DaoUkcfY2GImUpTNffow3HKvldLRKVbZgCLcB/s1600/Issue3e.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://4.bp.blogspot.com/-JWavD5sr7SQ/VxvmJ7XCbuI/AAAAAAAAF_k/DaoUkcfY2GImUpTNffow3HKvldLRKVbZgCLcB/s320/Issue3e.png" width="320" /></a></div>
<div class="" style="clear: both; text-align: left;">
In this case I chose to compile using Marshmallow, which is supported by my current setup.</div>
<div class="" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: left;">
Issue 4: Not configured to Deploy on Run (F5).</h2>
<div class="" style="clear: both; text-align: left;">
If you expect the App to compile, deploy and run when you press F5 or "Run" on the toolbar and it doesn't, then you'll need to adjust the build options.</div>
<div class="" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-3V5twXRcNBo/VxvnCHJFdsI/AAAAAAAAF_s/t38zWi6icPsaDBV1C0gCyPHtfXO97IQngCLcB/s1600/Issue4a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://1.bp.blogspot.com/-3V5twXRcNBo/VxvnCHJFdsI/AAAAAAAAF_s/t38zWi6icPsaDBV1C0gCyPHtfXO97IQngCLcB/s320/Issue4a.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
You can see in this screen shot the Android project is not configured to deploy automatically when it is "Run". Tick the box highlighted above, and you're set.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-39670907408187421582016-04-20T22:06:00.001+12:002016-04-20T22:06:54.135+12:00Auckland Xamarin Meet-Up Talk links<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{135}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; height: auto; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; width: auto; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">Steve Chadbourne </span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">– </span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">@</span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="SpellingError SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; background-image: url("data:image/gif; background-position: 0% 100%; background-repeat: repeat-x; border-bottom-color: transparent; border-bottom-style: solid; border-bottom-width: 1px; margin: 0px; padding: 0px; touch-action: pan-x pan-y;">stevechadbourne</span></span><span class="LineBreakBlob BlobObject SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><span class="SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; margin: 0px; padding: 0px; touch-action: pan-x pan-y;">​</span></span><span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{136}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; font-family: Arial; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">Ben Rees </span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">– </span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">@</span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="SpellingError SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; background-image: url("data:image/gif; background-position: 0% 100%; background-repeat: repeat-x; border-bottom-color: transparent; border-bottom-style: solid; border-bottom-width: 1px; margin: 0px; padding: 0px; touch-action: pan-x pan-y;">benrnz</span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{136}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; font-family: Arial; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><br /></span></div>
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{136}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; font-family: Arial; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">Here some links to the tools Steve and I talked about tonight. </span></div>
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{136}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; font-family: Arial; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><br /></span></div>
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{136}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; word-wrap: break-word;" xml:lang="EN-NZ">
<span style="font-family: Arial, sans-serif;"><b>Simple Xamarin Form Example: </b></span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{137}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><a class="Hyperlink SCX136509318" href="https://github.com/Benrnz/CorporateBsGenerator" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; cursor: text; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; text-decoration: none; touch-action: pan-x pan-y;" xml:lang="EN-NZ">https://github.com/Benrnz/CorporateBsGenerator</span></a><span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{138}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{139}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-US">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">Learning Forms </span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{140}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><a class="Hyperlink SCX136509318" href="https://developer.xamarin.com/guides/xamarin-forms/" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; cursor: text; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; text-decoration: none; touch-action: pan-x pan-y;" xml:lang="EN-NZ">https://developer.xamarin.com/guides/xamarin-forms/</span></a><span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{141}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{142}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-US">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">Gorilla Player</span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{143}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><a class="Hyperlink SCX136509318" href="http://www.gorillaplayer.com/" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; cursor: text; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; text-decoration: none; touch-action: pan-x pan-y;" xml:lang="EN-NZ">http://www.gorillaplayer.com/</span></a><span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{144}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{145}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-US">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ">Open Source </span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="SpellingError SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; background-image: url("data:image/gif; background-position: 0% 100%; background-repeat: repeat-x; border-bottom-color: transparent; border-bottom-style: solid; border-bottom-width: 1px; margin: 0px; padding: 0px; touch-action: pan-x pan-y;">Xaml</span></span><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"> Viewer</span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{146}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><a class="Hyperlink SCX136509318" href="http://bit.ly/1NtG3be" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; cursor: text; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"><span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; text-decoration: none; touch-action: pan-x pan-y;" xml:lang="EN-NZ">http://bit.ly/1NtG3be</span></a><span class="TextRun EmptyTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;"></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Calibri, sans-serif; font-size: 8.02593px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{147}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; font-weight: bold; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{148}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
<div class="OutlineElement EmptyList Ltr SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: white; clear: both; cursor: text; direction: ltr; font-family: Arial; font-size: 13.1333px; margin: 0px; opacity: 0.2; overflow: visible; padding: 0px; position: relative; touch-action: pan-x pan-y;">
<div class="Paragraph SCX136509318" paraeid="{ef18e696-330a-47bb-9374-73548aa1ccdb}{149}" paraid="0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: transparent; color: windowtext; line-height: 1.2; padding: 0px; touch-action: pan-x pan-y; vertical-align: baseline; white-space: pre; word-wrap: break-word;" xml:lang="EN-NZ">
<span class="TextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;" xml:lang="EN-NZ"><span class="NormalTextRun SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; background-color: inherit; margin: 0px; padding: 0px; touch-action: pan-x pan-y;"></span></span><span class="EOP SCX136509318" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -webkit-user-select: text; font-family: Arial, sans-serif; font-size: 13.1333px; line-height: 1.2; margin: 0px; padding: 0px; touch-action: pan-x pan-y; white-space: normal;">​</span></div>
</div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-30293284686890086702016-04-18T17:34:00.002+12:002016-04-18T17:34:58.917+12:00Data Binding - The Awesome Sauce lavished onto Xamarin FormsThere are some great resources around introducing Data Binding for Xamarin Forms. Here are some great posts I've come across that are worth reading and bookmarking.<br />
<br />
For some background on getting started with Xamarin Forms. Check out the Xamarin guide here:<br />
<a href="https://developer.xamarin.com/guides/xamarin-forms/">https://developer.xamarin.com/guides/xamarin-forms/</a><br />
<br />
Xamarin have a solid section that gives a good start into learning XAML and Data Binding here:<br />
<a href="https://developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/">https://developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/</a><br />
Its definitely worth reading through all six sections.<br />
Part 1. Getting Started with XAML<br />
Part 2. Essential XAML Syntax<br />
Part 3. XAML Markup Extensions<br />
Part 4. Data Binding Basics<br />
Part 5. From Data Binding to MVVM<br />
Part 6. Compiling XAML<br />
<br />
Data Binding Controls to each other to prevent/reduce writing code-behind.<br />
<a href="https://blog.xamarin.com/advanced-data-binding-for-ios-android-and-windows/">https://blog.xamarin.com/advanced-data-binding-for-ios-android-and-windows/</a>Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-37769746658610750242016-04-18T17:20:00.002+12:002016-04-18T17:20:30.975+12:00Awesome Xamarin Forms How-To CommandsRecently read a great blog from David Britch giving a comprehensive guide to using commands with Xamarin Forms.<br />
<br />
<a href="https://blog.xamarin.com/simplifying-events-with-commanding/">https://blog.xamarin.com/simplifying-events-with-commanding/</a>Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-73394108983219892672016-04-18T17:15:00.000+12:002016-04-18T17:15:52.328+12:00Fresh Essentials for Xamarin FormsMichael Ridland has recently blogged about a nice light weight library of essential and commonly used converters, controls and utilities.<br />
<br />
<a href="http://www.michaelridland.com/xamarin/freshessentials-for-xamarin-forms-the-must-have-nuget-for-forms/">http://www.michaelridland.com/xamarin/freshessentials-for-xamarin-forms-the-must-have-nuget-for-forms/</a><br />
<br />Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-20935830128689714812016-04-09T15:32:00.000+12:002016-04-09T15:32:01.160+12:00Simple Xamarin Forms Demo App<h2>
A Simple Xamarin Forms Sample App</h2>
<br />
Recently I presented a short Xamarin Forms introduction. It was only a short 30min taster, but I wanted to ensure I was showing something a little deeper than a simple "Hello World" App. I personally find those kind of demo's too basic and not enough to get a taste of how using a technology is going to suit real world work.<br />
<br />
Here's the App I built for the demo:<br />
<br />
<a href="https://github.com/Benrnz/CorporateBsGenerator">https://github.com/Benrnz/CorporateBsGenerator</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-HqLfZa7IVD8/Vwh3k8JHhqI/AAAAAAAAF1k/eAcL94WyhRUSRpr1li8s07E5O6lKekuZQ/s1600/BSGen1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://4.bp.blogspot.com/-HqLfZa7IVD8/Vwh3k8JHhqI/AAAAAAAAF1k/eAcL94WyhRUSRpr1li8s07E5O6lKekuZQ/s320/BSGen1.png" width="180" /></a></div>
<br />
<h3>
Demo points</h3>
<div>
<ol>
<li>Solution structure of a Xamarin Forms App.</li>
<li>Entry point - how does it start and choose the first Xaml page?</li>
<li>Anatomy of a Xaml page.</li>
<li>Xaml Basics</li>
<ol>
<li>Root elements, in this case a ContentPage. Other options are MasterDetailPage, TabbedPage, and NavigationPage.</li>
<li>Setting Page Padding to different values for each platform.</li>
<li>Layout Controls: In this case we're using a AbsoluteLayout and a StackLayout. Another common Layout is Grid.</li>
<li>Labels, Styles, and basic value DataBinding.</li>
<li>Using different buttons for iOS and Android. The Material Design Floating Action Button.</li>
<li>Binding can be used for more than value binding. The FAB has a bound reference to the ListView.</li>
</ol>
<li>Code Behind</li>
<ol>
<li>Great to get started</li>
<li>Event Handlers</li>
<li>Best Practice - Code behind doesn't scale well. The MVVM pattern.</li>
</ol>
<li>A look at more advanced customisation for Android. A Custom Renderer to create a Floating Action Button.</li>
<li>Tooling - What do we need to develop and test an App?</li>
</ol>
<div>
<br /></div>
</div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-32401306984547191892016-04-03T11:22:00.001+12:002016-04-03T11:23:14.102+12:00Floating Action Button in Xamarin FormsI'm loving experimenting with Xamarin Forms at the moment. So when I wanted to include a Floating Action Button (FAB) in Android versions of a Forms App, I naturally wanted to try to get this working with Forms first. I realise you can use Xamarin Native Android views in a Forms App, but I enjoy XAML and creating reusable controls.<br />
<br />
My first port of call was <a href="https://github.com/jamesmontemagno">James Montemagno's GitHub</a> and <a href="http://motzcod.es/">blog</a> and found his examples for a FAB.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-WlAuJ6Dqgq8/VwBKY2pi6uI/AAAAAAAAFx8/q-vk7Xm0nao8BaTibaFhN6vOIdgeSrVlw/s1600/demo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://3.bp.blogspot.com/-WlAuJ6Dqgq8/VwBKY2pi6uI/AAAAAAAAFx8/q-vk7Xm0nao8BaTibaFhN6vOIdgeSrVlw/s320/demo.gif" width="201" /></a></div>
<a href="https://github.com/jamesmontemagno/FloatingActionButton-for-Xamarin.Android">https://github.com/jamesmontemagno/FloatingActionButton-for-Xamarin.Android</a><br />
He does mention he ported this code from: <a href="https://github.com/makovkastar/FloatingActionButton">https://github.com/makovkastar/FloatingActionButton</a><br />
<br />
This looks perfect, but I wanted to improve the Forms example to be mostly XAML based and try to best encapsulate the events into the FAB control to minimise the amount of work the consuming developer has to do.<br />
<br />
Here's my code so far.<br />
<a href="https://github.com/Benrnz/XamlFloatingActionButton">https://github.com/Benrnz/XamlFloatingActionButton</a><br />
<br />
Its far from perfect, but works great. Be aware however, that if your ObservableCollection has duplicate values in it, the FAB will exhibit unexpected hide/show behaviour.<br />
<br />
Here's what I ended up with in my XAML:<br />
<br />
<pre style="background: url("http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif") rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828px;"><code style="word-wrap: normal;"> <AbsoluteLayout VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Label Text="FAB Test 1"
VerticalOptions="Center"
HorizontalOptions="Center" />
<ListView x:Name="MainList"
ItemsSource="{Binding MyItems}"
VerticalOptions="FillAndExpand"/>
</StackLayout>
<fabTest1:FloatingActionButtonView x:Name="Fab"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1,1,AutoSize,AutoSize"
ImageName="ic_add.png"
ColorNormal="#ff3498db"
ColorPressed="Black"
ColorRipple="#ff3498db"
Command="{Binding FabExecuteCommand}"
ParentList="{Binding Source={x:Reference MainList}, Path=.}"/>
</AbsoluteLayout> </code></pre>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-75997182082450303962016-04-03T10:33:00.000+12:002016-04-03T10:33:14.695+12:00Microsoft announces new licencing for Xamarin!<br />
<br />
<br />
Since Microsoft bought Xamarin and the deal was officially signed and closed about two weeks ago, Microsoft have announced their intentions to open source and make Xamarin free.<br />
<br />
Visual Studio Community edition (the free edition) will also have access but not to all features.<br />
This will include:<br />
<br />
<ul>
<li>Xamarin Studio (Mac and Windows version)</li>
<li>Xamarin Platform for iOS, Android and Windows, for small teams and non-Enterprise organisations. Enterprise is defined as organisations earning more then one million US Dollars per annum.</li>
<li>Check out this blog from https://blog.xamarin.com/xamarin-for-all/</li>
</ul>
<div>
Writing an App for any platform using Xamarin is now totally open source!</div>
<br />
<br />
Check out the actual //Build 2016 announcement by Scott Guthrie:<br />
https://www.youtube.com/watch?v=WC7ijoFzjEg<br />
18:35<br />
<br />
Test Cloud will continue to be a paid product with several tiers although Enterprise MSDN subscribers will get a 25% discount. <br />
<br />
Xamarin Insights will merge with Microsoft's HockeyApp over time. Right now Insights has features that Hockey does not yet support.<br />
<br />
Some level of Xamarin University will be included for MSDN Professional and Enterprise subscribers, although this isn't clear yet.<br />
<br />
Check out https://store.xamarin.com/ for latest details.Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-14909556481685315382016-03-15T17:24:00.002+13:002016-03-15T17:47:18.234+13:00Initial Learnings Setting Up For XamarinI've been gearing up some work projects as well as some home projects recently to use Xamarin. Specifically, of special interest to me is Xamarin Forms. In my opinion this is a truly incredibly useful technology.<br />
<br />
But first, inevitably, there is some setup and familiarisation to get through before getting into code. Here are some of my random findings during this process.<br />
<br />
<h3>
The Xamarin trial period is too short.</h3>
<div>
Its fantastic there actually is a trial period. However there's quite a bit of learning and discovery to do, and 30 days is just not enough. Its an amazing product well worth the money, so don't be afraid to jump in. The <a href="http://xamarin.com/">Xamarin.com</a> web site pricing indicates pricing per month, but you must sign up for a full year however.</div>
<div>
<br /></div>
<h3>
The Android SDK Emulator is still shocking.</h3>
<div>
Glaciers move faster than the default Android SDK Emulator. There is wide recognition of this, but in the few years I've been involved in mobile development, it hasn't really improved. The number of how-to web pages describing performance tweaks seems to back this up as well.</div>
<div>
<br /></div>
<div>
TIP: Fortunately there is a decent Andriod Simulator now for Visual Studio. It can be downloaded and installed separately <a href="https://www.visualstudio.com/en-us/features/msft-android-emulator-vs.aspx">here</a>.</div>
<div>
The good news: It even integrates into Visual Studio Community edition and Xamarin Studio. The bad news: It doesn't work with operating systems that don't support Hyper-V (which include Windows 10 Home see <a href="https://msdn.microsoft.com/en-us/virtualization/hyperv_on_windows/quick_start/walkthrough_compatibility">here</a>).</div>
<div>
<br /></div>
<div>
TIP: Don't close the Emulator when you're finished debugging, running code again with Visual Studio or Xamarin Studio will redeploy and reattach much faster than re-opening it.</div>
<div>
<br /></div>
<h3>
Creating New Projects in Xamarin Studio.</h3>
<div>
Xamarin Studio doesn't set all the same defaults as Visual Studio. </div>
<div>
<br /></div>
<div>
TIP: I had to manually tick the box to deploy my application when I 'F5' or click the Debug button. The Deploy box needs to be ticked.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-m9b-cnpe46w/Vud9OnsMfNI/AAAAAAAAFn8/CU9eAnmPW5YxuYMeXW2Ka6Az9C-tHuz6g/s1600/BuildConfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://3.bp.blogspot.com/-m9b-cnpe46w/Vud9OnsMfNI/AAAAAAAAFn8/CU9eAnmPW5YxuYMeXW2Ka6Az9C-tHuz6g/s320/BuildConfig.png" width="320" /></a></div>
<div>
<br /></div>
<div>
TIP: Using File-New-Project in Xamarin Studio doesn't create any Windows flavoured Apps. Also if the Apple build server isn't available at the time, you won't get an iOS App project either. I've had some trouble using Visual Studio File-New-Project with creation errors and PowerShell errors (which is probably issues with my rig rather than Vs), but Xamarin Studio has worked every time.</div>
<div>
<br /></div>
<h3>
Visual Studio vs Xamarin Studio on Windows</h3>
<div>
I've been impressed with Xamarin Studio so far. If you're a fan of Visual Studio like me, don't be tempted to write it off. Xamarin Studio presents a very clean and simple IDE with full intelli-sense support. I couldn't fault it creating new prototype Apps and debugging worked seemlessly everytime. It even can deploy and debug code to the new Visual Studio Android Emulator. </div>
<div>
<br /></div>
<div>
On the downside, Xamarin Studio does not have a XAML designer at all, which is a real negative for me. Another obvious issue is that any iOS Xamarin native development can only be performed on Xamarin Studio on a Mac. (Any shared iOS/Android PCL development can be done on Windows however). Also, only a Mac can build the native iOS binaries. Both Xamarin Studio and Visual Studio can use a Mac remotely on the LAN to trigger a build. The iOS Simulator can only be used locally on a Mac however.</div>
<div>
<br /></div>
<div>
I don'y miss R# that much its stops me from using Xamarin Studio, but any kind of XAML editing I prefer Visual Studio. Anecdotally, I do believe Xamarin Studio performs better than Visual Studio.</div>
<div>
<br /></div>
<h3>
Resharper tends to show phantom errors</h3>
<div>
Not sure what's going on with R#, but with my version, 10.0.2 I occasionally see red squiggly underlines indicating errors on methods that are building and functioning fine. No solution for this so far, but its not a show-stopper for me.</div>
<div>
<br /></div>
<div>
TIP: When building for the first time in Visual Studio, I had some phantom errors showing up which are coming from R#. To get rid of them I changed the build error filter to "Errors Only"; it was defaulting to "Errors+Intellisense".</div>
<div>
<br /></div>
<div>
Thats all I have for now, more learning still to do, so I'll have more to say in the near future.</div>
<div>
<br /></div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-46294050534322959662016-01-08T13:16:00.001+13:002016-01-08T13:16:11.992+13:00Method doesn't throw ArgumentNullException when expectedI noticed an interesting test failure when I refactored a method to use the recently added C# keyword 'yeild'.<br />
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">public</span> <span class="kwrd" style="color: blue;">class</span> Subject</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> {</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">public</span> IEnumerable<<span class="kwrd" style="color: blue;">string</span>> DoWork(<span class="kwrd" style="color: blue;">string</span> foo)</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> {</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">if</span> (foo == <span class="kwrd" style="color: blue;">null</span>) <span class="kwrd" style="color: blue;">throw</span> <span class="kwrd" style="color: blue;">new</span> ArgumentNullException(nameof(foo));</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> <span class="kwrd" style="color: blue;">var</span> someCollection = Enumerable.Range(0, 100);</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">foreach</span> (<span class="kwrd" style="color: blue;">var</span> number <span class="kwrd" style="color: blue;">in</span> someCollection)</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> {</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> yield <span class="kwrd" style="color: blue;">return</span> foo + number.ToString(<span class="str" style="color: #a31515;">"C"</span>);</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> }</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> }</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> }</pre>
<br /><br />The above method is, of course, a contrived and simplified example.<br /> Here is the unit test for this method to check that ArgumentNullException is thrown.<div>
<br /></div>
<div>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> [TestMethod]</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> [ExpectedException(<span class="kwrd" style="color: blue;">typeof</span>(ArgumentNullException))]</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">public</span> <span class="kwrd" style="color: blue;">void</span> DoWork_ShouldThrow_GivenNullFoo()</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> {</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">var</span> subject = <span class="kwrd" style="color: blue;">new</span> Subject();</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> <span class="kwrd" style="color: blue;">var</span> result = subject.DoWork(<span class="kwrd" style="color: blue;">null</span>);</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> Assert.Fail();</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> }</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;">
</pre>
This test does not pass in its current form. The thread reaches the Assert.Fail() and the test fails.<br /><pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;">
</pre>
<pre style="background-color: white; margin: 0em;"><span style="font-family: Consolas, Courier New, Courier, monospace; font-size: x-small;">
Assert.Fail failed.
at MyAssemblyTest.SubjectTest.DoWork_ShouldThrow_GivenNullFoo() in C:\... line 55
</span></pre>
If you're like me and seldom use the yield keyword, it takes a while to realise that the yield keyword triggers delayed execution of the entire method. Meaning the methods doesn't actually run until you access the collection that is returned. When the collection is accessed the exception is thrown.</div>
<div>
<br /></div>
<div>
Here's my modified unit test to cater for this:</div>
<div>
<br /></div>
<div>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> [TestMethod]</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> [ExpectedException(<span class="kwrd" style="color: blue;">typeof</span>(ArgumentNullException))]</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">public</span> <span class="kwrd" style="color: blue;">void</span> DoWork_ShouldThrow_GivenNullFoo()</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> {</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> <span class="kwrd" style="color: blue;">var</span> subject = <span class="kwrd" style="color: blue;">new</span> Subject();</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> <span class="kwrd" style="color: blue;">var</span> result = subject.DoWork(<span class="kwrd" style="color: blue;">null</span>);</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> result.Any();</pre>
<pre style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em;"> Assert.Fail();</pre>
<pre class="alt" style="background-color: #f4f4f4; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small; margin: 0em; width: 1904px;"> }</pre>
</div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-50754046781831339002015-08-09T19:27:00.001+12:002015-08-09T22:19:58.209+12:00Convert existing event handler invocations to C#6 Null Propagation<p>
Search for:
<pre name="code">if \(handler \!= null\)\s*\r?\n\s*\{\r?\n\s*handler\((?<args>.*?)\);\r?\n\s*\}</pre>
and replace using:
<pre name="code">handler?.Invoke(${args});</pre>
</p>
<p>
For example, this will be matched and replaced
<pre name="code" class="csharp">if (handler != null)
{
handler(this, new DialogResponseEventArgs(id, true));
}</pre>
<br/>
with this
<pre name="code" class="csharp">handler?.Invoke(this, new DialogResponseEventArgs(this.dialogCorrelationId, message.Response == ShellDialogButton.Cancel));
</pre>
</p>Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-14449305612526044272015-08-09T17:48:00.000+12:002015-08-09T22:19:47.775+12:00Converting existing code to use C#6 Expression Bodied Properties<h2>Converting all types of Simple Properties</h2>
<p>
Search for
<pre name="code">[^\S\r\n]+(?<accessor>\w+)(?<override> override | )(?<typename>\w+) (?<pname>.*?)\r?\n\s*\{\r?\n\s*get(\r?\n)*\s*\{\s*return (?<returnexpr>.*?);\s*\}\s*\}</pre>
and replace with
<pre name="code">${accessor} ${override}${typename} ${pname} => ${returnexpr};</pre>
</p>
<p>
For example the following properties will be matched and converted:
<pre name="code" class="csharp">public override string Description
{
get
{
return "The quick brown fox jumped over the lazy dog.";
}
}</pre>
<pre name="code" class="csharp">public string Description
{
get
{
return "The quick brown fox jumped over the lazy dog.";
}
}</pre>
<pre name="code" class="csharp">public string Description
{
get { return "The quick brown fox jumped over the lazy dog."; }
}</pre>
<pre name="code" class="csharp">public bool HasValue
{
get { return this.field; }
}</pre>
<pre name="code" class="csharp">public virtual IEnumerable<BudgetBucket> Buckets
{
get { return this.lookupTable.Values.OrderBy(b => b.Code).ToList(); }
}</pre>
<br/>
All the above are changed to the new syntax:
<pre name="code" class="csharp">public override string Description => "The quick brown fox jumped over the lazy dog.";</pre>
</p>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-23086992128876884812015-08-09T16:41:00.001+12:002015-08-09T17:10:37.877+12:00Converting existing code to use nameof() in C# 6Now with the new C#6 nameof operator, the use of ArgumentNullExceptions and ArgumentExceptions become more flexible and resistant to variable refactoring and renaming.
<br />
<h2>
ArgumentNullException</h2>
Here's a regex to search and replace in Visual Studio usage of ArgumentNullException:
Search for:
<br />
<pre name="code">throw new ArgumentNullException("(?<message>.*?)</pre>
Replace with:
<br />
<pre name="code">throw new ArgumentNullException(nameof(${varname})</pre>
<br />
For example this will replace this
<br />
<pre class="csharp" name="code">throw new ArgumentNullException("variable", "This variable cannot be null.");</pre>
with
<br />
<pre class="csharp" name="code">throw new ArgumentNullException(nameof(variable), "This variable cannot be null.");</pre>
<br />
<h2>
ArgumentException</h2>
Here's another regex to search and replace usage of ArgumentException:
Search for:
<br />
<pre name="code">throw new ArgumentException\("(?<message>.*?)", "(?<varname>.*?)"</pre>
Replace with:
<br />
<pre name="code">throw new ArgumentException("${message}", nameof(${varname})</pre>
For example this will replace this
<br />
<pre class="csharp" name="code">throw new ArgumentException("This argument is invalid for some weird reason.", "variable");</pre>
with
<br />
<pre class="csharp" name="code">throw new ArgumentException("This argument is invalid for some weird reason.", nameof(variable));</pre>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-45217400060033289652015-01-06T19:23:00.001+13:002015-01-06T19:23:40.899+13:00Calculating NZ Public Holidays<br />
I had to write a class to calculate the exact date of statutory holidays in New Zealand recently. It might not be the most efficient way, but it all works. The most up to date code is in <a href="https://github.com/Benrnz/BudgetAnalyser/blob/master/BudgetAnalyser.Engine/NewZealandPublicHolidays.cs">github</a>.<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">public class NewZealandPublicHolidays</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private static readonly List<Holiday> HolidayTemplates = new List<Holiday></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "New Years Day", Day = 1, Month = 1, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "New Years Holiday", Day = 2, Month = 1, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "Waitangi Day", Day = 6, Month = 2, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new EasterHoliday { Name = "Good Friday", Day = DayOfWeek.Friday },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new EasterHoliday { Name = "Easter Monday", Day = DayOfWeek.Monday },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "ANZAC Day", Day = 25, Month = 4, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "Christmas Day", Day = 25, Month = 12, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new FixedDateHoliday { Name = "Boxing Day", Day = 26, Month = 12, PushOutIfOnWeekend = true },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new IndexDayHoliday { Name = "Queen's Birthday", Day = DayOfWeek.Monday, Month = 6, Index = 0 },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new IndexDayHoliday { Name = "Labor Day", Day = DayOfWeek.Monday, Month = 10, Index = 3 },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> new DayClosestToHoliday { Name = "Auckland Anniversary", DesiredDay = DayOfWeek.Monday, Month = 1, CloseToDate = 29 }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> };</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public static IEnumerable<Tuple<string, DateTime>> CalcuateHolidaysVerbose(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var holidays = new Dictionary<DateTime, string>();</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> foreach (var holidayTemplate in HolidayTemplates)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposedDate = holidayTemplate.CalculateDate(start, end);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (holidayTemplate.PushOutIfOnWeekend && (proposedDate.DayOfWeek == DayOfWeek.Saturday || proposedDate.DayOfWeek == DayOfWeek.Sunday))</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> do</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposedDate = proposedDate.AddDays(1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> } while (proposedDate.DayOfWeek != DayOfWeek.Monday);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (holidays.ContainsKey(proposedDate))</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> holidays.Add(proposedDate.AddDays(1), holidayTemplate.Name);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> else</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> holidays.Add(proposedDate, holidayTemplate.Name);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return holidays.Select(h => new Tuple<string, DateTime>(h.Value, h.Key)).OrderBy(d => d.Item2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public static IEnumerable<DateTime> CalculateHolidays(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return CalcuateHolidaysVerbose(start, end).Select(t => t.Item2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private abstract class Holiday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public string Name { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public bool PushOutIfOnWeekend { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public abstract DateTime CalculateDate(DateTime start, DateTime end);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private class FixedDateHoliday : Holiday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int Day { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int Month { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public override DateTime CalculateDate(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> for (var year = start.Year; year <= end.Year; year++)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposed = new DateTime(year, Month, Day);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (proposed >= start && proposed <= end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return proposed;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> throw new InvalidOperationException(string.Format("Cannot find a suitable date between {0} and {1}", start, end));</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private class IndexDayHoliday : Holiday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public DayOfWeek Day { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int Index { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int Month { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public override DateTime CalculateDate(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> for (var year = start.Year; year <= end.Year; year++)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposed = ProposeDate(year);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (proposed >= start && proposed <= end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return proposed;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> throw new InvalidOperationException(string.Format("Cannot find a suitable date between {0} and {1}", start, end));</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private DateTime ProposeDate(int year)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposed = new DateTime(year, Month, 1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> while (proposed.DayOfWeek != Day)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var count = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> while (count != Index)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(7);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> count++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return proposed;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private class DayClosestToHoliday : Holiday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int CloseToDate { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public DayOfWeek DesiredDay { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public int Month { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public override DateTime CalculateDate(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> for (var year = start.Year; year <= end.Year; year++)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposed = new DateTime(year, Month, CloseToDate);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> switch (proposed.DayOfWeek)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Sunday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Monday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Tuesday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(-1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Wednesday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(-2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Thursday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(-3);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Friday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(3);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Saturday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (proposed >= start && proposed <= end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return proposed;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> throw new InvalidOperationException(string.Format("Cannot find a suitable date between {0} and {1}", start, end));</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private class EasterHoliday : Holiday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public DayOfWeek Day { get; set; }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public override DateTime CalculateDate(DateTime start, DateTime end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> for (var year = start.Year; year <= end.Year; year++)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> // first calculate Easter Sunday</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var day = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var month = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var goldenNumber = year % 19;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var century = year / 100;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var h = (century - century / 4 - (8 * century + 13) / 25 + 19 * goldenNumber + 15) % 30;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var i = h - h / 28 * (1 - h / 28 * (29 / (h + 1)) * ((21 - goldenNumber) / 11));</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> day = i - ((year + year / 4 + i + 2 - century + century / 4) % 7) + 28;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> month = 3;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (day > 31)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> month++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> day -= 31;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var proposed = new DateTime(year, month, day);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> switch (Day)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Friday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(-2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Sunday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Monday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> case DayOfWeek.Tuesday:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proposed = proposed.AddDays(2);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> default:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> throw new NotSupportedException("Only Easter Friday, Monday, and Tuesday are supported.");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> if (proposed >= start && proposed <= end)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return proposed;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> throw new InvalidOperationException(string.Format("Cannot find a suitable date between {0} and {1}", start, end));</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span>Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0tag:blogger.com,1999:blog-2612479901176767501.post-14050127221744226922014-08-10T17:22:00.001+12:002014-08-12T20:37:43.220+12:00How to use MsTest and NUnit Initialisation MethodsHow to use the available initialisation methods in both MSTest and NUnit can be a little confusing when learning how to write effective tests. Effective tests are designed, just like production code, shared code should be in one place (<a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>) and initialisation should be separate so to make tests less brittle. <br />
<br />
Imagine if every test constructs an object like so:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">var subject = new Foo();</span><br />
<br />
Also imagine that the Foo class has decent number of methods to test. One day a developer adds a parameter to the Foo constructor. Now many tests are broken and require the same change. If the initialisation code is in one place this would have been a fast fix:- these tests are less brittle.<br />
<br />
It would be handy to run some code before each test, some only once per class, and sometimes you need to initialise something before you run any tests.<br />
<br />
First up its important to note some semantic behavour of all <a href="http://en.wikipedia.org/wiki/XUnit">xUnit </a>frameworks.<br />
Every test will run in its own instance of the test class. No two tests share the same instance. When a test is finished running the instance is available for garbage collection. This means that any instance fields or properties are not shared between the tests in a class. This is by design and cannot be configured. This is mostly to isolate one test from another, but another reason for this is to support running tests in parallel on multiple threads, although MsTest and NUnit do not run tests in parallel by default, although they both can. <br />
<br />
<h2>
MsTest</h2>
In MsTest here's the low-down on the available initialisation methods:<br />
<br />
<ul>
<li>TestInitialize</li>
<li>ClassInitalize</li>
<li>AssemblyInitialize</li>
<li>TestCleanUp</li>
</ul>
<div>
These attributes are only recognised inside a class decorated with <span style="font-family: Courier New, Courier, monospace;">[TestClass]</span>.</div>
<h3>
<a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.testinitializeattribute.aspx">TestIntialize</a></h3>
<div>
<span style="font-family: Courier New, Courier, monospace;">[TestInitialize]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">public void TestInitialise() </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // Your initialisation code here</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
This method will run before every test. This is normally the best place to set up test data, mocks, and instantiate the subject under test. Sometimes, if possible, execution of the subject method can be done here as well so that each test only contains an assert. This has very similar to class's constructor, and both can be used, but its considered best practice to use the TestInitialise and not use constructors on Test Classes.<br />
<h3>
<a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.classinitializeattribute.aspx">ClassInitialize</a></h3>
<br />
<div>
<span style="font-family: Courier New, Courier, monospace;">[ClassInitialize]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">public static void ClassInitialise(TestContext context)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // Your initialisation code here</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<br />
<div>
This method will run once per class only, its very similar to a <a href="http://msdn.microsoft.com/en-us/library/vstudio/ms229018(v=vs.100).aspx">Type-Constructor</a>. This can be used to initialise any static fields and properties in the test class. The TestContext argument primarily allows output to the MsTest console log.</div>
<h3>
<a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assemblyinitializeattribute.aspx">AssemblyInitialize</a></h3>
<br />
<div>
<span style="font-family: Courier New, Courier, monospace;">[TestClass]</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">public class Global</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> [AssemblyInitialize]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> public static void AssemblyInitialise(TestContext context)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // Your initialisation code here</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
</div>
<div>
<br /></div>
<div>
This method will run only once per Unit Test Assembly per test run. Only one AssemblyInitialize method can exist per unit test assembly (or an exception is thrown when a test run starts). It is considered best practice to put this method into an easy to find Global class with no other tests. The TestContext argument primarily allows output to the MsTest console log. I personally find this handy for registering <a href="http://automapper.org/">AutoMapper </a>configuration before running any tests involving mappers.</div>
<h3>
<a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.testcleanupattribute.aspx">TestCleanUp</a></h3>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">[TestCleanup]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">public void TestCleanUp()</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // Your clean up code here</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
</div>
<br />
This is useful when you need to dispose any instance fields or properties, or reset anything back to a known state. Use with caution though, use if this method could be a "smell" that your tests are not isolated from dependencies like database and third-party services.<br />
Along with TestCleanUp you can also use the ClassCleanUp attribute. I'm not a fan of this, I've never had a good reason to use it. To me, it indicates use of a static dependency and that doesn't sit well with my style.<br />
<br />
<h3>
Here's how the Sequence unfolds</h3>
<div>
Lets use a test to show the sequence of method calls.</div>
<div>
<br /></div>
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestClass]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public class Global</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [AssemblyInitialize]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public static void AssemblyInitialise(TestContext context)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Assembly Initialise");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestClass]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public class SemanticTest</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private int counter;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> private Guid id;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public </span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SemanticTest</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.id = Guid.NewGuid();</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [ClassInitialize]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public static void ClassInitialise(TestContext context)</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Class Initialise");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestMethod]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void Test1()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.Write("Test1 ");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.counter++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Counter: {0} Id:{1}", this.counter, this.id);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestMethod]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void Test2()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.Write("Test2 ");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.counter++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Counter: {0} Id:{1}", this.counter, this.id);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestMethod]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void Test3()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.Write("Test3 ");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.counter++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Counter: {0} Id:{1}", this.counter, this.id);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestMethod]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void Test4()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.Write("Test4 ");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.counter++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Counter: {0} Id:{1}", this.counter, this.id);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestMethod]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void Test5()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.Write("Test5 ");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> this.counter++;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Counter: {0} Id:{1}", this.counter, this.id);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestCleanup]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void TestCleanUp()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("TestCleanUp " + this.counter);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [TestInitialize]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> public void TestIninitalise()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Debug.WriteLine("Test Initialise");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<br />
The output is:<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Assembly Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Class Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test1 Counter: 1 Id:fb05338c-b64e-4f30-bdbb-22f4c35749b1</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TestCleanUp 1</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test2 Counter: 1 Id:c207ef4b-83c1-4909-828b-10a7a43ef653</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TestCleanUp 1</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test3 Counter: 1 Id:07e5ddd0-6f3d-4e32-bd2d-2a9544e8bd51</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TestCleanUp 1</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test4 Counter: 1 Id:73e703a9-9c6b-4b02-8cb5-433c8c64167e</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TestCleanUp 1</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test Initialise</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Test5 Counter: 1 Id:37124412-e593-4ba2-8d28-6421d32117c8</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TestCleanUp 1</span><br />
<br />
Here its plain to see all tests ran in their own instance of the <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SemanticTest </span>class.<br />
<h2>
NUnit</h2>
<div>
All the above behaves identically in NUnit. Here are the equivalent attributes in NUnit as compared to MsTest.</div>
<div>
<ul>
<li>SetUp == TestIntialize</li>
<li>TestFixtureSetUp == ClassInitialize</li>
<li>SetUpFixture == AssemblyInitialize<br />Although in NUnit, SetUpFixture is scoped to a namespace not an entire assembly, which allows multiple SetUpFixture per assembly, but only one per namespace.</li>
<li>TearDown == TestCleanUp</li>
</ul>
</div>
<div>
<br /></div>
<br />
<br />
<h2>
See Also</h2>
<div>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assemblyinitializeattribute.aspx">MSDN</a></li>
<li><br /></li>
</ul>
</div>
Benhttp://www.blogger.com/profile/11272206013814656792noreply@blogger.com0