Adventures on the edge

Learning new development technologies
    "When living on the bleeding edge - you sometimes have to bleed" -BillKrat

Salesforce and Visual Studio IDE… The Welkin Suite rocks!

Last week I completed the Trailhead beginner and intermediate developer courses available at http://developer.salesforce.com.  During the course I was able to complete all development using their online IDE with relative ease and success – it was very impressive.   Its only shortfall is that it does not support source control and one of the solutions they recommend is to use Eclipse with Force.com IDE.   The results blogged at Salesforce and Eclipse…. arghhh!!

Failure is not an option

In the context of usability (and what I’m accustomed to) it failed miserably working with a VERY large org and failure was not an option.  A means to retrieve the Salesforce org contents, place it in source control, and migrate it to my Salesforce Development Environment (DE) had to be found – The Welkin Suite came to the rescue.  It is a great time to be a Salesforce developer because this developer suite, powered by Visual Studio, is shortly going to be released and as of this writing is in beta.   I’ll describe my successful adventures using this tool to retrieve a very large Salesforce org, in processing updates, deploying them back to Salesforce, and migrating those changes to my Salesforce DE.

I have some QUICK START tips at the end of this blog to fill in some blanks for those developers who want to ramp up in a few minutes to this product.

If you’re a Visual Studio user like myself you will be excited about the following screenshot – it will feel right at home to you.

IDE 

Support

More important than anything else is the support team and staff – they are very, very impressive.   Bear in mind that this product is in beta and as such issues are to be expected, none of them were blocking and I promptly reported the few I did encounter to the team.   Most of the issues were already on their radar and/or fixed (for the upcoming release).  For a minor issue that wasn’t, I was sure to provide detailed information and I got an immediate [next day] response; I might add it was a very appreciative reply from a support member that noted my issue was under investigation and they thanked me for my time.   Every issue reported was addressed with detailed reasons [for those on their radar] as to their cause and I was made to feel like I was a VIP customer of their product - that my input was the most important event for their entire team.   I have not seen this level of support on a product (particularly one I am not paying for).  I’m sold, as soon as it is released I am going to jump on their Enterprise edition.  For a $25.00 monthly subscription I will get updates/full support and I’ve already seen what they do for free customers, so it will be definitely worth the extra $10 (over their professional version) to get the level of support they provide.  FYI: they do provide a free unsupported application as well.

  Welkin Suite Team
WelkinSuite

Retrieving Metadata

Since I already have a solution with two projects (corporate and developer environment orgs) created as of this writing I won’t show a screenshot of the actual creation process, but it is similar, simple, and intuitive.  You will provide login information and a dialog will appear as it retrieves metadata from the applicable org.   I will note that the first dialog does not present a filter option as shown in the screenshot below so after it retrieves the initial catalog of available metadata I deselected all of the default selections (hundreds that didn’t apply), selected only one object, and then let it generate the Visual Studio project files so that I could then right click on the project and select “Project metadata components” as shown in the screenshot below.  Since this dialog is executing code asynchronously you can now input your filter selection, I input “LMSF” and approximately 6 minutes later my list of objects was available and within my project!!   Note that my corporate org has coding standards that require us to have a four character prefix for “all” objects so that there are no conflicts – this standard happened to make this great feature a plug’n play for getting all of my objects quickly located and selected!!!

image

Performance

So let’s pause and talk about that 6 minutes, it may have raised an eyebrow but all things being relative the performance of this Welkin Suite process is impressive.   If you launch Fiddler (shown in the bottom right of image above) you will find that 95% of this time is spent querying the information from Salesforce – the bottleneck is not in the Welkin Suite but Salesforce itself, particularly since this is an enormous org.  Case in point when I ran the same process in Eclipse (reference Salesforce and Eclipse…. arghhh!! blog) the process took well over 15 minutes before I could even access the IDE.  Once accessible I didn’t realize it wasn’t done yet importing (being new to the IDE I thought it failed to get all objects so I tried again) so it was really upset and started dragging into the ground – nothing I couldn’t eventually get out of with the task manager after much frustration.  So 6 minutes was MAGICAL Smile and high performance; when Salesforce was done with its part – the Welkin Suite screamed performance.

So after HOURS of frustration with Eclipse Force.com IDE (blogged about in link above) I was ecstatic that within 10 minutes I had retrieved my meta data from an extremely large org and was up and running!!!   Welkin Suite – you had me  at 10 minutes!

Unit Testing

But it wasn’t done impressing me yet, I created another project for my Salesforce Development Environment (DE) and pulled everything down in a fraction of the time – my environment only contained the objects created during the Trailhead beginner and intermediate courses.  It smoked this small org and within a few minutes I was able to see how the unit test features worked – I was shocked to see that I was able to actually step through my APEX unit test exactly as I’m accustomed to with C#, I even had local variables that allowed me to see what was going on – The Welkin Suite folks now became my best friends!  Up to this point everything had to be done with logging statements and being a new APEX developer completing solutions to the trailhead tests it was like putting on a blindfold and walking into a maze.  The Welkin Suite is amazing and now I am chomping at the bit to start writing my APEX applications!  

stick_figure_walk_blindfold_4540

Walla?

Prior to this it was a rather daunting and depressing venture, why?  I was quickly reminded as I attempted to migrate my application from the enormous corporate org to my Salesforce DE that you have to have 75% code coverage to deploy (try that blind-folded).   This is yet another place the Welkin Suite exceled!  I simply right clicked on my corporate org project, selected “Deploy to organization” (see left pane of image above), filled out the login information and walla!  It failed with detailed explanations why – I had currency fields that were not available in my DE org.   Turns out that my corporate org has Salesforce Winter 17 which is newer than my DE org.  I had to go to the layouts noted in the failed deployment report and remove the currency fields from them.   I then complied with a “Deploy to organization” and walla!  It failed again – this time because I only had 45% code coverage

Adventures on the edge now this was a blocking issue – but it had nothing to do with the Welkin Suite.  

Deploy to Organization

I had to get 75% code coverage or remove all of the culprit classes from my DE.  So if you are trying to deploy to your DE after taking the Salesforce trailhead courses be forewarned – you will have to reset (remove) all classes, triggers, unit test, etc. before you can deploy to your DE or write the unit test (no ROI in that).  In hindsight I wished I had removed the triggers first, then removed all “xxxxController” references from the APEX pages, and finally removed all classes.   Instead I got a lot of error messages and broken links because I was unable to remove components because they were being used – it was a long drawn out process.

After I completed the reset of the DE (which by the way there is no automated way to do) I did a “Deploy to organization” and walla! Success, within a few minutes I deployed from my corporate org to my DE and I didn’t have to touch a command prompt.   This is significant!!  I was originally dismayed to learn that to use the Salesforce Migration Tool that I was going to have to digress to a command prompt and type in many different command line statements to perform the migration.  Not so with Welkin Suite – simply login, point, and click; true to Visual Studio tradition, spoiling us with features on a silver platter.

“I’d rather fight than switch”

So if you are not totally impressed by Welkin Suite, don’t take my word for it.  Try Eclipse and Force.com IDE and find out for yourself, but do not neglect to then try the Welkin Suite because the productivity it offers will sell you within a few minutes.  If you are a corporate developer on a large org that will be doing APEX coding – I wouldn’t waste my time with Eclipse, you will be VERY, VERY thankful to the Welkin Suite team and their hard work and commitment to this project. 

Quick Start

As I eluded to, most C# developers are spoiled as we are accustomed to everything being handed to us on a silver platter – we generally want to jump right in and within a few minutes be able to get the task at hand done.   This section is dedicated to those because where this application is highly intuitive and easy to use – there were some areas that forced me to do some research (and be cautious of as I have admin access to my org) because I didn’t want to break something.

So creating and pulling information from Salesforce – piece of cake no brainer.  But how do you update your changes to your Salesforce org after you are done?   Very simple, simply “Build” the project or “Deploy” it.   I didn’t know the difference between the two so I posed the question to support and was not surprised to get an immediate response the next day – below is an excerpt from that email that demonstrates the level of support that I have been bragging on:

With my experience with Visual Studio and these questions answered I was focusing on the task at hand.  Did I say this product was amazing?   Well their support/staff is even better…

 

From: Kate Dulko [mailto:kate.dulko@welkinsuite.com]
Sent: Thursday, September 15, 2016 6:45 AM
To: Bill Kratochvil <bill@global-webnet.com>
Cc: Info TheWelkinsuite <info@welkinsuite.com>
Subject: Re: Verify bug submissions are being received

Hi Bill,

We are glad to get your response.

I would be glad to provide the information you requested. Here this is:
•    "Deploy Objects": the build functionality, that you have mentioned helps you to update your Organization on Salesforce with the new changes made inside The Welkin Suite, but the Build option applies for the next Salesforce metadata types only: Apex Classes, Apex Components, Apex Pages, Apex Triggers, Aura Definition Bundles, and Static Resources. If you work with other types of metadata and need to move the changes in them to an org, please use the functionality of Deploying Objects.
•    "Enable project structure sync": The Welkin Suite gives you an ability to create your own project structure. This means that you can create separate folders in the Solution Explorer, move your project files between default and your custom folders, or move folders inside the project structure. Enabling project structure synchronization allows you to store this structure on Salesforce or share it with your colleges. More detailed information about this feature you can find in the Release Notes blog post.

 
We will be happy to help you and answer your questions related to any other TWS process or feature. In addition, next week we will publish the Refreshed TWS Documentation which will allow you to find any necessary information easily.

Best Regards,
Kate

--
Kate Dulko
Customer Relations

The Welkin Suite
skype id: d_katerina_
e-mail: kate.dulko@welkinsuite.com

Salesforce and Eclipse… arghhhh!!

Salesforce rocks, I took their Trailhead beginner and intermediate developer courses at http://developer.salesforce.com and was very, very impressed.  It combined my experience of ASP.NET MVC, SQL, C#, and Visual Foxpro (data integrated with environment) and combined it into one very powerful package.   I was able to do everything with their online development environment except for source control which is where Eclipse stepped in….

If a picture says a thousand words then all I can say about my experience with Eclipse is

For a Visual Studio developer it is a jaw dropping [dismay], depressing, wondering if the IDE is locked up experience – if you have a large org, as I do, you will be staring at “not responding” a lot.   

image

DON’T MAKE THE MISTAKE I MADE and select the first radio button in the image above if you have a large org as you will be staring at a cursor for 15-20 minutes before you can start using the system (no it is not locked up).

FORTUNATELY, my corporate client has a coding standard that requires us to use a four character prefix – this was a lifesaver in this situation, but still had me wondering if I was locked up – or when/if the process was ever going to end… 

So if you select the second radio button from the image above and are fortunate enough to use this (because you have a consistent filter phrase) you will be able to type in your search phrase, e.g., “LMSF”.  Typing is extremely sluggish (in my case I had to wait for it to start responding again) and you will be presented with a list of available objects to select from.

image

But the torture doesn’t end yet!!   Oh you think I am exaggerating?  Take two minutes of your life and watch this video clip to get a glimpse of what your experience will be like if working with a large org.   VERY IMPORTANT FACT YOU MUST UNDERSTAND AS A NEWBIE – pay very close attention to the progress bar in the bottom right hand corner – I failed to my first attempt and I thought the process was completed (after waiting 15 minutes) because the dialog box simply disappears.  So I started using eclipse (it will let you) only to discover my components were not all there, so I started the process again (to get missing components) not realizing it was still processing -  I missed the progress bar in the bottom right corner ---- ARGHHHH!!!!!  

If you watch the video clip progress bar you might think that once it gets to 100% that you are done – not so lucky, it starts over at 0% and repeats this continually over and over again with no clue of when it will be done.

So after sluggish performance, wondering if your IDE is locked up half the time, having to be very patient every time you try to expand a tree node, and tired of looking at a never ending progress bar – you might do like me and say “screw this” there has to be a better way and exit the application.   You will then see something like the pane on the left…. I was like “Okay, maybe this tells me when I’ll be done – I only have to go up to 79 files”.    THEN you wait and the pane on the right shows up – 373 files…. ARGHHH!!!!

SNAGHTML16437a29

At this point I am wondering – what the heck is it doing because I did not ask for these files.  I only requested my 30 or so files that start with LMSF as indicated in the image before this one.   Get me to that darn Task Manager so I can close this thing – CALL ME SPOILED but this is nothing I have ever had to deal with while working with Visual Studio…. I am out of here…

I wasted hours of my life trying to start from scratch working with Eclipse

ASP.NET MVC / REST Web API / Unity IOC

Source code available on GitHub => https://github.com/BillKrat/Framework

“Dependency Injection has become a first class citizen”, I heard this in a video I was watching on ASP.NET MVC 5 and judging by the latest release it is very impressive indeed;  Microsoft nailed it with ASP.NET MVC

I’ve been using the Microsoft.Practices.Unity container (not to be confused with the Unity gaming framework) since its conception and would like to continue doing so  (versus using the ASP.NET MVC internal IOC container).  So I created a wrapper for Unity’s IUnityContainer instance and expose it from my IGwnContainer Container property (code shown below).   I use lazy instantiation to load my Unity container in the getter which comes registered with a logger, event aggregator, AppSettings, and other features provided by my GwnClassBase.

using Microsoft.Practices.Unity;

namespace Gwn.Library.Common.Entities
{
public class GwnContainer : IGwnContainer
{
private IUnityContainer _container;

public IUnityContainer Container
{
get
{ // Lazy instantiation so we'll always return
// the same container
if (_container == null)
{
_container = new GwnClassBase().GetContainer();
_container.RegisterInstance<IGwnContainer>(this);
}
return _container;
}
set { _container = value; }
}
}
}
 
With that done I simply have to register it with the ASP.NET MVC IOC container within the Startup.ConfigureService method as a singleton (line 49 below), I’ll piggy back on the IOC container to ride through the system; I can have the best of both worlds.
 

StartupCode
Figure 1 coding in Startup.cs required to implement Unity Container

On line 72 in figure 1, I added the IGwnContainer interface to the Startup.Configure method parameters which uses ASP.NET MVC parameter injection to provide an instance.  on lines 76-78, I register IFactory and IConcreteProcessor with my Unity Container which are used by my DataController Web API REST service. 

That is all the “coding” my ASP.NET MVC application required to activate the REST Service – I can now do the following from my Web application!  How is this possible?

URL
Figure 2 using a REST Web API service from a ASP.NET MVC application

Well, there is one more step to perform, but it doesn’t require coding, by adding a reference to my Gwn.Library.AspNet project it automagically pulled in the DataController (code shown below) simply because it exists in the library and has a Route(“svc/[controller]”) attribute.  Now any URL for this web application that starts with “svc/data” automatically ends up in this DataController – very cool….

Note: referencing the code below, my Unity container comes into play in the DataController constructor.  I use constructor injection so that the ASP.NET MVC framework will serve up my IGwnContainer instance where I use the Container property to resolve the IFactory instance.  From that point on the _factory field will be used by the data controller to handle request.

using Microsoft.AspNet.Mvc;
using Gwn.Library.Data.Results;
using Gwn.Library.Data.Events;
using Microsoft.Practices.Unity;
using Gwn.Library.Data.Factories;
using Gwn.Library.Common.Entities;

// ----[ !!! THIS FILE IS LINKED !!! ]----------------------------------------
// FROM: Gwn.Library.AspNet\Controllers\DataController.cs
// TO: Gwn.Test.Library.Data (Gwn.Library.AspNet folder)\DataController.cs
// ---------------------------------------------------------------------------
// For more information on enabling Web API for empty projects,
// visit http://go.microsoft.com/fwlink/?LinkID=397860

namespace Gwn.Library.AspNet.Controllers
{
[Route("svc/[controller]")]
public class DataController : Controller
{
public IUnityContainer Container;
private IFactory _factory;

public DataController(IGwnContainer gwnContainer)
{
Container = gwnContainer.Container;
_factory = Container.Resolve<IFactory>();
}
[HttpGet("{factoryName}")]
public ServiceResult Get(string factoryName)
{
var args = new ServiceEventArgs(ServiceEventType.Get);

var factoryArgs = new FactoryEventArgs(factoryName);
var factory = _factory.GetFactory(this, factoryArgs);
var processor = factory.GetConcrete();

var serviceResult = processor.Execute<ServiceResult>(this, args);
return serviceResult;
}
[HttpGet("{factoryName}/{id}")]
public ServiceResult Get(string factoryName, string id)
{
var args = new ServiceEventArgs(ServiceEventType.Get, id);

var factoryArgs = new FactoryEventArgs(factoryName);
var factory = _factory.GetFactory(this, factoryArgs);
var processor = factory.GetConcrete();

var serviceResult = processor.Execute<ServiceResult>(this, args);
return serviceResult;
}
[HttpPost]
public ServiceResult Post([FromBody]ServiceParameter para)
{
var args = new ServiceEventArgs(ServiceEventType.Post, para.Id);

var factoryArgs = new FactoryEventArgs(para.Factory);
var factory = _factory.GetFactory(this, factoryArgs);
var processor = factory.GetConcrete();

var serviceResult = processor.Execute<ServiceResult>(this, args);
return serviceResult;
}

[HttpPut("{id}")]
public ServiceResult Put(string id, [FromBody]ServiceParameter para)
{
var args = new ServiceEventArgs(ServiceEventType.Put, id);

var factoryArgs = new FactoryEventArgs(para.Factory);
var factory = _factory.GetFactory(this, factoryArgs);
var processor = factory.GetConcrete();

var serviceResult = processor.Execute<ServiceResult>(this, args);
return serviceResult;

}

[HttpDelete("{factoryName}/{id}")]
public ServiceResult Delete(string factoryName, string id)
{
var args = new ServiceEventArgs(ServiceEventType.Delete, id);

var factoryArgs = new FactoryEventArgs(factoryName);
var factory = _factory.GetFactory(this, factoryArgs);
var processor = factory.GetConcrete();

var serviceResult = processor.Execute<ServiceResult>(this, args);
return serviceResult;
}
}
}

Obviously I don’t want this Gwn.Library.AspNet project to become bloated with every applications data requirements, so I created a generic DataController that handles the REST operations GET, POST, PUT, and DELETE.  This nicely covers my data CRUDL requirements (create, read, update, delete, and list) .  

It is the IFactory implementation, which will be configured by the application, that will handle what implementation to use for the application’s data requirements.   I’ll show code below that demonstrates how this generic DataController can allow the application to use its own implementation.

The default Factory implementation will handle most requirements; it will permit most Factory classes to look as simple as the following:

namespace Gwn.Library.Data.Factories
{
/// <summary>
/// Test factory uses the default configuration which
/// depends on the following interfaces to be registered:
/// <see cref="IFactory"/>,
/// <see cref="IConcreteProcessor"/>
/// </summary>
/// <example><code><![CDATA[
///
/// _container = new GwnClassBase().GetContainer();
/// _container
/// .RegisterType<IFactory, TestFactory>()
/// .RegisterType<IConcreteProcessor, TestProcessor>()
/// ;
///
/// ]]></code></example>
public class TestFactory : FactoryBase
{
}
}
 
The default FactoryBase operations used by the DataController will simply serve up the IConcreteProcessor that is registered within the Unity container (line 27 below).  The power of the IFactory interface comes when you want to process more than one data access layer for handling data.
 

DataController

 

public class TestFactory : FactoryBase
{
public override IFactory GetFactory(object sender, EventArgs e)
{
// Use Unity named registrations for factory pattern.
// These registrations could be made here - but are
// better done in the application
Container
// http://MyApp/svc/data/UserData/MyID
.RegisterType<IFactory, UserFactory>("UserData")

// http://MyApp/svc/Data/TestData/MyID
.RegisterType<IFactory, TestFactory>("TestData")
;

var args = e as FactoryEventArgs;
return Container.Resolve<IFactory>(args.FactoryName);
}
}
 
Above I can now select the factory to be used by the URL, you’ll see I have URL options for UserData and TestData.  Just as I used named registrations for IFactory so that I can select UserData or TestData, I could just as easily do the same with the IConcreteProcessor which provides an unlimited number of usages – all URL command line driven.
 
I should note that if I want more features than the default REST operations provide, I can easily add a new FooController and use http://MyApp/svc/foo/para1/para2/  versus http://MyApp/svc/Data/factory/id 
As for the Processor, the following is the code that I am using for TDD, it is what provided the result you saw in the bottom pane of figure 2.
 
Processor
 
The following code is the unit test used for TDD of the DataController class:
 
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
using Gwn.Library.Common.Entities;
using Gwn.Library.Data.Factories;
using Gwn.Library.Data.Processors;
using Gwn.Library.AspNet.Controllers;
using Gwn.Library.Data.Events;
using System;
using Gwn.Library.Data.Results;

namespace Gwn.Test.Library.Data.Fixtures
{
[TestClass]
public class DataControllerFixture
{
private const string clientFactoryParameter = "Test";

private IUnityContainer _container;
private DataController _controller;

[TestInitialize]
public void InitializeTest()
{
_container = new GwnContainer().Container;

// Register the TestFactory and TestProcessor for use
// by the DataController (in Gwn.Library.AspNet)
_container
.RegisterType<IFactory, TestFactory>()
// ▼▼▼▼▼▼▼▼▼▼▼▼▼
.RegisterType<IConcreteProcessor, TestProcessor>();
// ▲▲▲▲▲▲▲▲▲▲▲▲▲
_controller = _container.Resolve<DataController>();

Assert.IsNotNull(_controller, "Controller null, all test will fail");
}


// ▼▼▼▼▼▼▼▼▼▼▼▼▼
public class TestProcessor : ProcessorBase
// ▲▲▲▲▲▲▲▲▲▲▲▲▲
{
public override T Execute<T>(object sender, EventArgs e)
{
var args = this.EventArgs as FactoryEventArgs;
var returnResult = new ServiceResult();

Func<string> parameter = () =>
args.ServiceParameter == null ? "NA" : (args.ServiceParameter.Id ?? "NA");

var data = $"ID: [{args.Id ?? "NA"} / {parameter()}] TYPE:{args.ServiceEventType}";

returnResult.Data = data;
returnResult.FriendlyMessage = args.ServiceParameter?.Message ?? "Friendly Message";
returnResult.DeveloperMessage =
$"Factory=[{args.FactoryName}] [{args.ServiceParameter?.Tag ?? "NA"}]";

return (T)(object)returnResult;
}
}


[TestMethod] // template: svc/data/Test
public void Can_GET_FromDataController()
{
var result = _controller.Get(clientFactoryParameter);

var expected = "ID: [NA / NA] TYPE:Get";

Assert.AreEqual(expected, result.Data);
Assert.AreEqual("Friendly Message", result.FriendlyMessage);
Assert.AreEqual("Factory=[Test] [NA]", result.DeveloperMessage);
}

[TestMethod] // template: svc/data/Test/100
public void Can_GET_WithID_FromDataController()
{
var para = "100";

var result = _controller.Get(clientFactoryParameter, para);

var expected = "ID: [100 / NA] TYPE:Get";

Assert.AreEqual(expected, result.Data);
Assert.AreEqual("Friendly Message", result.FriendlyMessage);
Assert.AreEqual("Factory=[Test] [NA]", result.DeveloperMessage);
}

[TestMethod] // template: svc/data [FromBody]ServiceParameter para
public void Can_POST_ToDataController()
{
var serviceParameter = new ServiceParameter
{
Id = "500",
Factory = "Test-Factory"
};

var result = _controller.Post(serviceParameter);

var expected = "ID: [NA / 500] TYPE:Post";

Assert.AreEqual(expected, result.Data);
Assert.AreEqual("Friendly Message", result.FriendlyMessage);
Assert.AreEqual("Factory=[Test-Factory] [NA]", result.DeveloperMessage);
}

[TestMethod] // template: svc/data/250 [FromBody]ServiceParameter para
public void Can_PUT_ToDataController()
{
var serviceParameter = new ServiceParameter
{
Id = "500",
Factory = "Test-Factory",
Message = "Replace Friendly Message",
Tag = "Can be used for anything"
};

var result = _controller.Put("250", serviceParameter);

var expected = "ID: [250 / 500] TYPE:Put";

Assert.AreEqual(expected, result.Data);
Assert.AreEqual("Replace Friendly Message", result.FriendlyMessage);
Assert.AreEqual("Factory=[Test-Factory] [Can be used for anything]", result.DeveloperMessage);
}
}
}

Note that the POST and PUT operations provide a ServerParameter object which can contain as many parameters as required for the application.
 
public class ServiceParameter : ParameterBase
{
#region The Id and Factory Properties are used by framework

public string Id { get; set; }

public string Factory { get; set; }

#endregion


// The following are used by the implementation as applicable

public string Tag { get; set; }

public string Message { get; set; }

}

Universal Windows: ResourceMap Not Found / How to programmatically retrieve resources with properties

This adventure cost me a few hours of my life…

This occurred when I tried to programmatically get a string from the resource loader.

image

If I called the resource file Resources.resw and placed it in my Strings\en-us path of my application then it sorta-kinda works. 

It sort-kinda works because where you can get simple content, e.g., “TestString” as shown on line 49 in the line below (infoR variable in red box of bottom pane), you can’t programmatically retrieve the control resources such as EmailTextBlock.Text and LostPasswordButton.Content.  Localization did however work using the XAML UID – just not programmatically.

I have a work-around for that as well but first let’s address the error that started all of this.

image

 

The problem was that I had a Gwn.Library.Desktop project that has its own resource file and I needed to reference the resources from a view within this very same library.  Long story short, I could not get localization to work at all (programmatically or through binding) unless the Application had a copy of the resource file.  

To resolve this issue I opted to have a “linked” copy of the resource file from my Gwn.Library.Desktop project in the Application – this way I only have to update one file.  

  1. I named my resource file DesktopResources.resw
  2. Right click on this file and copied the path to clipboard
  3. Navigated to my Application Strings\en-use path and then right clicked on it
  4. Added existing item and pasted the path into the File name box.
  5. Selected the dropdown (right down triangle) and selected “Add as Link”

With this change done I now had localization that worked with XAML UID (as expected) as well as the ability to programmatically retrieve strings using a my GetLocalizedText<T>() method.  Note that in this method (line 34 of image below) that I have to specify the name of my resource file in the ResourceLoader constructor.

image

Likewise I had to ensure that my UID settings were prefixed with the resource filename (not required if you use the default name of resources.resw). 

image


OCT-25-2016 Thank you Matt Cecile for providing the following great tip:
   You say " I cannot retrieve resources that have a property attached". Its simple actually:
          var resourceLoader = new ResourceLoader("DesktopResources");
          var value = resourceLoader.GetString(resourceName + "/Text");
    or /Content, or whatever property you are trying to get.

With the environment setup now, and localization working within XAML, I now have to work-around the issue presented above where I cannot retrieve resources that have a property attached.  To do this I programmatically build a XAML control using the provided type, load it, and then cast the resulting instance as required to get the Text or Content value using the extension method below:

/// <summary>
/// Class StringExtension.
/// </summary>
public static class StringExtension
{
/// <summary>
/// Gets the localized text.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="resourceName">Name of the resource.</param>
/// <returns>System.String.</returns>
public static string GetLocalizedText<T>(this string resourceName)
{
var resourceLoader = new ResourceLoader("DesktopResources");
var value = resourceLoader.GetString(resourceName);

if (string.IsNullOrEmpty(value))
{
var ctrlType = typeof(T).Name;

var xaml =
$"<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" +
$"<{ctrlType} xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' " +
$"x:Uid='{resourceName}' x:Name='Content' />" +
$"</Grid>";

var control = XamlReader.Load(xaml) as Grid;
var result = control?.FindName("Content");
if (result == null) return "";

switch (ctrlType)
{
case "TextBlock": return ((TextBlock)result).Text;
case "Button": return ((Button)result).Content?.ToString();
default:
return "";
}
}
return value;
}
}


 
Below, underlined in yellow, I show how I use this extension method to get the button content so that I can programmatically update my Register and Lost Password buttons – required because I reused this buttons on a registration view and changed their names while in that view.

image
 

Arch-101: Model, View, Controller (MVC)

“Those who do not remember their past are condemned to repeat their mistakes.”
     - George Santayana

If we hope to grasp the foundation of architectural patterns we have to understand MVC.   Every pattern today hinges on this understanding since they, for the most part, have evolved from it.  MVC knowledge is an important part of becoming an architect as it teaches us the lessons learned from our past great architects, the issues they encountered, and why they evolved to the next pattern as a solution to those issues.

It is also important to know that for ASP.NET MVC, the (C)ontroller in MVC is an overloaded term and has nothing to do with traditional MVC as outlined in this article; the controller in ASP.NET MVC actually behaves more like a Presenter from the Model View Presenter (MVP) pattern.

image

Figure 1 – Learn from our past architects, lest history repeats itself…

Martin Fowler tells us in his GUI Architecture article 6 that MVC is the most misquoted pattern, and this was among those architects that understood the Smalltalk environment.   To complicate matters, we (todays developers) lack a common core of experience with our great architects (and their articles), e.g., we don’t know what a “controller” is because we’ve never had to work with one, so it is understandable how MVC can be hard to grasp.  

Understanding the Controller

“Another irritating feature of MVC, at least with respect to Dolphin, was that the idea of a controller did not fit neatly into the Windows environment. Microsoft Windows, like most modern graphical operating systems, provides a set of native widgets from which user interfaces can be constructed. These "windows" already include most of the controller functionality embodied as  part of the underlying operating system control.” 7

The above statement eludes to the underlying difficulty in our ability to understand MVC;  it was not designed for Windows (or modern) operating systems – it was designed for systems that had to monitor user inputs and process them manually. Unlike Windows, those systems did not have controls (supported by an operating system) that did all the work for them, they had to manually manage framework features that we take for granted.

For those systems, if you created a text control (view) you had to create a way to communicate with it (update the display from data) as well as a way for the control to communicate with the application (update data from input) – this is where the MVC controller came in.  There were a collection of controllers, one for each control on the screen (controller-view pair).  Only one controller could have control at anytime (the one receiving the input) so a ControlManager was responsible for managing the hierarchical of controllers to ensure the proper controller was active 3.

The system had input sensors (keyboard or mouse) and as the user interacted with the controls (gestures), the active controller would broadcast the applicable message.

image

Figure 2: Model-View-Controller State and Message Sending 2

When the controller was initialized it was linked to both a model and a view (control), likewise the view is linked to the model.  When a user selects a control (via keyboard or mouse) the controller associated with that control is made active and it broadcast the user input as a message.  

This message contains a symbol (#propertyName) and the applicable value 6.   The model receives this message and updates the applicable property on it.  It then notifies the view that there was a property changed so that it can refresh its associated view, or views (if more than one control are linked to the model property).  

So when you understand the role of the view-controller pair as follows:  “The view and controller are supposed to create and maintain the user interface, track user events, and update the model when appropriate” 4. You’ll better understand that it is the model that handles all of the application business logic – not the controller or its view.   

In summary, at the highest level the controllers only responsibility is to get the user inputs to the model.  If we look at todays controls, i.e., a text control, we do not have to worry about this.  We can either take a passive approach and grab the content from the textbox control and place it on the model, or we can use data-binding so that as the content is changed the model is automagically updated – the controller functionality is done for us under the hood of the control.

Armed with this information, you can see that with the Windows operating system there is no “C” in MVC – only MV.  Some architects wrongly believe the the “C” in MVC is analogous to the “P” in MVP, because they believe the controller is where all of the business logic resides.   If they understood MVC they would know that the “P” in MVP is actually analogous to the  “M” in MVC because in MVC the model contains all of the business logic, later it was moved to a Presentation/Application, aka view model (more on this below) – this is explained further in the article referenced below “Twisting the Triad”.

Model View Pattern

With Windows the pattern now becomes MV because there is no controller.  This does not mean that the MVC pattern conceptually does not apply to us – it still does.  For all practical purposes there is no functional difference because the view-controller pair of MVC and the view of today’s control.  When it comes to the principles (and issues) of MVC they apply equally to both of us because our view functioned the same function as their controller-view. 

image

Figure 3: Windows View-Model pattern (there is no controller)

Understanding the Model

“This is the data upon which the user interface will operate. It is typically a domain object and the intention is that such objects should have no knowledge of the user interface.” 7

Definitions

Domain Object (aka Entity)
A domain object is a class that has a clear separation of concerns; it represents a single entity.  For example a User domain object would have Last, First, MI, Address, and Email properties.  it “should be completely self contained and work without reference to presentation, they should also be able to support multiple presentations” 6

What does “work without reference to presentation” mean?  If the view has a behavior where the email content displays in red if it is invalid, you would have a EmailTextColor property on your model to trigger this behavior – since this is presentation state, you would not want the EmailTextColor property in your domain object; to be technically correct you would place this in the evolved MVC Application Model (discussed below).

Model

A model, by today’s definition, is a class.  This class will have properties and methods to handle the business rules of the application; in MVC all processing is done by the Model.  The model properties could be any type, i.e., bool, string, etc. as well as entities such as the User entity discussed above.

In MVC, the user inputs are sent to the model via a controller message.   The model updates the applicable property and then notifies the view that there was an update.  The view is responsible for refreshing itself with the applicable data from the model.

In MV, the user inputs into a control and it automatically updates the model if using the Observer pattern (data binding).  If Passive view is being used (no data binding) then the view’s code-behind would have to manually update the model.

In either case, MVC or MV, the model is changed and/or notified of a request (button click) and the model is responsible for processing the applicable business logic.   Neither the view nor controller (in the case of MVC) handles business logic – only the model does.

Application Model / Presentation Model (aka MVVM)

Note: the Presentation Model is similar to the Application Model with the exception that the Presentation Model does not permit you to update the view 6. 

”Smalltalk 80's MVC was very influential and had some excellent features, but also some faults. As Smalltalk developed in the 80's and 90's this led to some significant variations on the classic MVC model.” 6.  One of these changes was the use of an “Application Model” (discussed below) which sits between the view and the model, this allowed for the purity of domain objects by moving presentation state to this new Application Model.   Note: the Application Model can consist of your domain objects, but is typically specialized to handle UI behavior 5.

All of the business logic was moved out of the domain into the Application Model, which in today’s terms is referred to as a “view model”.  A noted limitation of MVC was the complexity of code required to update the view from the model (particularly since it had no reference to the view), complex view behaviors required special coding and property objects; this was often seen as too much work so unlike the Presentation Model, the Application Model was allowed to modify the UI directly 6.

image

Figure 4: Functional model (view-controller pair represented only as view above to be consistent with Windows OS)

 

Understanding the View

“The View displays the Model on the screen. View provides a simple protocol to pass information to and from the Model. The heart of a View object presents the Model data in one particular way that is of interest to the end user. Different views may support the same data, i.e., the same Models, in completely different ways. The classic example is that one View may show data as a bar graph while another shows the same data as a pie chart.” 1 

“Each view may be thought of as being closely associated with a controller, each having exactly one model, but a model may have many view/controller pairs”. 2

With the Application and Presentation Model,  the view only communicates with the view model - not the domain model; this permits the domain objects to maintain their purity in terms of not having any presentation state or contain “application” business logic in them. 

Lessons Learned

The evolution to the Model View Presenter (MVP) pattern was the solution to the problems inherent in the evolved MVC patterns as noted by Andy and Blair in their “Twisting the Triad” article, Mahemoff and Johnston in their “Handling Multiple Domain Objects with MVC”, and the issues I experienced myself.

My experience working on large projects based on MVVM seemed consistent; I have found that the Presentation Model (MVVM) lends itself to code bloat and the inability to reuse components.  As such, I have had to refactor frameworks to MVP-VM to overcome the shortcomings which evolved into blocking issues.  some of the pain points that I have encountered follow (perhaps you recognize them as well?):

  • All of the business logic is placed in the Application Model (view model) which will have dependencies on domain objects that are more application centric than what a particular view requires.  If another view wants to reuse a view model it has to pull in its domain objects and business logic as well, e.g., if it wants to reuse the drain it has to pull in the kitchen sink, which has to pull in the kitchen, which pulls in the house, which pulls in the yard… the architect might find it easier to add on another kitchen, with its own sink, to have the drain that can be reused for their purpose… 
  • A big issue I’ve seen is when the view model (for all practical purposes) becomes a view code-behind file; the view is so tightly coupled to the view model, the view model serves no other purpose than to handle that one view.  The sad part is the view doesn’t even have the benefit of being able to access the view – which lends itself to the next issue.
  • Another big issue is when the view’s code-behind ends up being utilized for business logic because it is inaccessible from the view model. What’s worse is when views contains child views that have their own code-behind files.  It becomes difficult to locate  where the actual business logic resides, particularly with data-binding in the mix - in many cases it can be almost impossible to locate business logic without the assistance of an application such as Snoop because of a deep hierarchical nesting of view/view models with code in both.
  • The biggest issue - without the ability to reuse components the application becomes monolithic, hard to maintain, and is not easily extensible.
    image

 

Below is an excerpt from “Twisting the Triad” – it eludes to the frustration in working with the evolved MVC pattern:

“By now we were once more becoming somewhat disheartened with our framework approach. We were left holding two possibilities that, although adequate, were flawed in several respects (and, when one is engaged on a quest to create the perfect development environment, such flaws seem all the more debilitating).

So, where were we? We liked the Observer aspect of MVC and the flexibility that came from its pluggable nature but it just didn't seem correct that the link between the application model and view was an indirect one. Also, the requirement for "controllers" in the Windows environment seemed out-moded.

To be honest, we didn't feel confident about tinkering with these aspects of MVC purely as the result of our own intuition; we’d wasted enough time already. We were on the point of giving up and resigning ourselves to using our existing interpretation of MVC when a colleague asked if we had looked at Taligent's Model View Presenter framework?” 7

 

REFERENCE: Mahemoff, Johnston - Handling Multiple Domain Objects with MVC 4

Note: for brevity I only mention the titles – please read the article from reference links below.

Problem 2: Each model-view-controller package should rely on as few other packages as possible

Problem 3: How can views and controllers present information relating to one model and simultaneously enable a user to change another model?

Problem 4: Some models and views have their state defined by one or more models.

Problem 5: Some models reference other models and need to know that they have changed.

REFERENCE: Andy Bower, Blair McGlashan - Twisting the Triad 7

“In MVC, it is a view's responsibility to display the data held by a model object. A controller can be used to determine how low-level user gestures are translated into actions on the model. The various components, M, V and C are all pluggable for maximum flexibility. Generally, a view and controller are directly linked together (usually by an instance variable pointing from one to the other) but a view/controller pair is only indirectly linked to the model. By “indirect”, I mean that an Observer relationship1 is set up so that the view/controller pair knows about the existence of the model but not vice versa. The advantage of this comes because it is then possible to connect multiple views/controller pairs to the same model so that several user interfaces can share the same data. Unfortunately, it is the nature of this indirect link that causes the problems with MVC.”

“In MVC, most of the application functionality must be built into a model class known as an
Application Model2 (see figure 1). It is the responsibility of the application model to be the mediator between the true domain objects and the views and their controllers. The views, of course, are responsible for displaying the domain data while the controllers handle the raw user gestures that will eventually perform actions on this data. So the application model typically has methods to perform menu command actions, push buttons actions and general validation on the data that it manages. Nearly all of the application logic will reside in the application model classes. However, because the application model’s role is that of a go-between, it is at times necessary for it to gain access to the user interface directly but,
because of the Observer relationship between it and the view/controller, this sort of access is discouraged”.

“let's say one wants to explicitly change the colour of one or more views dependent on some conditions in the application model. The correct way to do this in MVC would be to trigger some sort of event, passing the colour along with it. Behaviour would then have to be coded in the view to "hang off" this event and to apply the colour change whenever the event was triggered. This is a rather circuitous route to achieving this simple functionality3 and typically it would be avoided by taking a shortcut and using #componentAt: to look up a particular named view from the application model and to apply the colour change to the view directly. However, any direct access of a view like this breaks the MVC dictum that the model should know nothing about the views to which it is connected. If nothing else, this sort of activity surely breaks the possibility of allowing multiple views onto a model, which must be the reason behind using the Observer pattern in MVC in the first place.

 

References

  1. Trygve Reenskaug and James Coplien - March 20, 2009.  The DCI Architecture: A New Vision of Object-Oriented Programming 
  2. Krasner, Glenn E.; Pope, Stephen T. (Aug–Sep 1988). "A cookbook for using the model–view controller user interface paradigm in Smalltalk-80". Also published as "A Description of the Model–View–Controller User Interface Paradigm in the Smalltalk-80 System" (Report).
  3. Burbeck, Steve (1992) Applications Programming in Smalltalk-80:How to use Model–View–Controller (MVC)
  4. Mahemoff, Johnston.  Handling Multiple Domain Objects with Model-View-Controller
  5. Hopkins, Horan. SmallTalk an introduction to application development using VisualWorks
  6. Martin Fowler (2006), GUI Architectures.
  7. Andy Bower, Blair McGlashan. Twisting the Triad, The evolution of the Dolphin Smalltalk MVP application framework