Country Tag Helper–part 4

 

Now I want to see somewhere in order to prove it Ii s right. I choose https://appharbor.com/ because it is free – and can not beat free for free source.

I made github integration and modify the .csproj file accordingly to https://support.appharbor.com/discussions/problems/90387-is-net-core-supported-yet 

The result is at http://countrytaghelper.apphb.com/ 

Also , I have to modify the code source to get the ip of the user :

string GetUserIP(ViewContext vc)
        {
            StringValues headerFwd;
            if (ViewContext.HttpContext?.Request?.Headers?.TryGetValue("X-Forwarded-For", out headerFwd) ?? false)
            {
                string rawValues = headerFwd.ToString();
                if (!string.IsNullOrWhiteSpace(rawValues))
                {
                    return rawValues.Split(',')[0];
                }

            }
            return ViewContext.HttpContext?.Connection?.RemoteIpAddress?.ToString();

        }

where ViewContext is

 [ViewContext]
        public ViewContext ViewContext { get; set; }

Friday links 229

  1. Building a Great Hosted Web App | Building Apps for Windows 
  2.   Expecting Failures In Microservices and Working Around Them
  3. Samsung Galaxy Note Edge vs Samsung Galaxy Note 5 – Phone specs comparison
  4. Compare Samsung Galaxy Note 5 vs Samsung Galaxy Note Edge Size, Specs, Camera
  5. NReco.VideoConverter: C# FFMpeg wrapper .NET library (FREE)
  6. OfficeDev/Open-Xml-PowerTools
  7.  NuGetPackageExplorer/NuGetPackageExplorer: The new home for NuGetPackageExplorer (moved from https://npe.codeplex.com)
  8. Async OOP 1: Inheritance and Interfaces
  9. Using-blocks and asynchronous operations
  10. Async disposal
  11. How to Encrypt and Protect your Email | Comparitech
  12. The Role of an Enterprise Architect in a Lean Enterprise
  13. New: ASP.NET Session State Provider for SQL Server In-Memory OLTP | SQL Server Blog
  14. Microsoft/BotBuilder: The Microsoft Bot Builder SDK is one of three main components of the Microsoft Bot Framework. The Microsoft Bot Framework provides just what you need to build and connect intelligent bots that interact naturally wherever your users a
  15. How to program using PostSharp in C# | InfoWorld
  16. The Zen of Code Reviews: Review As If You Own the Code
  17. lukebuehler/CShell: A simple, yet powerful, C# scripting IDE and REPL
  18. 12 years, 12 lessons working at ThoughtWorks |
  19. How to destroy Programmer Productivity | George Stocker
  20. ed2428f803e5cff6f1f48d89b1e602c5.jpg (720×629)
  21. Why “Agile” and especially Scrum are terrible – Michael O. Church
  22. A Gamer’s Blog: 05/01/2007 – 06/01/2007
  23. How to call WinRT APIs in Windows 8 from C# Desktop Applications – WinRT Diagram – Scott Hanselman
  24. Stop ‘innovating’: Aim higher | VentureBeat | Entrepreneur | by Iliya Rybchin, Highnote Foundry
  25. MyDriving | Microsoft Azure
  26. IConfiguration in .NetCore
  27. itext/itextpdf: Core Java Library + PDF/A, xtra and XML Worker
  28. Create Responsive AMP Pages
  29. C# 7 Features Previewed
  30. SSubjectivity : Naming Standards – SQL Sentry Team Blog
  31. The Codist: My Biggest Regret As A Programmer
  32.  jacobslusser/ScintillaNET: A Windows Forms control, wrapper, and bindings for the Scintilla text editor.
  33. Jolt.NET : Productivity Libraries for the .NET Framework – Documentation

Country Tag Helper – part 3

Adding empty item – easy peasy. Just append "<option selected style=’display: none’ value=”></option>";

 

if (ASPCountryEmpty)
                {
                    string empty = "<option selected style='display: none' value=''></option>";
                    output.Content.AppendHtml(empty);
                }

For getting the IP, I was trying to balance the 2 variants: downloading GeoIP database (https://dev.maxmind.com/geoip/geoip2/geolite2/) or calling http://freegeoip.net/ .

I do call http://freegeoip.net/ – and the next point is to use Dependency Injection … or a provider to do that.

For the moment, the code is:

 private async Task<string> GetCountryCodeFromIP(string ip)
        {
            //ip= "188.25.145.65";
            var url = "http://freegeoip.net/csv/"+ip;
            var request = WebRequest.Create(url);
            request.Method = "GET";
            using (var wr = await request.GetResponseAsync())
            {
                using (var receiveStream = wr.GetResponseStream())
                {
                    using (var reader = new StreamReader(receiveStream, Encoding.UTF8))
                    {
                        string content = reader.ReadToEnd();
                        return content.Split(',')[1];
                    }
                        
                }
                    
            }


        }

CountryTagHelper–part 2

Finally, I have arrived at functionality. I said that I want something like

<select asp-country="true" asp-country-selected="US" >
   
</select>

 

The functionality is very easy to be added:

The entire class is :

using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace CTHWeb.Controllers
{
    [HtmlTargetElement("select", Attributes = ASPCountryAttributeName)]
    public class CountryTagHelper:TagHelper
    {
        private const string ASPCountryAttributeName = "asp-country";
        private const string ASPCountrySelectedAttributeName = "asp-country-selected";

        [HtmlAttributeName(ASPCountryAttributeName)]
        public bool ASPCountry { get; set; }

        [HtmlAttributeName(ASPCountrySelectedAttributeName)]
        public string ASPCountrySelected{ get; set; }

        static string[] CountryISO;
        //static PropertyInfo[] properties;
        static CountryTagHelper()
        {
            var t =typeof( ResCTH);
            var properties= t.GetProperties(
                BindingFlags.Public |
                BindingFlags.Static |
                BindingFlags.GetProperty);
            CountryISO = properties
                .Where(it=>it.Name.Length==2)
                .Select(it => it.Name)
                .ToArray();
        }
        public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (ASPCountry)
            {
                bool existSelected = !string.IsNullOrWhiteSpace(ASPCountrySelected);
                string option = "<option value='{0}' {2}>{1}</option>";
                foreach (var item in CountryISO)
                {
                    string selected = "";
                    string localizedName = ResCTH.ResourceManager.GetString(item);
                    if (existSelected)
                    {
                        bool currentItem = string.Equals(item, ASPCountrySelected, StringComparison.CurrentCultureIgnoreCase);
                        currentItem = currentItem || string.Equals(localizedName, ASPCountrySelected, StringComparison.CurrentCultureIgnoreCase);
                        if (currentItem)
                            selected = "selected";
                    }
                    output.Content.AppendFormat(option, item, localizedName,selected);
                }
            }
            return base.ProcessAsync(context, output);
        }
    }
}

 

The important thing is that it works with other html attributes, like

<select asp-country="true" asp-country-selected="US" disabled=”disabled”>
   
</select>

 

What it remains to be done:

  1. from IP – recognize the country of the visitor from IP
  2. localized – display messages in other language
  3. first item empty – now it selects Andorra
  4. Add select2 with image flags
  5. NuGet package
  6. readme.md / wiki on github
  7. tests

Country tag helper–part 1

 

What I want to do is to create a Country Tag Helper for asp.net core.

Something like

<select asp-country=”true”

and then list all countries in this select. More, it should be localized ( Germany vs Allemagne). That means 1 or more resource files 

 

First I need initial data: The WorldBank API gives us the names http://api.worldbank.org/countries and I have made a project https://github.com/ignatandrei/WorldBankAPi that inspects that API.

To retrieve data in resource format , it is simple:

 var r = new CountriesRepository();
            var arr = r.GetCountries().Result.
                Select(it =>
                $"<data name = \"{it.iso2Code}\" xml:space=\"preserve\" >" +

                $"<value>{it.name}</value>" +
                "</data>").ToArray();
            var s = string.Join(Environment.NewLine, arr);
            File.WriteAllText(@"D:\c.txt", s);

 

Then we could copy paste into resources:

 <data name = "AW" xml:space="preserve" ><value>Aruba</value></data>
  <data name = "AF" xml:space="preserve" ><value>Afghanistan</value></data>
  <data name = "AO" xml:space="preserve" ><value>Angola</value></data>
 ...

 

Now I want to make a list of those names – so I need this code to translate between C# generated code from resource

public static string AD {
            get {
                return ResourceManager.GetString("AD", resourceCulture);
            }
        }
public static string AE {
            get {
                return ResourceManager.GetString("AE", resourceCulture);
            }
        }
...

 

and a list of names to be put into select.

Reflection to the rescue:

  var t =typeof( ResCTH);
            properties= t.GetProperties(
                BindingFlags.Public |
                BindingFlags.Static |
                BindingFlags.GetProperty);
            CountryISO = properties
                .Where(it=>it.Name.Length==2)
                .Select(it => it.Name)
                .ToArray();

 

The code is on github https://github.com/ignatandrei/CountryTagHelper and I will improve next time.

Friday links 226

  1. Top 15 Underutilized Features of .NET
  2. Top 15 Underutilized Features of .NET Part 2
  3. Louis Davidson : Getting the difference between two sets of like data
  4. App-vNext/Polly: Polly is a .NET 3.5 / 4.0 / 4.5 / PCL library that allows developers to express transient exception handling policies such as Retry, Retry Forever, Wait and Retry or Circuit Breaker in a fluent manner.
  5. dbelmont/ExpressionBuilder
  6. Youtube Downloader in One Easy Class – CodeProject
  7. Career Guide for the New Developer
  8. Harvard psychologist Amy Cuddy says people judge you on 2 criteria – Business Insider
  9. StructureMap – Supported Lifecycles
  10. Jquery Ajax Request and MVC detailed « A Programmer with Microsoft tools
  11. Friendly, Readable Expression Trees
  12. 18F — Software maintenance is an anti-pattern
  13. Getting Started with Bower – Treehouse Blog
  14. NuGet Package of the Week: ASP.NET Web API Caching with CacheCow and CacheOutput – Scott Hanselman
  15. Less Than Dot – Blog – MVVM Validation with KnockoutJS – Don’t put it in the View/HTML
  16. WEIRD – RationalWiki
  17. C# 7 Feature Proposal: Local Functions – Bill Wagner
  18. Dubai is set to unveil spectacular floating apartments with underwater rooms
  19. Software has bugs. This is normal. — Signal v. Noise — Medium
  20.    Visual Studio: How to create a solution template with multiple projects – Jayway
  21. Avoiding the Service Locator Pattern in ASP.NET Core
  22. Service Locator is an Anti-Pattern
  23. Service Locator violates SOLID
  24. Service Locator violates encapsulation
  25. Service Locator: roles vs. mechanics
  26. Suremaker/LightBDD: Lightweight Behavior Driven Development test framework
  27. John L. Miller’s answer to Google: How does Google provide so much online storage for Youtube videos? – Quora
  28. John L. Miller’s answer to What is the best way to read software documentation? – Quora