Demystifying the SDK Project

I am often, and rightfully, accused of living on the bleeding edge. It can be quite painful being there as ideas are not always fully flushed out, and tooling is often just not there yet. When Microsoft began the push towards .NET Core and .NET Standard, I knew this was an area that I needed to be. It was clear to me that this was a major shift that was going to make .NET development more appealing to a variety of developers, and businesses. As I set out to learn this new paradigm I both struggled and enjoyed the massive project system simplification that was introduced in the xproj format with a json configuration. For a variety of reasons though at the 11th hour Microsoft completely changed directions going back to the csproj and ditching the whole concept of a json configuration altogether. For months I struggled to understand what was going on. 

Why I struggled

There were a lot of reasons I struggled. The project system has a lot of loose but very important couplings with MSBuild. Frankly I had heard of msbuild, but I knew so little about it that I simply called it "The Compiler" (which is very inaccurate). Another reason that I struggled is that there isn't exactly a lot of documentation to explain how the project system works, or what elements mean. Then of course have you ever looked at the older style of csproj? There is a lot of nonsense xml going on there. You can kind of figure out some stuff. You can for instance figure out that any of your code files that need to be compiled needed a Compile tag to include it in the compilation, but what on earth is all of the other crazy stuff going on there?

Breaking Through

The new SDK Style projects really help make what's going on in the project system easier to understand and customize because it's not polluted by a lot of insanity. You don't need to add a bunch of duplicate settings for Debug vs Release since it's already assumed these build configurations exist and we have some standard assumptions about them, like Release builds need to be optimized, while Debug configurations need all of our debug symbols to be able to step into them. Then of course we make some standard assumptions like all of your code files should be compiled (known as File Globbing). What's left over is often a file that has a PropertyGroup with a single TargetFramework.

PropertyGroup vs ItemGroup

While this can get a little crazy when we start looking at creating custom build targets, we'll keep this simple for now. A PropertyGroup, is exactly what it sounds like. It's an area where you can declare Properties (think variable declarations), that will be used in the build process. There are a number of built in Properties (Well-Known & Common properties) that really come from msbuild, these include things like specifying the Assembly Name, where the build output should go, and some specialty variables that can be used to get things like the path to the Project File, or the current directory. While these properties can help us there are a number of other properties that can come into play from all over, and we can frankly make up properties as we see fit (more on that later).

Ok so now we have an idea about the PropertyGroup so what about ItemGroup's? Well ItemGroup's are all about grouping Items we need to do SOMETHING with. I admit that probably doesn't clarify what I mean. So let's look at the Xamarin Essentials csproj. It's a good use case where the decision was made to turn off the default file globbing.

  <ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
    <Compile Include="**\*.netstandard.cs" />
    <Compile Include="**\*.netstandard.*.cs" />
  </ItemGroup>
  <ItemGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
    <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.1.5" />
    <SDKReference Include="WindowsMobile, Version=10.0.16299.0">
      <Name>Windows Mobile Extensions for the UWP</Name>
    </SDKReference>
    <Compile Include="**\*.uwp.cs" />
    <Compile Include="**\*.uwp.*.cs" />
  </ItemGroup>

There is a lot going on in this snippet so let's break this up. First you'll notice some conditions on these ItemGroup's. You do not have to ever use a Condition, but you can also put a Condition on Any Element. As I mentioned before, the EnableDefaultCompileItems Property was set to false, meaning that when this project is built, it will not compile ANY of the code unless we do something to include code. What you see here is that they have adopted a practice in which each file contains a platform identifier. This then allows them to have a condition in which the TargetFramework is evaluated and determine which C# files should be included in the compilation. Often times you may see multiple ItemGroup's in a csproj, with each Group containing a single set of Items, for instance only Embedded items, or Compile items, Project References. You'll notice here though that the ItemGroup can contain any set of Items, as the UWP ItemGroup contains a PackageReference, an SDKReference for Windows Mobile, and adds the UWP C# code.

Multi-Targeting

Perhaps one of my favorite features of the SDK Style Project is that it makes Multi-Targeting that much easier. As you may have noticed in the snippet above from the Xamarin Essentials csproj, they have a single Project that targets both UWP and netstandard. Honestly, Microsoft only get's partial credit here. The new Project system introduces the ability to specify TargetFrameworks rather than a single TargetFramework if we so choose. Unfortunately the team only thought about Full Framework Targets like net45 and netcore/netstandard targets, which is why I say they get partial credit. For the Xamarin Developer (or even the 3 UWP developers out there), this gets really frustrating. Luckily the community has Microsoft MVP/RD Oren Novotny, who developed a completely custom SDK that ships via NuGet which introduces support for all kinda of new targets including UWP, Xamarin iOS, Android, Mac, and even Tizen and WPF.

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
    <!-- Standard SDK Sytle Project that doesn't support cool targets -->
    <<TargetFramework>netstandard2.0</TargetFramework>
</Project>

So what do we have to do to start Multi-Targeting more fun targets as a Xamarin Developer? Well it's actually pretty simple, again thanks to Oren, the Microsoft team added support so that all we need to do is replace the value in the Sdk attrubute of the Project. To start with let's look how you might do this if you only care about a single Project. 

<Project Sdk="MSBuild.Sdk.Extras/1.6.47" ToolsVersion="15.0">
    <!-- Single Multi-Targeting Project... You control the version here as part of the Sdk string -->
    <TargetFrameworks>netstandard2.0;xamarin.ios;xamarin.android;uwp10.0.16299</TargetFrameworks>
</Project>

Suddenly you have the ability to create a single project that targets all of the platforms you want. But what about those cases where you still need to break code up into multiple projects? Well again it's very simple. Simply add MSBuild.Sdk.Extras as the Sdk value and then drop in a file called global.json next to your solution. (NOTE: You'll notice that this is what I've done for Prism)

{
    "msbuild-sdks": {
        "MSBuild.Sdk.Extras": "1.6.47"
    }
}

Of course you could ask why should you care about Multi-Targeting? Well have you ever noticed that you have to do some crazy thing like:

global::SomeProject.Platform.CoolRenderer.Init();

Suddenly you're referencing a bunch of Init methods that look like this:

public static void Init()
{
    // The Linker Sucks
}

public static void Init()
{
    // Watch the build is going to warn me about a variable I'm not actually using for anything....
    var a = DateTime.Now;
}

To me this has always been code smell. Ultimately the real reason you're having to do this so often is to ensure that the Linker sees an actual reference in code that goes into the Platform specific binary. This was a problem with the old project system since we had to have a sharable project (PCL), and then platform projects each of which needed to be bundled into a single NuGet. By Multi-Targeting you've already made references into the assembly to keep it from being stripped out reducing the legwork you need to do, to tell the Linker to pay attention to something else.

Multi-Targeting Snafu

Multi-Targeting is a fantastic tool. Unfortunately for those working on a Mac there is a little bit of legwork you need to do. Visual Studio Mac does not currently support Multi-Targeting projects. It really should, and is very overdue in my opinion. If you agree, I suggest pinging Jordan Matthiesen (@JMatthiesen) to let him know this needs to be a top priority for the team (and in the next alpha release)... I did say there is a little bit of legwork you need to do though, I never said it doesn't work. MSBuild LOVES Multi-Targeting so you can build these projects from the command line all day long. In fact, as one of the nice things that Mac developers get for FREE, both MSBuild and NuGet are added to your PATH when you installed Visual Studio Mac making building from the command line very easy. Generally for these Multi-Targeting projects I simply move my workflow into Visual Studio Code where I can easily write code and build from the integrated terminal.

I should probably admit the pain doesn't entirely stop there. UWP is simply an unresolvable target. The solution? Earlier I mentioned Conditions can be applied to any element, which includes the TargetFramworks element. If you lookup the well known MSBuild variables there is an OS variable. Unfortunately it's a bit simplistic meaning you're not going to figure out if you're on a Mac or Ubuntu or Centos, or Windows 7 or Windows 10... but you can at least figure out one thing... are you on Windows or not. So what does that look like:

<Project Sdk="MSBuild.Sdk.Extras">
    <PropertyGroup> 
        <TargetFrameworks>netstandard1.0;netstandard2.0;Xamarin.iOS10;MonoAndroid71;MonoAndroid80;MonoAndroid81;uap10.0.16299</TargetFrameworks>
        <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.0;netstandard2.0;Xamarin.iOS10;MonoAndroid71;MonoAndroid80;MonoAndroid81;</TargetFrameworks>
    </PropertyGroup>
</Project>

Packaging

Some of you may be wondering why you should be packaging your code? I've talked with a number of developers over the years who are engaged in a process in which for each release the entire code base is pulled from source control and built and released in one go. I've heard some interesting arguments for the practice, though I completely disagree with them. To be clear obviously something has to be built, but all of your common support libraries should be built and packaged as they are updated. There are actually a few benefits to this:

  1. This reduces build times... Imagine you have a single support library that's used in 5 applications that are released across your organization. This literally eliminates 4 completely unnecessary builds of that single project. Of course the reality is that you probably have a bunch of support libraries making the results that much greater.
  2. Versioning... It is a little scary when you think about it, but so many companies NEVER version their code. I have literally seen projects that started 15 years ago that are still on version 1.0.0.0 (from the template). In my experience these are companies that are probably storing your passwords in clear text, prefer http over https, and think a 56k modem is high speed internet instead of a painful memory of the 1990's. If you aren't versioning your code you really have no idea when a problem was introduced, if a problem has been fixed, or a regression has been made... you only have guesses.
  3. Garbage In -> Garbage Out... because you've built and shipped that project independent of the rest of your monolithic applications, it means that you have had a chance to validate the code base before it finds it's way into use by others in your development team or a production environment. For many (realistically) this means that you are protecting yourself from that developer who checked in code that doesn't build. For others it means that you have ensured that all of your unit tests for that project have both run and passed.
  4. Testability... I know what you're thinking, you're perfect, and so are the rest of the developers on your team. I totally understand, that's why I like to wear the shirt declaring "I don't always test my code, but when I do, I do it in Production". But for that time when maybe you forgot to update that one repo that you aren't responsible for, but that repo is required to build the project you are responsible for. The simple truth is as a .NET developer you're used to looking at the package manager for Updates. When your support libraries are packaged and available to your team via a private or public NuGet feed, it becomes easy to discover that an update is available. Because the discoverability is actually going up, it means that the entire team really has a better opportunity to test the code in development before it ever sees production.

How do you get started?

Maybe you didn't need convincing, maybe you just need to know how to get started. Well for starters, let's completely toss out the idea of using a nuspec. They're annoying and frankly if you're multi-targeting... they are error prone. There are still a few monolithic projects out there like Xamarin.Forms that still require the use of a nuspec (largely due to the issues around Packing that the NuGet team needs to fix/implement), but the reality is that if you're using a Sdk Style project you probably don't need it.

Earlier I mentioned that you could completely make up properties to put in the PropertyGroup of your csproj. Well when the Sdk Style projects were created, the folks at Microsoft decided to make up some new Properties to help with the very common task of packaging your projects. Many of these properties can be found at the links below. Some are a little harder to discover such as the GeneratePackageOnBuild property. By default this is false, however when you set this to true, all you need to do is build your project and each build will generate a new NuGet package for any packable projects in your solution. You'll find there is no right or wrong way as much as there is a way that makes sense for the project you are working on. Many of my projects, including Prism include a Directory.build.props in the solution directory, this allows me to set this value in a single place. Since IsPackable is true by default this means that you need to have some logic to set IsPackable to false on projects that should not be packed such as Tests and Samples.

Project References... Package References Oh My

You may know a little bit about a Project Reference and Package Reference. The difference here being that a Package Reference comes in from a NuGet feed, while a Project Reference is a Reference to a local project in the file system. So what happens then when you want to build and package a project? What happens to those Project References? A friend of mine recently asked if I could come take a look at a project he had been working on. Well every Project Reference is assumed to be a Reference that will be needed by the generated package. This means that there is no need to have some crazy conditional includes for a Package configuration.

<Project Sdk="MSBuild.Sdk.Extras">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup Condition=" $(Configuration) != 'NuGetRelease' ">
        <ProjectReference Include="../AnotherProject/AnotherProject.csproj" />
    </ItemGroup>

    <ItemGroup Condition=" $(Configuration) == 'NuGetRelease' ">
        <PackageReference Include="AnotherProject" Version="$(Version)" />
    </ItemGroup>
</Project>

All you actually need is just your ProjectReference. When the project is built, this assumes that it is being Packed and will actually pick up whatever the version number is that, that specific project was packed with.

<Project Sdk="MSBuild.Sdk.Extras">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <ProjectReference Include="../Foo/Foo.csproj" />
    </ItemGroup>
</Project>

Because it will pick up the other project automatically it means that you just need to ensure that the Pack target is invoked.

> dotnet pack MyProject.csproj -c Release
> msbuild MyProject.csproj /p:Configuration=Release /t:pack

Earlier I mentioned the GeneratePackageOnBuild element which is false by default. All we need to do is set this to true like in the following example or add it to our Directory.build.props file and EVERY build will now generate a package automatically.

<Project Sdk="MSBuild.Sdk.Extras">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    </PropertyGroup>
</Project>

Directory.build.props

For those paying attention, you've heard me mention the Directory.build.props... this is one of my favorite files, and in some ways a replacement for the nuspec*, in other ways it's just something I use to make my DevOps processes smoother. This is a slightly refined version of what I have published previously.

<Project>
  <PropertyGroup>
    <Product>$(AssemblyName) ($(TargetFramework))</Product>
    <DefaultLanguage>en-US</DefaultLanguage>
    <Authors>Your Name Here</Authors>
    <Copyright>© $([System.DateTime]::Now.Year) Your Name Here</Copyright>
    <PackageIconUrl>Uri to an icon image (png)</PackageIconUrl>
    <PackageLicenseUrl>Uri to the license</PackageLicenseUrl>
    <PackageProjectUrl>Uri to the project</PackageProjectUrl>
    <RepositoryUrl>Uri to clone the project</RepositoryUrl>
    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
    <RepositoryType>git</RepositoryType>
    <!-- Root control Version Prefix -->
    <VersionPrefix>1.0.0</VersionPrefix>
  </PropertyGroup>

  <!-- CI Helpers -->
  <PropertyGroup>
    <PackageOutputPath>$(MSBuildThisFileDirectory)/Artifacts</PackageOutputPath>
    <PackageOutputPath Condition=" $(BUILD_ARTIFACTSTAGINGDIRECTORY) != '' ">$(BUILD_ARTIFACTSTAGINGDIRECTORY)</PackageOutputPath>
    <IsPackable Condition=" $(ProjectName.Contains('Sample')) ">false</IsPackable>
    <IsPackable Condition=" $(ProjectName.Contains('Test')) ">false</IsPackable>
    <GeneratePackageOnBuild>$(IsPackable)</GeneratePackageOnBuild>
    <IS_PREVIEW Condition=" $(IS_PREVIEW) == '' ">false</IS_PREVIEW>
    <IS_RELEASE Condition=" $(IS_RELEASE) == '' ">false</IS_RELEASE>
    <VersionPrefix Condition=" $(BUILD_BUILDNUMBER) != '' ">$(VersionPrefix).$(BUILD_BUILDNUMBER)</VersionPrefix>
    <VersionSuffix>ci</VersionSuffix>
    <VersionSuffix Condition=" $(IS_PREVIEW) ">pre</VersionSuffix>
    <VersionSuffix Condition=" $(IS_RELEASE) "></VersionSuffix>
  </PropertyGroup>
</Project>

You'll notice that in this Directory.build.props file I have split it into two PropertyGroups to make it a little easier to read. So let's take a look at the first PropertyGroup.

  • Product: The Product line here gets updated to include both the Target Framework and Assembly Name instead of just the Assembly Name. This is particularly helpful for multi-targeting projects as it can help identify which framework specifically was being used when an error occurred.
  • You'll notice several elements here that contain placeholders for Uri's for specific to your project, and your name. These are all elements that came from the nuspec which are now taken care of and will be uniform across your entire solution helping to ensure that you don't have to duplicate values all over. 
  • VersionPrefix: This is the root version number that I want to control. Every single build will start with this version string.

Ok great, now let's take a little closer look at what's going on in the CI Group.

  • PackageOutputPath: Maybe you have just one project, or maybe you have 10 that are built and packaged for your solution. Even with one, it can get a little tedious to have to drill down into the Project's output folder {Path To Project}/bin/{Build Configuration} each time you want to get the generated NuGet. When you have multiple projects though this gets really annoying. By setting this value we ensure that all of the packages are created in a common location making it easier to find. By default we are creating an Artifacts folder under the current directory (where the Directory.build.props is located). On VSTS however we are defaulting that location to be in the Artifact Staging Directory defined by VSTS.
  • IsPackable: By default this is true, so we have a check to see if the Project Name contains either the word Test or Sample. If it contains either one we mark the project as NOT packable.
  • GeneratePackageOnBuild: By default this is false meaning you either need to explicitly invoke the Pack target. By setting this to true we will generate the Packages on each build. If this is too much, or you don't want to accidentally ship a Debug build, you could add a condition to only set it to true when the build Configuration is Release.

*NOTE:
Just to prevent some confusion here, there is still a nuspec in the process, only it is automatically generated by the build task rather than you having to maintain it as part of your project.

Helpful Links

For more information and to see how I build many of my tools and support libraries see this post I wrote on the new Project Format. Still have questions feel free to leave a comment or reach out on Twitter.

.NET Standard & the New Project Format for Xamarin Developers

.NET Standard has really changed the ballgame for .NET Developers. In large part because the entire project system has experienced a revamp. Lately I've found myself really encouraging developers to update their PCL libraries to .NET Standard 2.0. For developers who haven't made the jump it's easy to find yourself saying "no we can't do it". In reality it doesn't take as much effort as you think it does to update your projects. Why should you update your projects though? Well for starters PCL is painful, you lookup how to do something only to find out that it's not supported and sometimes there's no workaround. With .NET Standard the missing API's that lead to weird workarounds is a thing of the past.

Upgrading

Upgrading really isn't as hard as you may think. For starters your csproj is going to start out about as simple as:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
</Project>

Then of course we need to start adding in your dependencies. Now this is where it gets "Hard". It's hard because it means you need some familiarity with your project. You need to know what are the top level dependencies that your project has. For example if you're using Prism there are generally 3 Prism packages you're referencing, Prism.Core, Prism.Forms, and Prism.{Some Container}.Forms. It's only the last one that you actually need to reference in the new project format. You can of course add this from either Visual Studio or Visual Studio Mac or update it manually so that your project file now looks like:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Prism.DryIoc.Forms" Version="7.0.0.396" />
  </ItemGroup>
</Project>

Assuming you wanted to get started with Prism for Xamarin Forms this would be all you would actually need as all three Prism packages are automatically brought in along with Xamarin Forms. Now let's say that you wanted to target a newer version of Xamarin Forms than 2.5.0.122203, such as the 3.0 preview that's now available. You simply need to add a new PackageReference for that version of Xamarin Forms or install it in the IDE's Package Manager.

That may seem too easy, and it is. Of course you need to make some more changes. You'll need to find the packages.config or project.json and delete those files... If you have a standard Properties/AssemblyInfo.cs you'll need to go ahead and send that one to the trash as well. With that your project is upgraded, and you're wondering why you didn't do this sooner....

Multi Targeting

Around 5 years ago I first started trying to Multi-Target. My earliest attempts were pretty bad with a csproj file for each framework I wanted to target, all part of the same solution, and it generally resulted in build errors due to file locks as I had no clue how the build system worked back then. Honestly I've never found much documentation that made it very easy, and while I eventually figured out I could do lots of MSBuild trickery to make it work, and then manually develop a nuspec to pack my library, it was always really painful. The new Project system gives us some real advantages for Mutli-Targeting that make it a real breeze.

I suppose though I should start with why on earth should you multi-target... and when would you want to? If you're a Xamarin developer chances are you want to Multi-Target. Internally and for all of my clients I generally start off with a common library. This is something that is really helpful to give me extensions, and custom controls that I may want to use across all of my apps or components like a Prism Module. A lot of that code is truly portable and I could easily handle it with a simple netstandard2.0 class library. However sometimes I'm implementing Platform Effects and Renderers for my controls that instantly require that I have a native binary for my iOS and Android projects. This is where multi-targeting really becomes very powerful. By Multi-Targeting I maintain a single Project which generates a single binary, native to the platform I need to target. Now if we expand on the basic project structure we saw above and now update our csproj to look like the following we can target both .NET Standard 1.3 & 2.0, along with Android, iOS, Mac, and UWP. It's worth noting that the non .NET Standard targets are really getting a lot of help due to the MSBuild.Sdk.Extras package from Oren Novotny.  

<Project Sdk="MSBuild.Sdk.Extras/1.5.4" ToolsVersion="15.0">
  <PropertyGroup>
    <TargetFrameworks></TargetFrameworks>
    <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard1.3;netstandard2.0;Xamarin.iOS10;Xamarin.Mac2.0;MonoAndroid80;uap10.0.16299</TargetFrameworks>
    <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0;Xamarin.iOS10;Xamarin.Mac2.0;MonoAndroid80</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup>
    <Compile Remove="**/Platform/**/*.cs" />
    <None Include="**/Platform/**/*.cs" />
  </ItemGroup>
  <ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
    <None Remove="**/Platform/Droid/**/*.cs" />
    <Compile Include="**/Platform/Droid/**/*.cs" />
  </ItemGroup>
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
    <None Remove="**/Platform/iOS/**/*.cs" />
    <Compile Include="**/Platform/iOS/**/*.cs" />
  </ItemGroup>
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac')) ">
    <None Remove="**/Platform/macOS/**/*.cs" />
    <Compile Include="**/Platform/macOS/**/*.cs" />
  </ItemGroup>
  <ItemGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
    <None Remove="**/Platform/UWP/**/*.cs" />
    <Compile Include="**/Platform/UWP/**/*.cs" />
  </ItemGroup>
</Project>

So what's going on here anyway? Well for starters we're establishing some conventions for our code. We are saying that anywhere in our project that we have a folder named Platform we are going to change the inclusion of those files from Compile to None. This means that the IDE will display our code while MSBuild will ignore our code. Then, we start conditionally adding code back in so that when MSBuild is compiling for iOS and it encounters code that has a path that includes Platform/iOS, that code will be added back in for compilation. 

Generating a NuGet

If you're trying to generate a library that you can easily consume in your projects, or if you're trying to make it available for the community at large, these new SDK style projects are make generating a NuGet easier than ever. You just need to worry about what targets you want to compile for, and the NuGet largely takes care of itself with very little that we actually need to add. It's really just a few properties that we need to add to our project. Of course, if you take a look at any of my projects you'll notice a recurring theme, most of my NuGet configurations aren't even in the project file at all. Along the way I've come to realize the power of a file called Directory.build.props. This is a little bit of a magic file. If it exists anywhere from the solution folder to your project folder it will automatically be picked up by MSBuild. 

Looking at a real world example

Prism has more than 15 NuGet packages that have to generated on every build. Honestly for WPF we still use the older style projects which is a painful process, but the rest of the projects all share a lot of common logic.

  • If there is a project that isn't a test project we don't want it to Generate a NuGet. 
  • The package authors are always going to the members of the Prism Team.
  • The source is always located on GitHub in the same repository.
  • We always want to provide symbols packages.

Without using the Directory.build.props in our solution directory we would have to replicate this information in every single project file. 

Setting your project up for NuGet Packaging

If you want to pack your project all you really need to do is to add the following Directory.build.props to your project:

<Project>
  <PropertyGroup>
    <Product>$(AssemblyName) ($(TargetFramework))</Product>
    <NeutralLanguage>en</NeutralLanguage>
    <Authors>Your Name Here</Authors>
    <VersionPrefix>1.0.0</VersionPrefix</VersionPrefix>
    <VersionPrefix Condition=" '$(BUILD_BUILDID)' != '' ">$(VersionPrefix).$(BUILD_BUILDID)</VersionPrefix>
    <IS_PREVIEW Condition=" '$(IS_PREVIEW)' == '' ">false</IS_PREVIEW>
    <IS_RELEASE Condition=" '$(IS_RELEASE)' == '' ">false</IS_RELEASE>
    <VersionSuffix>ci</VersionSuffix>
    <VersionSuffix Condition=" $(IS_PREVIEW) ">pre</VersionSuffix>
    <VersionSuffix Condition=" $(IS_RELEASE) "></VersionSuffix>
    <PackageProjectUrl>https://github.com/USER/PROJECT_NAME</PackageProjectUrl>
    <PackageLicenseUrl>https://github.com/USER/PROJECT_NAME/blob/master/LICENSE</PackageLicenseUrl>
    <RepositoryType>git</RepositoryType>
    <RepositoryUrl>https://github.com/USER/PROJECT_NAME</RepositoryUrl>
    <IncludeSymbols>True</IncludeSymbols>
    <IncludeSource>True</IncludeSource>
    <PackageOutputPath>$(MSBuildThisFileDirectory)Artifacts</PackageOutputPath>
    <PackageOutputPath Condition=" '$(BUILD_ARTIFACTSTAGINGDIRECTORY)' != '' ">$(BUILD_ARTIFACTSTAGINGDIRECTORY)</PackageOutputPath>
    <IsTestProject>$(MSBuildProjectName.Contains('Test'))</IsTestProject>
    <GenerateDocumentationFile>!$(IsTestProject)</GenerateDocumentationFile>
    <GeneratePackageOnBuild>!$(IsTestProject)</GeneratePackageOnBuild>
  </PropertyGroup>
</Project>

 

Prism Quickstart Templates

Quickstart Templates for Prism Forms

So you had this great idea for an app... maybe you spent weeks planning with your team or with your client. The day finally comes to create the project. Suddenly you realize that we have this new .NET Standard thing and you want to take advantage of that too. You remember you need icons, you want a Splash Screen... all of the things that go into making an App. For anyone who has done this, you know there's a lot of heavy lifting to be done. In all honesty you could easily spend several days just getting a new project from File -> New to something that you're ready to start working on.

It was for this and so many other reasons that I realized we need better templates, and we need something that can help us whether we're on a Mac or on PC.

There are some very basic things left out of the base Xamarin & Prism Templates. For some developers these just require time that could be better spent on something else, and for other developers it leads them down a path of poor design.

Features

Why should you use these templates? Well here are a couple bullet points:

  • Gets you off the ground following Best Practices
  • *Starts you off using Prism for Xamarin Forms with either DryIoc or Unity for Dependency Injection
  • Already has all of your App Icons added so all you need to do is drop in the replacement files from File Explorer or Finder. There is also a link in there so you can see how to get all of your icons generated for you correctly in all of the sizes with all of the correct naming.
  • Starts you off with some base colors to use for your project with information of how to develop a Material Design pallet for your application.
  • By default it already has everything you need for Localizing strings in XAML
  • It's cross platform, using dotnet new you get the same experience from the command line whether on Mac or PC.
  • Item templates to generate Views and ViewModels with support for the common Xamarin Forms pages as well as PopupPages
  • Makes it easier to inject variables at Build to protect sensitive project secrets.
  • Quickstart with a fully working Todo app working with in memory data, Realm, or Azure Mobile Client
  • Included config for MFractor

*NOTE: Autofac & Ninject will be reintroduced once Prism 7 has a public preview.

Best Practices

App development can be simultaneously fun and frustrating. So many developers love Xamarin Forms because it really narrows down the number of API's you need to work with. What it doesn't do is eliminate your need to understand the platform your application will run on. These templates will not eliminate that need either, however they do set you down the right path, with some basic things like a splash screen so your user will at least see something while your app loads. Also included by default is the MVVM Helpers library from James Montemagno so that you can use his ObservableRangeCollection<T> to reduce the notifications sent to the UI when updating or replacing multiple items in your collection. If you don't use it MVVM Helpers you still get a ViewModelBase that will incorporate these properties as well as well as IDeviceService and virtual implementations of INavigationAware, IActiveAware, and IApplicationLifecycle.

Prism

Continuing really with Best Practices, these templates use Prism for Xamarin Forms. Currently the templates support DryIoc and Unity for Dependency Injection. Autofac and Ninject will be added back in once there is a publicly available release of Prism 7.

TabbedPages

Working with TabbedPages has traditionally been one of the more challenging areas of working with Prism. With the QuickStart template this challenge disappears. The template includes two base implementations for a TabbedPage, the PrismTabbedPage and the DynamicTabbedPage. If your TabbedPage inherits from PrismTabbedPage, it will automatically pick up and pass on the NavigationParameters to the Child Pages allowing you to properly initialize them. If you use the DynamicTabbedPage you only need to reference it in your Navigation URI and pass in variables like:

NavigationService.NavigateAsync("TabbedPage?tab=ViewA&tab=ViewB&tab=ViewC");

But it actually gets a little better than that because not only does it pick up tabs but you can also do some deep linking like:

NavigationService.NavigateAsync("TabbedPage?tab=NavigationPage/ViewA/ViewD&tab=NavigationPage/ViewB&tab=ViewC");

This means you can actually support scenarios where your actual tabs contain their own NavigationStack independent of the rest of the application.

App Icons

Applications need a lot of icons and really the templates out there don't do a very good job with App Icons. Most templates out there just leave your deployed app with a broken icon image and require some time getting the icons setup. These templates start you off with icons for your Android and iOS projects. But more than that is the GettingStarted document included in the template gives you the information you need to be able to quickly and efficiently generate a full icon set that you can drop in to replace the default icons with your own icons. Following along with Best Practices, you'll find that the iOS project is using the newer appiconset approach with the app icons as ImageAssets rather than having them in the Resources folder as BundleResources. Similarly on Android you'll find the app icon's are all in the mipmap folders rather than drawable.

Material Design

While my purpose is not to teach Material Design, there are some basics that we can easily include in the template to get you started down the right path. That includes a basic color pallet with information of how to choose new colors. There is also already a Style defined for you to customize the look and feel of a NavigationPage using those colors.

Localization

One of the things I hear over and over, developers in the United States forget some people don't speak English. For most US based dev's Localization is a complete and total afterthought. Interestingly nobody seems to have thought previously that maybe we should provide a template that assumes you want your application easily consumable by people in another country who speak another language. The quickstart template comes complete with all of the helper classes you need to get Localization working in the application and gets the Localization implemented with the DI container using Prism's IPlatformInitializer. There is also a XAML extension provided so all you need to do is include the namespace in your XAML file and use it as needed. The app of course also includes a single Resx file to get you started. You simply need to add the string resources you want to use in your application.

Cross Platform

It might seem weird when we're talking about Xamarin, but seriously it gets frustrating when we're working with a Cross Platform technology and then the developer experience is completely and totally different depending on which platform you are on. One of the most common issues we can see from a templating standpoint is that if I click File -> New, it shouldn't matter whether I'm on Mac or PC, I should be able to decide if I want my project to include iOS, Android, UWP. That's not to say I don't understand that some time may be needed before you can build a UWP app on Mac, but you should at least be able to have the platform as an option so you can work on the codebase from either platform.

Item Templates

Also included are some Item Templates custom built for the included project templates. There are two basic types of Item Templates, Pages and Services. Note that there is currently no way for the dotnet templating engine to pick up what your base namespace is, so you do have to specify this from the command line.

Pages

By default when you call dotnet new prismitem you will get a page. It's assumed that you're using the ViewModelBase from the included Project templates. You can add flags to specify whether you want to implement INavigatingAware, INavigatedAware, INavigationAware, IActiveAware, or IDestructible. By default it implements INavigationAware. There is also a flag to indicate if the page is a Tabbed Child which will automatically implement IActiveAware and INavigatingAware. Currently supported page types include ContentPage, MasterDetailPage, TabbedPage (which inherits from the Quickstart PrismTabbedPage), and PopupPages.

Samples

dotnet new prismitem -namespace MyAwesomeApp -n LoginPage
dotnet new prismitem -namespace MyAwesomeApp -page PopupPage -n SomePage
dotnet new prismitem -namespace MyAwesomeApp -n CustomerDetailPage -child

Services

Chances are your app is probably using some sort of service and if you like testability like I do, then you'll really appreciate that you can create a service with Mock class that will automatically be picked up by the Quickstart template simply by building with the Mock configuration. 

Samples

dotnet new prismitem -item Service -namespace MyAwesomeApp -n LoginService
dotnet new prismitem -item Service -namespace MyAwesomeApp -n LoginService -mocks false

Secrets

All apps have secrets and other variables that we just don't want checked into source control. To better assist with this, the template includes some helpers that will regenerate the Secrets.cs with sensitive variables you want in your codebase. Both the Secrets.cs and secrets.json files have also been added to the included .gitignore, so you can finally develop apps without having to tackle the issue of keeping app secrets out of SCM.

secrets.json

{
  "AuthClientId": "{Your App Client Id}",
  "AppServiceEndpoint": "https://appservicename.azurewebsites.net/"
}

Secrets.cs

namespace YourProject.Helpers
{
    internal static class Secrets
    {
        internal const string AuthClientId = "{Your App Client Id}";

        internal const string AppServiceEndpoint = "https://appservicename.azurewebsites.net/";
    }
}

PropertyChanged.Fody

Part of the MVVM pattern is working with INotifyPropertyChanged. Unfortunately the code can get a bit tedious. 

public class ViewAViewModel : BindableBase
{
    private string _title;
    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }

    private MyModel _selectedItem;
    public MyModel SelectedItem
    {
        get => _selectedItem;
        set => SetProperty(ref _selectedItem, value, onChanged: OnSelectedItemChanged);
    }

    private void OnSelectedItemChanged()
    {
        // Do Stuff
    }
}

With PropertyChanged.Fody already included our ViewModels and other Observable objects simply become:

public class ViewAViewModel : BindableBase
{
    public string Title { get; set; }

    public MyModel SelectedItem { get; set; }

    private void OnSelectedItemChanged()
    {
        // Do Stuff
    }
}

Mobile Center

Also bundled into this template is support for the Azure Mobile Center. While this is an opt in feature you can pass in your App Secret for iOS and/or Android from the command line with everything already wired up to send your analytics and crash data to the Azure Mobile Center. This includes an implementation of ILoggerFacade that will create a Mobile Center Analytics Event.

Data Providers

Apps today are so often really connected apps. The Quickstart Template provides you a fully functional TodoApp with the option to use either the Azure Mobile Apps Client with AzureMobileClient.Helpers or to use Realm. Either data provider will start you out with the ability to quickly develop your app with full online/offline sync with the bare minimum of configuration. 

Azure Mobile Client

In addition to simply using the Azure Mobile Client you can additionally decide if you want to use anonymous authentication or if you will require some sort of authentication. If you choose an authentication provider, the Quickstart will provide you base classes for everything you need to get started. This includes scaffolding for custom authentication sources and a fully working implementation for Azure Active Directory B2C with support coming for AAD, Google, Facebook and Microsoft Accounts.

Plugins

Because the full working app uses a PopupPage for the TodoItem detail page, the Quickstart includes Prism.Plugin.Popups, and also optionally includes a Barcode Scanning Service utilizing ZXing.Net.Mobile and is fully registered and configured.

Getting Started

To get started with the templates it's recommended that you install version 2.0 pre3 of the dotnet cli as this contains several fixes in the templating engine. Once that is installed you can install the templates by using the following commands in your cli.

dotnet new -i "Prism.Forms.QuickstartTemplates::*"

You should see the prismitems and prismformsempty templates. The Quickstart template is grouped with the empty template, though you may not see it listed it is still there.

# See the Help and options for the Quickstart Template
dotnet new prismforms -h

#Create your first quickstart
mkdir Contoso.AwesomeApp
cd Contoso.AwesomeApp
dotnet new prismforms -id com.contoso.awesomeapp -fr netstandard1.6 -mc -ios-secret 
     "{your ios secret}" -android-secret "{your android secret}" -data AzureMobileClient 
     -auth AADB2C -client-id "{your AADB2C application id}"
#Be sure the B2CName in secrets.json matches your AAD B2C name

 

A Dot Net Developer on a Mac

Recently I had a chance to attend a meetup here in San Diego. To be honest, around other developers I sometimes feel like the odd man out. I mean here I am a C# Dot Net developer, and I'm showing up to code with a Mac. It really wasn't all that long ago that you might look at a "C# Developer" doing something like that, as if they were on crack. But the times they are changing. In fact, at that meetup the odd man out, was the dev with a Windows Laptop.

I often have conflicting feelings about my development. On the one hand, I absolutely LOVE Visual Studio. As far as I'm concerned it hands down beats every other IDE out there. As I mentioned though, when I'm on the go, more often than not I'm working off my Mac. So then how on earth does a Dot Net developer work on a Mac. Well truthfully if it wasn't for all of the hard work coming from Microsoft the past few years I'm not sure it would be anywhere near as pleasant as it is now.

I realize that there are still a lot of short comings with NetStandard, for one it is completely useless for Xamarin libraries that contain XAML files. That said the work that has been done around the NetStandard has been instrumental in making Dot Net even a citizen in non-Windows environments. Part of the problem with being a Dot Net developer outside of Windows is that the tooling was heavily integrated with Windows, so it wasn't as easy as install Mono... go...

I have been gleefully watching over the past couple of years as all of that has started to change. One of my recurring issues, and frankly one that may have caused me to pull out a lot of hair, was that Microsoft kept increasing the developer experience around PowerShell. Well that's cool, but everyone else in the world is using Bash and PowerShell wasn't available outside of Windows. So to me I kept asking how stupid can you be to increase the dependency on a Windows Environment? Well truth be told they were working on porting PowerShell and it is actually available for Mac and Linux now so any PowerShell commands I may have been running in the past on PC, are now available on Mac.

But it really doesn't end with PowerShell. For the past year I have been somewhat vocal about what they call "Visual Studio for Mac", or as I call it "Xamarin Studio with a Visual Studio logo". This week the team released Preview 6 for VS for Mac. For the first time Mac users like myself are getting a lot closer to some of the critical pieces that have been missing. Now you may have noticed that until now, I haven't mentioned Visual Studio Code. It's not a bad editor, in fact I use it when writing articles for this blog. It's a great environment as well for quickly working up an AspNetCore website and running it locally. But it's been a little frustrating as a Dot Net developer that there hasn't been any tooling (other than PowerShell) that would allow me to connect to Azure and deploy resources right from the IDE. Preview 6 really changes things though. First it brings tooling directly into the IDE to deploy an AspNetCore application straight to Azure whether to an existing resource or a new resource you want to create. The next piece of critical functionality of course... C# 7. It may have taken a month longer, but it's finally available on Mac, proof they really are using the same Rosyln as Visual Studio???

Prism Forms 6.3.0 Highlights

For those following Prism 6.3, it's been a while coming, but there is a lot there. Here are a few helpful things to get you going.

 

Behaviors

One of my favorite additions to Prism Forms 6.3.0 is the addition of Behaviors. First of all Prism gives you a great BehaviorBase<T> class you can use for all of your custom behaviors. But we finally have an EventToCommandBehavior that allows us to execute our ViewModel Commands when an event is triggered, and the control doesn't directly support Commands for that event. This is great for things like attaching to something like a ListView where we might want to work with the ItemTapped or ItemSelected events. You have a wide degree of flexibility here where you can choose to directly accept the EventArgs in your command or you can use a custom converter to grab the item from the EventArgs.

NavigationParameters

One of the breaking API changes you may notice is with the NavigationParameters. In the past, the NavigationParameters was based on a Dictionary which gave us the limitation that a key could only be used once in the querystring. While most of the time this was fine, there are so many cases where you just need to pass a list of something. Along with the new implementation are some great helpers including both a GetValue<T> and GetValues<T>. These are also safe to use if the key didn't actually exist so there's no more need for if( parameters.ContainsKey("foobar")) FooBar = (Foo)parameters["foobar"]. Naturally you will get a default value, so do check for `null`.

 

INavigationAware

Probably one of the most used interfaces in my Prism Forms apps, is INavigationAware. This is a major breaking change. That said, it's worth the frustration of the breaking change here. First of all INavigationAware is no longer a standalone interface. It is now actually the combination of two concepts INavigatingAware and INavigatedAware. As the verbs imply, one is based on Navigation that is about to occur, while the other is about Navigation that has occurred. One of the complaints I often heard, and frankly had myself was that with OnNavigatedTo, there was a visible UI update as my ViewModel was updating the Values that were bound on the UI. INavigatingAware with it's singular OnNavigatingTo really helps to address this problem.

 

The reason why we were seeing the UI changes was that the ViewModel never had a chance to load before we pushed the page onto the Navigation Stack. OnNavigatingTo is only called once, and only before we actually push the page to the stack. Like the sample below shows, we may have some default value that is really only there to alert the developer of a problem or is there for the design time. With the OnNavigatingTo, this value will no longer appear when the the page is actually pushed as the value of Message will update to whatever was in the NavigationParameters.
 
public class FooBarViewModel : BindableBase, INavigatingAware
{
	private INavigationService _navigationService { get; }

	public FooBarViewModel( INavigationService navigationService )
	{
		_navigationService = navigationService;
	}

	private string _message = "some default value"
	public string Message
	{
		get { return _message; }
		set { SetProperty( ref _message, value ); }
	}

	public void OnNavigatingTo( NavigationParameters parameters )
	{
		Message = parameters.GetValue<string>( "message" );
	}
}

BindableBase Update

So this one got snuck in last minute. BindableBase now allows you to specify an action when the value is changed. Also changed was the change up to call RaisePropertyChanged when a property has been changed. This becomes highly useful in a variety of situations like the with the following:
public class Person : BindableBase
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { SetProperty( ref _firstName, value, () => RaisePropertyChanged( nameof( Name ) ) ); }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { SetProperty( ref _lastName, value, () => RaisePropertyChanged( nameof( Name ) ) ); }
    }

    public string Name => $"{FirstName} {LastName}";
}

IActiveAware

For long time Prism users, IActiveAware is nothing new. In fact it's been there the whole time. But for Prism Forms, it's really been useless until 6.3.0. With the addition of behaviors, 6.3.0 adds a new behavior to help with one of the major problems that we have when using any MultiPage such as a TabbedPage or CarouselPage in our application. That problem of course, how on earth do you figure out when the user is actually on your page. How to handle the Children of a MultiPage is something that we will be seeing some additional work on before the next release. But in the mean time the IActiveAware behavior really gives us a great tool. Going forward with 6.3.0, I expect we will see a lot of developers adopting a pattern of making ViewModels for children of TabbedPages like the following:
public class TabbedChildPageAViewModel : BindableBase, INavigationAware, IActiveAware
{
	private bool isInitialized = false;

	public event EventHandler IsActiveChanged;

    private bool _isActive;
	public bool IsActive
    {
        get { return _isActive; }
        set { SetProperty( ref _isActive, value, OnIsActiveChanged ); }
    }

	public void OnNavigatingTo( NavigationParameters parameters )
	{
		if( isInitialized ) return;
		isInitialized = true;

		// Implement loading logic here
	}

    private void OnIsActiveChanged()
    {
        // Do Foo
    }
}
with a TabbedPage like the following:
public partial class MyTabbedPage : TabbedPage, INavigatingAware
{
	public MyTabbedPage()
    {
        InitializeComponent();
    }

    public void OnNavigatingTo( NavigationParameters parameters )
    {
        foreach( var child in Children )
        {
            // You only need to do this on the child if any of your child pages actually implement this.
            ( child as INavigatingAware )?.OnNavigatingTo( parameters );
            ( child?.BindingContext as INavigatingAware )?.OnNavigatingTo( parameters );
        }
    }
}
With this strategy you can now both initialize your Tabbed Page Children, and handle the Activation/Deactivation events that occur when the user changes the tab. You can check out a complete example of this in the Prism Samples.

Writing Cleaner, More Concise Code with Fody

We've all written code that we looked at and said, "Wow this sucks". It's not necessarily that the code itself sucks, but perhaps we just have to make the code very verbose, and we wish there was some way we could clean it up. Just as an example I'll pick on INotifyPropertyChanged. Chances are if you work with an MVVM framework like Prism or MvvmCross, you're pretty used to this. I am a huge fan of simple, elegant, and self documenting code. The problem with INotifyPropertyChanged, is that while it's necessary, it also bloats our code, and can quickly make it a little harder to see what our real intent is.
// The standard format for a Prism ViewModel
public class MyPageViewModel : BindableBase
{
    private string _email;
    public string Email
    {
        get { return _email; }
        set
        {
            if( SetProperty( ref _email, value ) )
            {
                OnEmailChanged();
            }
        }
    }

    private bool _isValid;
    public bool IsValid
    {
        get { return _isValid; }
        set { SetProperty( ref _isValid, value ); }
    }

    public void OnEmailChanged()
    {
        IsValid = RegEx.IsMatch( Email, AppSettings.EmailRegExPattern );
    }
}
Now it's great that so many framework's give us some sort of base class we can inherit from that already implements INotifyPropertyChanged so we at least don't have to do that, but let's be honest our real intent is more like:
// First possible refactoring
public class MyPageViewModel
{
    public string Email { get; set; }

    public bool IsValid { get; set; }

    public void OnEmailChanged()
    {
        IsValid = RegEx.IsMatch( Email, AppSettings.EmailRegExPattern );
    }
}
Or even simpler like:
// Second possible refactoring
public class MyPageViewModel
{
    public string Email { get; set; }

    public bool IsValid
    {
        get { return RegEx.IsMatch( Email, AppSettings.EmailRegExPattern ); }
    }
}
The question you may have, is how can you get your code simplified like the last two examples? This is where it's important to take a moment, and look at one of those things, that most of us developers do not like to think about. Let's be honest, it's something that to most of us, is easier to consider "Magic". Often we just think about the code we write, and then it ends up a compiled library or executable. The thing is, there is all sorts of stuff we can do during compilation to manipulate our code. Fody offers some excellent tooling to do exactly this, and with their PropertyChanged library you can easily add INotifyPropertyChanged.

After installing the library, your ViewModel simply needs to add a single attribute and INotifyPropertyChanged will be 'Weaved' in.
[InjectPropertyChanged]
public class MyPageViewModel
{
    // ViewModel implementation
}
Given the above examples of what we might like to do, the generated class would look like the following:
// First refactoring generated output
public class MyPageViewModel : INotifyPropertyChanged
{
    string email;
    public string Email
    {
        get { return email; }
        set
        {
            if( email != value )
            {
                email = value;
                OnEmailChanged();
                OnPropertyChanged( "Email" );
            }
        }
    }

    bool isValid;
    public bool IsValid
    {
        get { return isValid; }
        set
        {
            if( isValid != value )
            {
                isValue = value;
                OnPropertyChanged( "IsValid" );
            }
        }
    }

    public virtual void OnEmailChanged()
    {
        IsValid = RegEx.IsMatch( Email, AppSettings.EmailRegExPattern );
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
Or the second preferred example:
// Second refactoring generated output
public class MyPageViewModel : INotifyPropertyChanged
{
    string email;
    public string Email
    {
        get { return email; }
        set
        {
            if( email != value )
            {
                email = value;
                OnPropertyChanged( "Email" );
                OnPropertyChanged( "IsValid" );
            }
        }
    }

    public bool IsValid
    {
        get { return RegEx.IsMatch( Email, AppSettings.EmailRegExPattern ); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
You may notice a couple of key differences here, and they will have an impact on our application. The differences can be extremely subtle. In the first example we execute an action when our Email property is updated. In the second we have no action executed but we call OnPropertyChanged for the IsValid property anytime the Email property is updated. What does all of this mean?

I fully admit I really like the syntax of the second refactoring, it is far more elegant. That said, there is a particular problem that we would face using this syntax. Take the email '[email protected]', and say that the Email field is bound to an Entry field. When the user types 'j' OnPropertyChanged is called for the Email property and IsValid property. The user types 'o', again OnPropertyChanged is called for both properties. This would continue for every single character meaning that the UI would have to respond to the event for both bindings.

Now say that you use the first implementation where you call the action OnEmailChanged when the Email property is changed, and this then executes IsValid = RegEx.IsMatch( Email, AppSettings.EmailRegExPattern ). What we are really doing is checking to see if anything has really changed. Again saying that the user types 'j', the action attempts to set a value of 'false' for IsValid. Since the property already was false, OnPropertyChanged is never called and the UI never has to respond to it. In fact the user would have to have entered [email protected] before we would see OnPropertyChanged being executed for the IsValid property. Another way of putting it that we would have been telling the UI to do something 17 times, taking up CPU time that was never needed. Then we would notify the UI again when the user typed the final character.

By using a helper like Fody, we can instead write clean concise code, following the best coding practice that fits our exact situation.

Using Popup Pages with Prism for Xamarin Forms

So often as mobile developers we use some sort of Popup view. Really the reasons why we want to do this simple task are pretty endless. For too long it's been something that wasn't an option for Xamarin Forms. Then came one of my favorite new packages Rg.Plugins.Popup. The only problem is that the library requires navigation through their Popup Navigation Service instead of being integrated in with the Xamarin Forms.

This creates an issue for Prism Applications. How do you navigate to Popup Pages while maintaining a proper MVVM pattern? The solution, Prism.Plugin.Popups. With Prism.Plugin.Popups, Prism based apps can now navigate to Popup Pages using the Prism INavigationService that you're already using. Best of all, there is no configuration required. The plugin adds several new extensions in the Prism.Navigation namespace, so simply adding the INavigationService to your ViewModel and using the Prism.Navigation namespace is all you need to do.
 
using Prism.Navigation;
using Prism.Commands;
using Prism.Mvvm;

namespace MyApp.ViewModels
{
	public class MainPage : BindableBase
	{
		public MainPage( INavigationService navigationService )
		{
			_navigationService = navigationService;

			NavigateCommand = new DelegateCommand( OnNavigateCommandExecuted );
		}

		INavigationService _navigationService { get; }

		DelegateCommand NavigateCommand { get; }

		private async void OnNavigateCommandExecuted() =>
			_navigationService.PushPopupPageAsync( "MyPopupPage" );
	}
}
As mentioned before we're using the INavigationService, and just like the INavigationService you'll need to register your View and/or ViewModel the same as if you're registering any other pages for your application. One caveat to this, in order to function as an extension of the INavigationService it requires specific knowledge of the Container you're using as we have to use your container to resolve the View. As a result there is a container specific implementation for each of the public containers for Prism for Xamarin Forms.

.NET Debug - Remote Debugging Setup

We all might try to pretend that the code we wrote is perfect and will never break, but if there is one constant in Software Development it is that no matter how genius you were when you wrote your code, you are bound to run into bugs. As every developer is all too aware, debugging can present a real challenge, particularly when the code must be executed from within a specialized environment remote from the developers own computer.

As .NET developers we have transitioned our model to a Cloud First mentality which is to say that all of our processes must work in the cloud including the ability to debug our code. When I found myself suddenly needing to reach out to the Cloud as any developer would I began researching what options were available. It didn’t take long for me to find out that Visual Studio offers free Remote Tools. Unfortunately every article I read seemed to be either out of date or leave just enough information out that it ultimately led me in circles.

From vNow to vNext, .NET provides one of the friendliest environments for working Cloud First once you understand the tools at your disposal. Regardless of what type of .NET application you have deployed on your Windows Cloud Server, Visual Studio provides you with an easy out of box solution for securely connecting to your live code in the Cloud. While every development situation is a little different, one of the common one’s that I see today is for the Web App Developer. With that in mind here’s a simple guide to go from a fresh Cloud Server to a Web Server that you as a developer can fully utilize to debug your code.
 

Checklist:

  • Microsoft Windows Server running Server 2008 or later
  • Add any Local or Domain Users and Groups that should have access to the Remote Debugging Tools to the Local Administrators Group

 

Step 1:

  • Perhaps this should go without saying, but Install the Web Server (IIS) Role. This can be done manually or by using either Web Platform Installer or the included script.

 

Step 2:

  • Install Web Deploy 3.5 if you want to deploy your solution directly from within Visual Studio. This should be done from within Web Platform Installer or the included script.

 

Cheat:


- OR -


  • Install Web Platform Installer.
  • Install the following packages:
  • Recommended IIS Configuration ( Step 1 )
  • Web Deploy 3.5 ( Step 2 )

- OR -


  • Recommended IIS Configuration for Hosting Providers ( Steps 1 & 2 )
  • This includes Web Deploy, PHP 5.3, PHP 5.5, and Node.JS

You should also verify that all of the Features of the Web Server you want are installed.

Step 3:


Download and Install the Remote Tools for the version of Visual Studio you have installed and will be using. The installation process is extremely simple, simply agree to the license and click Install.
 
The installer has the same easy flow for vNow to vNext. Agree to the Terms and Conditions and click Install.
The installer has the same easy flow for vNow to vNext.
Agree to the Terms and Conditions and click Install.
 
Following the installation you will need to open the Remote Debugger Configuration Wizard from the Start menu. Since it just seems like a bad practice to leave your server open to anyone to be able to connect to the processes, my suggestion would be to opt for running the Remote Tools as a service. You can use any account you want though running it as the Local System should be fine for most applications.
 
Note that there is an option for the Remote Debugger and the Remote Debugger Configuration Wizard. You want the Wizard to set it up as a service.
Note that there is an option for the Remote Debugger and the Remote
Debugger Configuration Wizard. You want the Wizard to set it up as a service.
 
 
Check the box to run as a Service. Leave the User name as
LocalSystem or enter the User Credentials you want the
service to run as.
 
Once you’ve configured the Remote Tools to run as a Service; your server is ready for Cloud Development. If you open your Visual Studio Project simply right click the Project and select Publish.