#VSCode: Quickly clone a git repository from #GitHub

download.pngI really enjoy Pluralsight.com as a place to refresh and learn new tech. In their courses they usually have example code on public GitHub repositories. Here’s the fast way to get them downloaded and up in VSCode (Visual Studio Code)

Here’s the fastest way to download a repo and open it in Visual Studio Code in the folder you’d like.

Step 1: Get the repo link.

For this example I’m using https://github.com/DanWahlin/Angular-JumpStart

Open the that link and press the Clone or Download button, then the Copy Link button seen here:

2020-03-11 09_43_03-DanWahlin_Angular-JumpStart_ Angular and TypeScript JumpStart example applicatio.png

Step 2: Open Windows Explorer to the folder you’d like it, then right click the folder and choose Open with Code 

2020-03-11 09_45_57-.png

Step 3: With VS Code open, press CTRL+<back tick> to open the Terminal

Type in git clone, then paste the URL:

2020-03-11 09_48_40-Welcome - Angular Architecture and Best Practices - Visual Studio Code.png

Done!

2020-03-11 09_50_11-Welcome - Angular Architecture and Best Practices - Visual Studio Code.png

 

#VSCode: Adding Windows Explorer Context Menus

1200px-Visual_Studio_Code_1.35_icon.svg.pngIn order to open VSCode in a specific folder, I used to Right Click the folder with SHIFT help down then choose Open PowerShell Window Here, then type code .

2020-03-11 09_05_44-Select Windows PowerShell.png

But, it turns out you can add Open in Visual Studio Code much easier if you choose the option in the Visual Studio Code installer.

If you have VSCode installed or not, just run the installer again. You can get it here.

Select these options:

2020-03-11 09_08_06-Setup - Microsoft Visual Studio Code (User).png

Now, when you right click a folder in Windows Explorer (SHIFT is not needed) you can choose the option:

2020-03-11 09_09_17-.png

Pro tip:

When you hold the SHIFT key down, you’ll get more options:

2020-03-11 09_11_22-.png

 

 

#VSCode: Handling Debugging Error “Breakpoint set but not yet bound”

download.pngYour Angular VS Code project can contain either a simple application, or multiple. When you have multiple, it can cause issues with connecting a debugger. Here’s the trick on how to handle that situation:

After you create a new Angular app then try to debug it in VSCode, you can often get the error “Breakpoint set but not yet bound” when you try to set a break point.

sourceMapPathOverrides is critical

The fix is simple, just indicate the actual path to the webRoot, not just the workspaceFolder in the launch.json.

{
 
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome against localhost",
      "url": "http://localhost:4200",
      "webRoot": "${workspaceFolder}/my-app/src",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/./*": "${webRoot}/*",
        "/src/*": "${webRoot}/*",
        "/*": "*",
        "/./~/*": "${webRoot}/node_modules/*"
      }
    }
  ]
}

When you just have a single application (you don’t have a Project/ folder) set the webRoot to

"webRoot": "${workspaceFolder}"

Tip: When you open the folder in VS Code, do so at the root where the .vscode folder is. The e2e, src etc folders should all be at the top level.

2020-03-10 12_36_19-launch.json - application - Visual Studio Code.png

 

Some Gotchas:

  • I’ve noticed that sometimes you still get the error “Breakpoint set but not yet bound” after the first try. After you build then try to debug, close VSCode and Chrome then open up again. That sometimes helps.
  • sourceMapPathOverrides is critical
  • Make sure that tsconfig.json has sourceMaps set to true
  • When you run the app in Chrome, go to the dev tools and see if the ts files are displayed like this:
2020-03-11 11_23_43-Cloning.png

#VSCode: One #Angular Workspace with multiple projects

In VS Code (Visual Studio Code) you can create a single Workspace with 1 git repo but contain multiple projects. This lets you create library and app and contain them all under the same angular.json as well.

Here’s how.

Create a folder where you’d like to create the Workspace. In my example e:\ngLearn\CLIPlayGround

2020-03-09 10_42_08-Select Windows PowerShell.png

VS Code will appear. Open the Terminal Ctrl+Shift+`

Now, ask the CLI to create an Workspace, but with no default application:

ng new –createApplication=false

In the prompt give your workspace a name, like my-workspace

2020-03-09 10_46_33-CLIPlayGround - Visual Studio Code.png

It’s take a few minutes to set up. If you open Windows Explorer you’ll see the new workspace made, but without any application inside:

2020-03-09 10_47_29-my-workspace.png

Let’s now add a few applications by using the commands in the new folder

cd .\my-workspace\

ng g application

Run this twice and you’ll then notice there are 2 applications in your workspace: under a new Projects folder

2020-03-09 10_50_11-CLIPlayGround - Visual Studio Code.png

 

 

#NDepend – Rate your .Net code

download.pngRecently I tried out the NDepend tool to see how it can help with code reviews and code quality assessment of .Net code in Visual Studio.

I found this tool to be helpful and it quickly found areas of code in our projects that need some extra help.

Once you run the tool, you get a report which lays out the good, the bad and the ugly in your code. This is helpful as it lets us focus on what is important, and perhaps how much work needed to fix an issue.

Here’s a summary example:

2020-03-09 09_01_20-NDepend Report.png

 

You can then drill down and see the detail:

2020-03-09 09_02_25-NDepend Report.png

NDepend comes with a Visual Studio plug as well as a stand alone version.

Xamarin iOS: Getting a list of Contacts

Getting Contacts from iOS and Android is a little harder than it really should be. I hope one day it will be added to Xamarin.Essentials, but until then, here’s how to get them in a simple way.

I won’t cover all the DTOs needed as those are simple and not really part of the point, but here’s the overview of the PhoneContact class I’ll use:

public class PhoneContact
{
    public string Identifier { getset; }
    public string FirstName { getset; }
    public string LastName { getset; }
    public List<PhoneNumberContact> PhoneNumbers { getset; } = new List<PhoneNumberContact>();
    public List<EmailContact> Emails { getset; } = new List<EmailContact>();
    public List<AddressContact> PostalAddresses { getset; } = new List<AddressContact>();
    public List<DateLabelContact> Dates { getset; } = new List<DateLabelContact>();
    public string DepartmentName { getset; }
    public List<InstantMessageContact> InstantMessageAddresses { getset; } = new List<InstantMessageContact>();
    public string JobTitle { getset; }
    public string OrganizationName { getset; }
    public List<SocialContact> SocialProfiles { getset; }
    public string Notes { getset; }
}

To get the contacts out of iOS, you can use this service. The namespace is marked as a Dependency so you could inject it into a Xamarin.Forms project.

using Contacts;
using Foundation;
using MyApp.Extensions;
using MyApp.Interfaces;
using MyApp.iOS.Dependencies;
using MyApp.Services.Contacts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Telerik.XamarinForms.Common.iOS;
using Xamarin.Forms;
 
[assemblyDependency(typeof(ContactService))]
namespace MyApp.iOS.Dependencies
{
 
    /// <summary>
    /// SEE for more help on Android: https://github.com/jamesmontemagno/Xamarin.Mobile/blob/master/MonoDroid/Xamarin.Mobile/Contacts/ContactHelper.cs
    /// </summary>
    public class ContactService : IContactService
    {
 
        public Task<IList<PhoneContact>> GetContactListAsync()
        {
            return Task.Run(GetContactList);
        }
 
        public IList<PhoneContactGetContactList()
        {
            List<PhoneContactresult = new List<PhoneContact>();
            try
            {
                var keysToFetch = new[]
                {
                    CNContactKey.GivenName,
                    CNContactKey.FamilyName,
                    CNContactKey.EmailAddresses  ,
                    CNContactKey.PhoneNumbers  ,
                    CNContactKey.OrganizationName,
                    CNContactKey.Dates,
                    CNContactKey.DepartmentName,
                    CNContactKey.Identifier,
                    CNContactKey.InstantMessageAddresses,
                    CNContactKey.JobTitle,
                    CNContactKey.Birthday,
                    CNContactKey.PostalAddresses,
                    CNContactKey.SocialProfiles,
                };
                var contactList = ReadRawContactList(keysToFetch);
 
                if (contactList != null)
                    result = GetContacts(contactList).ToList();
            }
            catch (Exception ex)
            {
                App.Logger.LogError(ex);
                result = new List<PhoneContact>();
            }
 
            return result;
        }
 
        private static IEnumerable<CNContactReadRawContactList(IEnumerable<NSStringkeysToFetch)
        {
            using (var store = new CNContactStore())
            {
                var allContainers = store.GetContainers(nullout _);
                return ContactListFromAllContainers(keysToFetchallContainersstore);
            }
 
        }
 
        private static IEnumerable<CNContactContactListFromAllContainers(
            IEnumerable<NSStringkeysToFetch,
            IEnumerable<CNContainerallContainers,
            CNContactStore store)
        {
            var nsStrings = keysToFetch.ToList();
            var contactList = new List<CNContact>();
            foreach (var container in allContainers)
            {
                var contacts = ReadFromContainer(nsStringscontainerstore);
                if (contacts != null)
                {
                    contactList.AddRange(contacts);
                }
                else
                {
                    Console.WriteLine("ERROR unable to get contacts");
                }
            }
 
            return contactList;
        }
 
        private static IEnumerable<CNContactReadFromContainer(
            IEnumerable<NSStringkeysToFetch,
            CNContainer container,
            CNContactStore store)
        {
            try
            {
                using (var predicate = CNContact.GetPredicateForContactsInContainer(container.Identifier))
                {
                    return store.GetUnifiedContacts(predicatekeysToFetch.ToArray(), out _);
                }
            }
            catch (Exception ex)
            {
                App.Logger.LogError(ex);
            }
 
            return null;
        }
 
        private static IEnumerable<PhoneContactGetContacts(IEnumerable<CNContactcontactList)
        {
            return contactList.Select(GetContact);
        }
 
        private static PhoneContact GetContact(CNContact item)
        {
            if (item == nullreturn new PhoneContact();
 
            try
            {
                var contact = new PhoneContact
                {
                    FirstName = item.GivenName,
                    LastName = item.FamilyName,
                    PhoneNumbers = item?.PhoneNumbers?
                        .Where(x => x.Value != null)
                        .Select(x => new PhoneNumberContact() { Name = x.Label, Phone = x.Value?.StringValue })
                        .ToList(),
                    Emails = item.EmailAddresses?
                        .Where(x => x.Value != null)
                        .Select(x => new EmailContact() { Name = x.Label, Email = x.Value?.PathComponents?.FirstOrDefault() })
                        .ToList(),
                    OrganizationName = item?.OrganizationName,
                    Dates = item?.Dates?
                        .Where(q => q.Value != null)
                        .Select(x => new DateLabelContact { Name = x.Label, Date = x.Value?.Date?.ToDateTime() }).ToList(),
                    DepartmentName = item.DepartmentName,
                    Identifier = item.Identifier,
                    InstantMessageAddresses = item?.InstantMessageAddresses?
                        .Where(x => x.Value != null)
                        .Select(x => new InstantMessageContact { Service = x.Value?.Service, Username = x.Value?.Username })
                        .ToList(),
                    JobTitle = item.JobTitle,
 
                    PostalAddresses = item?.PostalAddresses?
                        .Where(x => x.Value != null)
                        .Select(x => new AddressContact()
                        {
                            City = x.Value.City,
                            Country = x.Value.Country,
                            PostalCode = x.Value.PostalCode,
                            State = x.Value.State,
                            Street = x.Value.Street
                        }).ToList(),
                    SocialProfiles = item?.SocialProfiles?
                        .Where(x => x.Value != null)
                        .Select(x => new SocialContact() { Username = x.Value.Username, Service = x.Value.Service, }).ToList()
                };
 
                var birthDate = item?.Birthday?.Date?.ToDateTime().Date;
                if (birthDate != null)
                {
                    contact?.Dates?.Add(new DateLabelContact()
                    {
                        Name = "BIRTHDATE",
                        Date = birthDate
                    });
                }
 
                //  Console.WriteLine(contact.ToJson());
                return contact;
            }
            catch (Exception ex)
            {
                App.Logger.LogError(ex);
            }
 
            return null;
        }
 
    }
}

 

In my next post I’ll show you how to get it from Android, much harder sadly 😦