Enterprise Framework

Software Solutions in the Enterprise

How To : NopCommerce Best Practices For Database Updates using Entity Framework.

How To : NopCommerce Best Practices for Database Updates using Entity Framework.

Compatible With:  NopCommerce 3.7

These instructions will help you setup Entity Framework Migrations on the Nop.Data project with the assumption that you did a NopCommerce 3.7 fresh default database setup install with or without sample data. The NopCommerce default database install will be the base used.

Enabling Entity Framework Migrations will allow you to apply Entity Framework Code First to the database to update the default NopCommerce schema.  The benefits are that you have a starting point database with NopCommerce and any changes that you apply after that are captured as individual database changes that are applied to the NopCommerce Default database.  The Migrations can be reapplied later on to a Fresh NopCommerce install using the migrations.

Prerequisites:  

  • Fresh NopCommerce 3.7 Source Code Installed
  • Fresh NopCommerce 3.7 Database Installed with or without sample data

Getting Started:

  1. Open NopCommerce Solution
  2. Change Presentations\Nop.Web\Web.Config to point to the database you want to use.

      <connectionStrings>
        <add name="NopCommerce" providerName="System.Data.SqlClient" connectionString="Data Source=.;Initial Catalog=NopCommerce37;Integrated Security=False;User Id=sa;Password=yourpassword;MultipleActiveResultSets=True" />
      </connectionStrings>
    
  3. Open Package Manager Console
  4. Set Default project: Nop.Data 
  5. Type:  Enable-Migrations - this will create a folder called Migrations under the Nop.Data project.
  6. Type:  Add-Migration “InitialDatabaseSnapshot” –IgnoreChanges

    Note: The –IgnoreChanges switch will tell our Nop.Data project to not compare the Nop.Data Migrations against the current database. Because we don't have any existing migrations, by not using the "-IgnoreChanges", it would create all the code to regenerate all the tables from NopCommerce duplicating what NopCommerce will create by default. Our Migrations are meant to capture changes moving forward after the default NopCommerce 3.7 Database is setup and be easily reapplied.

After you have ran this, the Nop.Data project will have a new folder called Migrations with two new files:

  • Configuration.cs
  • {DateTimeStamp}_InitialDatabaseSnapshot.cs – Initial place holder for Migrations.  This has an empty Up() and Down() method intentionally because we used the "-IgnoreChanges" switch in our command earlier.  It assumes that Created the tables and sample data and anything moving forward is newly added.

Next Steps:  Applying the changes to the database 

In Package Manager Console:

  • Type:  Update-Database 

You should receive a confirmation that the project is ready.

This will enable Migrations in the database by adding a __Migrations table.  The __Migrations table is a history of Migration changes applied to it.  The newly added migration we created earlier InitialDatabaseSnapshot will to be applied to the default NopCommerce 3.7 database we setup earlier, but since we did the -IgnoreChanges switch, the {DateTimeStamp}_InitialDatabaseSnapshot.cs contains no code in Up() or Down(), so no changes are applied to the database with the exception of the newly added __Migrations table which is what we want.  If you open the new __Migrations table, it will have a single record for the InitialDatabaseSnapshot migration that was applied to the database.  Now that a record was captured for InitialDatabaseSnapshot, it will never be applied again to the database..

Your database and solution is now ready for Code First Updates using Migrations.


Next Steps:

ADDING A NEW ENTITY AND RUNNING ADD-MIGRATION

Important:  These instructions will create Migrations code to generate tables after the adding of new Entities 

Prerequisite:  

  • Added a newly Entity Person (Example:  Person.cs) to the Nop.Core\Domain\Custom;
Steps:
  • Open Presentations\Nop.Web\Web.Config and verify the connection string that it is pointing to the database you want to use.
  • Open:  Package Manager Console
  • set Default Project: Libraries\Nop.Data
  • Type:  Add-Migration “SomeDescriptionHere” 
  • Example:  Add-Migration Add New Person Entity

NOTE:  After you run “Add-Migration”, the Nop.Data project will have a new file called

  • {DateTimeStamp}_AddNewPersonEntity.cs

This new file contains code to generate any new tables from new Entities you have defined in Entity Framework in the Up () method and code to remove tables in the Down() method.

Type:  Update-Database

This will cause the newly added migration AddNewPersonEntity to be applied to the database and a new table called Person tables to be created.  The AddNewPersonEntity migration will be tracked in the __Migrations table so it’s never applied again.


How To : C# Numbers To Words Generator

Numbers To Words Generator - C# Project


Numbers to Words is a C# project that takes a number and converts it to a word.


NOTE:  THIS WAS DONE IN 3 HOURS FOR A TEST SO IT IS IN NO WAY SHAPE OR FORM CLEANED OR OPTIMIZED OR BEST PRACTICES.  HOWEVER, THIS PROJECT WAS BUILT DOING TDD (Test Driven Development) SO THERE A LOT OF TESTS TO VALIDATE IT AND SHOWS THE VALUE OF UNIT TESTS.


Example: (1000000 generates the words "One Million")

Project examples:

Ones (Example:  3 returns "Three")

Tens (Example:  14 returns "Fourteen")

Hundreds (Example:  397 returns "Three Hundred Ninety Seven")

Thousands (Example: 7923 returns "Seven Thousand Twenty Three")

Ten Thousands (Example:  22222 returns "Twenty Two Thousand Two Hundred Twenty Two")

Hundred Thousands (Example:  832935 returns "Eight Hundred Thirty Two Thousand Nine Hundre Thirty Five")

Millions (Example:  9882235 returns "Nine Million Eighty Hundred Eighty Two Thousand Two Hundred Thirty Five")

Billions (Example:  1012345678 returns "One Billion Twelve Million Three Hundred Fourty Five Thousand Six Hundred Seventy Eight")

Also supports decimal.  but in percent.  Have fun.

Source Code : https://github.com/Gigundo/Numbers-to-Words

How To : ASP.NET MVC With Microsoft Identity with a GUID Id and Unity Injection

How To : ASP.NET MVC With Microsoft Identity with a GUID Id and Unity Injection

This downloadable project contains the code to do ASP.NET Identity with a GUID ID and doing Unity Injection


Download File:  AspNet Identity Working with GUID ID and Unity Injection Final.zip (8.2MB)


Previous Version for default ASP.NET Identity is available :

http://www.enterpriseframework.com/post/how-to-asp-net-mvc-with-microsoft-identity-and-unity-bootstrapper


OpenStreetMap Mapnik Make Error: mapnik/version.hpp: No such file or directory

robert@robert-Ubuntu-Virtual-Platform:~/src/mod_tile$ make
Making all in iniparser3.0b
make[1]: Entering directory '/home/robert/src/mod_tile/iniparser3.0b'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/robert/src/mod_tile/iniparser3.0b'
make[1]: Entering directory '/home/robert/src/mod_tile'
g++ -DHAVE_CONFIG_H -I. -I./includes  -pthread -DSYSTEM_LIBINIPARSER=0   -g -O2 -MT src/renderd-gen_tile.o -MD -MP -MF src/.deps/renderd-gen_tile.Tpo -c -o src/renderd-gen_tile.o `test -f 'src/gen_tile.cpp' || echo './'`src/gen_tile.cpp
src/gen_tile.cpp:1:30: fatal error: mapnik/version.hpp: No such file or directory
 #include <mapnik/version.hpp>
                              ^
compilation terminated.
Makefile:1124: recipe for target 'src/renderd-gen_tile.o' failed
make[1]: *** [src/renderd-gen_tile.o] Error 1
make[1]: Leaving directory '/home/robert/src/mod_tile'
Makefile:1288: recipe for target 'all-recursive' failed
make: *** [all-recursive] Error 1


Fix the error by installing libmapnik-dev:


robert@robert-Ubuntu-Virtual-Platform:~/src/mod_tile$ sudo apt-get install libmapnik-dev

Auto Generate C# Client Proxy from Swagger Metadata from ASP.NET WEB API

Here are some tools for automatic C# client side proxy code generators from Swagger Metadata
 
Microsoft - Azure
Article:  Get started with API Apps and ASP.NET in Azure App Service
Section: Consume from a .NET client by using generated client code
Link : https://azure.microsoft.com/en-us/documentation/articles/app-service-api-dotnet-get-started/#codegen

Git Repository:  https://github.com/azure/autorest
Community - Swagger Code Generator
https://github.com/swagger-api/swagger-codegen
Community - NSwag
https://github.com/NSwag/NSwag
Microsoft - MSDN
Article:  Introducing the Azure API Apps Tools for Visual Studio 2013
Section:  Enable Developers with One-click Strongly-typed REST API Clients
Section:  One-click API App Client Code Generation in Visual Studio
Link:  http://blogs.msdn.com/b/visualstudio/archive/2015/03/24/introducing-the-azure-api-apps-tools-for-visual-studio-2013.aspx

C# Serialization - Deserialize from one Name and Serialize To A different Name

Scenario:

We have a Web Service which talks to a 3rd party service and receives json where the property names that are not standard to our organization.  We don't want the overhead of created multiple DTO objects to support transformations.

Example:  {"office_code" : "ABC1234"}  (office_code needs to be "Code")

We have to take the incoming json and deserialize to a organization standard POCO and run rules to it and serialize it again back out to the organization so it would now look like:

Example:  {"Code" : "ABC1234"} 

The workflow:

3rd Party Json => Our Web Service => Run Rules => Serialize to Internal consumer using company standard naming
so:
{"office_code" : "ABC1234"} => POCO Deserialzied to {"Code" : "ABC1234"} => Run Rules => POCO Serialized {"Code" : "ABC1234"}

example:  

Our Original POCO looks like:  If I Serialize it as is, it will have Code serialized to office_code which what I don't want.  I want to stay as Code
    [DataContract]
    public class Test
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Description { get; set; }

        [DataMember]
        public string Whatever { get; set; }

        [DataMember]
        [JsonProperty("office_code")]
        public string Code { get; set; }
}
Updated Test Object by adding a private method called _code with Attributes and method
   
        [DataMember]
        [JsonProperty("office_code")]
        private string _code { get; set; }
Then updated the public string Code property to use the private property _code

        [DataMember]
        public string Code
        {
            get
            {
                return _code;
            }
            set
            {
                _code = value;
            }
        }

Microsoft Serializer and Newtonsoft both support a method called ShouldSerialize{Property} that is not heavily documented.  We'll create a method for our _code property

        public bool ShouldSerialize_code()
        {
            return false;
        }
You can deserialize Json office_code to C# _code but when you Serialize Test, it will not serialize _code

    [DataContract]
    public class Test
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Description { get; set; }

        [DataMember]
        public string Whatever { get; set; }

        [DataMember]
        public string Code
        {
            get
            {
                return _code;
            }
            set
            {
                _code = value;
            }
        }

        [DataMember]
        [JsonProperty("office_code")]
        private string _code { get; set; }

        public bool ShouldSerialize_code()
        {
            return false;
        }

        public bool ShouldSerializeWhatever()
        {
            return false;
        }
    }
Running the Test
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Practices.Unity;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using System.Web.Http;

namespace Generic
{
    public class BlahController : ApiController
    {
        [HttpGet]
        public Test Get()
        {
            Test test1 = null;

            //JSON Deserialization string  {"Id":0,"Name":"Robert","Description":"Cool","office_code":"BlahBlahBlah"}
            //office_code will be deserialized to a private property called _code
            string deserializeFrom = "{\"Id\":0,\"Name\":\"Robert\",\"Description\":\"Cool\",\"office_code\":\"BlahBlahBlah\"}";

            test1 = JsonConvert.DeserializeObject(deserializeFrom);

            string serializeTo = JsonConvert.SerializeObject(test1);

            //Results
            // Json string to Serialized Object    {"Id":0,"Name":"Robert","Description":"Cool","office_code":"BlahBlahBlah"}
            // Serialized objec to json string     {"Id":0,"Name":"Robert","Description":"Cool","Code":"BlahBlahBlah"}

            //
            Test test2 = new Test();
            test2.Id = 0;
            test2.Name = "Robert";
            test2.Description = "Cool";
            test2.Whatever = "How Annoying";
            test2.Code = "BlahBlahBlah";
            //test._code = "BlahBlahBlah"  Inaccessible

            return test2;
        }
    }
}

AngularJS template javascript code from the snippets of John Papa's Angular Style Guide best practices

Here is the outputted AngularJS template javascript code from the snippets of John Papa's Angular Style Guide best practices

<script>
/* CONTROLLER BEST PRACTICE TEMPLATE */
(function() {
   'use strict';
   angular
       .module('module')
       .controller('Controller', Controller);
   Controller.$inject = ['dependencies'];
   /* @ngInject */
   function Controller(dependencies) {
       var vm = this;
       vm.title = 'Controller';
       activate();
       ////////////////
       function activate() {
       }
   }
})();
</script>

<script>
/* DIRECTIVE BEST PRACTICE TEMPLATE */
(function() {
   'use strict';
   angular
       .module('module')
       .directive('directive', directive);
   directive.$inject = ['dependencies'];
   /* @ngInject */
   function directive (dependencies) {
       // Usage:
       //
       // Creates:
       //
       var directive = {
           bindToController: true,
           controller: Controller,
           controllerAs: 'vm',
           link: link,
           restrict: 'A',
           scope: {
           }
       };
       return directive;
       function link(scope, element, attrs) {
       }
   }
   /* @ngInject */
   function Controller () {
   }
})();
</script>

<script>
/* FACTORY BEST PRACTICE TEMPLATE */
(function() {
   'use strict';
   angular
       .module('module')
       .factory('factory', factory);
   factory.$inject = ['dependencies'];
   /* @ngInject */
   function factory(dependencies) {
       var service = {
           func: func
       };
       return service;
       ////////////////
       function func() {
       }
   }
})();
</script>

<script>
/* FILTER BEST PRACTICE TEMPLATE */
(function() {
   'use strict';
   angular
       .module('module')
       .filter('filter', filter);
   function filter() {
       return filterFilter;
       ////////////////
       function filterFilter(params) {
           return params;
       };
   }
})();
</script>

<script>
/* SERVICE BEST PRACTICE TEMPLATE */
(function() {
   'use strict';
   angular
       .module('module')
       .service('Service', Service);
   Service.$inject = ['dependencies'];
   /* @ngInject */
   function Service(dependencies) {
       this.func = func;
       ////////////////
       function func() {
       }
   }
})();
</script>

Windows Server 2012 RabbitMQ Remote Access 3.0.0 and up

By default, trying to access RabbitMQ Management UI (http://localhost:15672/) from a remote machine is not allowed.  You must turn this on by setting the setting an environment variable and then creating a rabbitmq.config file before installing rabbitmq on Windows.

Here are the steps before you install. 

Clean Install on Windows Server 2012:

  1. Set System Environment Variables
    1. Go to System > Advanced System Settings > Advanced Tab > Environment Variables
    2. Under System variables > New...
    3. variable name  : RABBITMQ_BASE
      variable value : c:\rabbitmq
    4. Click OK
    5. Click OK at Environment Variables screen.
    6. Create a new file called rabbitmq.config in c:\rabbitmq
      1. Edit rabbitmq.config and paste the following into it: 
        [{rabbit, [{loopback_users, []}]}].
  2. Install Erlang
    1. Go to http://www.erlang.org/download.html
    2. Download:  OTP 17.5 Windows 64-bit Binary File (91.1 MB)
  3. Install RabbitMQ
    1. Go to https://www.rabbitmq.com/download.html
    2. Download:  RabbitMQ 3.5.3 Windows 

If you already installed rabbitmq, you will need to uninstall rabbitmq service and then do the above 1 through 3 steps.