C# Model Coding Practices

What is a model?  A model is a programmatic representation of a concept or physical object that exists in real life.  We represent models in code as Entities in C# and as Tables in the Database.  Since these entities and tables represent the same underlying model, they need to remain synchronized.  In the past, generally the database was created first and then the entities were generated from it.  Recently, this paradigm has changed…

Now, we are using a code-first model creation paradigm in which the programmers write the C# Entities and from those entities the database is generated.  When working in this manner, there are best practices that will make the process more simple.

First, when creating the entities, adhere to the Database Design Standards set by Ty.  Even though this document was written for designing databases, it still applies.  Just substitute “Entity” for “Table” and “Field” for “Column” and you should have no problems.  In addition to this, make sure to make all fields virtual.

public virtual int UserRoleId { get; set; }

Next, for any foreign key field, add another field named and typed the same as the foreign key entity.  For example:

public virtual int UserRoleId { get; set; }
public virtual UserRole UserRole { get; set; }

This gets us most of the way to where we want to be, but sometimes we want certain behavior in table or column creation, in how Entity Framework treats the entity, or in data serialization.  Below are a list of common attributes and what they do:

Class level attributes:

  • DataContract – Tells the data serializer that we are using an opt-in policy.  This means that only fields which are decorated with the DataMember attribute will be serialized.  This attribute is highly recommended as it gives you complete control over which fields are transmitted.
  • Table – Specifies to the code-first model generator the table name that you wish to map this entity to.  This is useful if you want the table to be named something different than the entity and is not required in most cases.

Field level attributes:

  • DataMember – Works with the DataContract attribute.  Used to specify that the field it decorates is meant to be serialized.
  • Key – Identifies this field as the primary key for the database table it represents
  • DatabaseGenerated – Indicates to the code first model generator and Entity Framework that this field will be updated by the database and not the user.  This can be applied to fields like primary keys and database generated dates (last update date) but use discretion as to when you apply this attribute.
  • Required – Tells the Entity Framework validator that this field is required and allows you to specify an error message upon failed validation
  • StringLength – Tells the entity validator that this field has a max and min range for string length and allows you to specify these ranges and an error message.
  • Display – An intended display name for the field
  • ForeignKey – Indicates that the field is a foreign key

Below is an example of a class which uses most of these attributes:


    [DataContract]
    public class User
    {
        /// The identifier for the user.  Also the primary key.
        [Key]
        [DataMember]
        public virtual Guid UserId { get; set; }

        /// Foreign key to the UserRole table/object.
        [Required]
        [DataMember]
        public virtual int UserRoleId { get; set; }

        /// UserRole object associated with this User.
        [ForeignKey( "UserRoleId" )]
        public virtual UserRole UserRole { get; set; }

        /// The login user ID for the user.
        [Required( ErrorMessage = "Login is required." )]
        [StringLength(100, ErrorMessage = "Login cannot be longer than 100 characters.")]
        [DataMember]
        public virtual string Login { get; set; }

        /// The hashed password for the user.
        [Required( ErrorMessage = "Password is required." )]
        [StringLength(40, ErrorMessage = "Password cannot be longer than 40 characters.")]
        [DataMember]
        public virtual string Password { get; set; }

        /// The driver's first name.
        [StringLength( 100, ErrorMessage = "First Name cannot be longer than 100 characters." )]
        [Display(Name = "First Name")]
        [DataMember]
        public virtual string FirstName { get; set; }

        /// The driver's last name
        [Required( ErrorMessage = "Last Name is required." )]
        [StringLength( 100, ErrorMessage = "Last Name cannot be longer than 100 characters." )]
        [Display(Name = "Last Name")]
        [DataMember]
        public virtual string LastName { get; set; }

        [DataMember]
        public virtual Guid BaseUserId { get; set; }

    }

The next step is to create a database context class.  This is how Entity Framework communicates with the database.  You need to add a field which corresponds to each table you want to create in the database from code. Each record in the database context is a line of communication between Entity Framework and the database for the specified table/entity.  After creating your database context, the first thing you should do is remove the convention of cascading deletes.  While this can save time in certain situations, it also allows for the opportunity to delete large amounts of data by accident.  A basic database context class looks like this:


public class DatabaseContext : DbContext
    {
        public  DatabaseContext()
            : base("name=DefaultConnection")
        {
        }

        // tables
        public DbSet Users { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        }

    }

This can optionally be generated by MVC scaffolding.

The last topic I have to discuss is, “How do I work with database views using Entity Framework and code-first?”  Currently, code first cannot create the view for you.  You need to create the view in the database itself, then create an entity that represents it.  You could probably add the creation script for the view to the migration created by code first, but that would be a topic for a different presentation.  To connect a view to an entity, the procedure is pretty much the same as with a table with the following exceptions:

  • Create the view in the database.  Specify the view’s base table as the “primary key”.  For example, the primary key for a UsersView should be UserId.  While views technically do not have a primary key, this makes Entity Framework happy and generated code works better.
  • Add the “Table” attribute to the entity’s class definition and specify the view name.  Otherwise the code-first model generator will automatically attempt to pluralize your view and it will end up pointing to the wrong object in the database.  Pluralization works well for table creation (Users) but not for views (UsersViews?)
  • Use the add-migration command to create the migration script and then comment out the table creation code.  As stated above, you can optionally add code for view creation here at this time.

Below is an example of the class definition and primary key setup for a view:


    [DataContract]
    //This makes the database generator link to "HeatDriverYearsView".  Otherwise   
    //it would attempt to pluralize the class name and create a new table 
    //(HeatDriverYearsViews)
    [Table("HeatDriverYearsView")]
    public class HeatDriverYearsView
    {
        /// The identifier for the heat.  Also the primary key.
        [Key]
        [DataMember]
        //Even though views have no primary keys, this property will act like one.
        //There will only be one HeatDriverYearsView record per HeatId
        public virtual int HeatId { get; set; }

It is worth while to note that using views is one of a few ways to handle retrieving data from multiple tables.  Another way is to add commands to existing entities and use LINQ to perform any joins manually.  This has its own set of pros and cons so use your judgement as to which methodology to use.

CruiseControl.net Basics and Setting Up a New Project

The basics of using CruiseControl.net start with using the GUI to manage the different builds for each environment. Within the web app there are a few tips that can help in diagnosing problems when the build is broken. We will cover those items along with the basic items that need to be set up on a new project in this blog.

CruiseControl.net Web App

CaptureCC.NetGUI_Home

I will forego much of the obvious on the CC.NET home page. A couple  items worth noting is that this page can become stale very quickly especially if you keep it open in your browser. Each time returning to the home page it is a good idea to go ahead and click the Refresh button located in the upper right hand corner of the page to make sure that you have the most up to date information about the builds. Its also a good idea if you are waiting for a build to complete or have just forced a build that you go ahead and click the Refresh button to make sure you see the latest changes as quickly as possible. Another item to note is that when the build breaks all the people who commit after the build breaks will be listed as a breaker.

CaptureCC.NetGUI_ProjReportPage

In order to see who is responsible for breaking the build / bringing donuts to the next meeting click on the project name to dig into the details for the project.  If the build is broken then under the Build Overview chart  clicking on the first that broke(where the color changed from green to orange) will show the details of what was committed and by whom.

Once drilling into a build there are some important items that can be helpful in trouble shooting what is breaking the build. On the left navigation click on Latest Build and then on the left navigation click View Build Log will show the scripts that are run by MSBuild to build the dlls for the project along with all other scripts set up to run such as deployment scripts that will create backups and deploy the dlls to the web server. You can look at what is failing on each script that is run but usually its best to scroll to the bottom of the page to find quickly what is causing the build to break or causing other scripts to not work properly.

Setting up a New CruiseControl.NET Project

Step 1:

Create a new build project in CC.Net config and configure

To configure a CC.Net project first navigate to the config file located on the build.reurgency.net VM at  C:Program Files (x86)CruiseControl.NETserverccnet.config.

An example of the configuration for a project in the ccnet.config:


<project name="Youngevity" queue="Q1" queuePriority="1">
   <webURL>http://localhost/ccnet/</webURL>
   <workingDirectory>E:CIYoungevityWorking</workingDirectory>
   <artifactDirectory>E:CIYoungevityArtifacts</artifactDirectory>
   <modificationDelaySeconds>10</modificationDelaySeconds>
   <labeller type="assemblyVersionLabeller">
      <major>1</major>
      <minor>0</minor>
      <build>0</build>
      <incrementOnFailure>false</incrementOnFailure>
   </labeller>

   <triggers>
      <intervalTrigger seconds="60" name="continuous" />
   </triggers>

   <sourcecontrol type="svn">
      <trunkUrl>https://source.reurgency.net/svn/Youngevity/trunk/</trunkUrl>
      <executable>C:Program Files (x86)CollabNetSubversion Clientsvn.exe</executable>
      <username>CruiseControl</username>
      <password>21M6yI750528B7</password>
      <timeout units="minutes">30</timeout>
   </sourcecontrol>

   <prebuild>
   </prebuild>

   <tasks>
   <msbuild>
      <executable>C:WINDOWSMicrosoft.NETFrameworkv4.0.30319MSBuild.exe</executable>
      <projectFile>.Youngevity.sln</projectFile>
      <targets>Build</targets>
      <buildArgs>/p:Configuration=Release</buildArgs>
      <timeout>900</timeout>
      <logger>C:Program Files (x86)CruiseControl.NETserverThoughtWorks.CruiseControl.MsBuild.dll</logger>
   </msbuild>
   <exec>
      <executable>E:CIYoungevityScriptsCopyDLLsToLatestBuild.bat</executable>
   </exec>
   <exec>
      <executable>E:CIYoungevityScriptsZip.bat</executable>
   </exec>
   <exec>
      <executable>E:CIYoungevityScriptsDeployWebServiceDLLs.bat</executable>
   </exec>
   </tasks>

   <publishers>
      <!--
      <buildpublisher>
      </buildpublisher>
-->
   <merge>
      <files>
      </files>
   </merge>
   <xmllogger />
   <statistics />
   <modificationHistory onlyLogWhenChangesFound="true" />
   </publishers>
</project>

Start by copying a project already set up in the cc.net config and renaming it. There are quite a few things that can be configured but for many projects much of the configuration will stay the same. The items that must be configured are:
1) Paths to the Working and Artifact folders
2) The interval trigger in the triggers section can be commented out if you want the build to only be updated when it is forced manually. This can be uncommented for a Dev1 environment that should be continually updated whenever any new code has been committed.
3) The trunkUrl under the SourceControl section should be set to the path of the correct SVN repository
4) Set the projectFile under the MSBuild task to the correct solution file
5) Change the path for batch files for all the executables for the new project

Step 2:

Allow permissions for the project  folder on the web server to allow CruiseControl access to deploy new files for the project

1) Navigate to the folder through windows explorer(this folder is usually under the default inetpub IIS folder)
2) Right click on folder, click on Properties, select the Sharing tab. Under Network File and Folder Sharing click on the Share button. In the drop down type in CruiseControl and hit enter. Make sure to change CruiseControl’s permission level to Read/Write, select from the list and click the Share button. Copy the Network Path as this is the path that you will need to use for the deployment batch file

Step 3:

Set up folders and scripts  for the new project

1) Create a new project folder under E:\CI on the build server
2) Create folders for Artifacts, Builds, Scripts, and Working files under the new project folder
3) Copy over batch files from another project into the Scripts folder and configure for the needs of the new project – there at least needs to be batch files for copying and zipping up latest dlls into the builds folder and a batch file for deploying dlls and files to the web server.

Step 4:

Allow User permission for CruiseControl to read from the SVN repository through VisualSVNServer

1) On the build server open up VisualSVNServer Manager
2) On the left section of the VisualSVNServer Manager expand the node of repositories and find the repository for the new project, right click on the repository, and click on Properties. Under the security tab add CruiseControl as a user with Read access.

If everything is configured correctly the project will be set up and can be managed from the CruiseControl.NET web app.

 

AngularJS and Cookies (Continued)

As my esteemed colleague Robbie Pell has pointed out in a recent post, AngularJS provides an easy mechanism for setting and retrieving cookies but this mechanism comes with several notable limitations.  Robbie’s post outlines the fact that AngularJS provides no way to set an expiration date on a cookie which causes the cookie to expire when the browser session ends.

I have uncovered an additional limitation.  It appears that AngularJS also does not provide a way to specify which subdirectories of a domain the cookie applies to.  This causes the cookie to, by default, only be applied to the subdirectory in which it is set.  For example, if I set a cookie from a page at http://dev1.derby.reurgency.net/derby/racetracker/index.html using AngularJS the cookie will not be visible at http://dev1.derby.reurgency.net/derby/api/ causing all API calls which require that specific cookie to fail.

The solution to this is to, once again, set the cookies manually outside of AngularJS.  I have built on Robbie’s example below:

var expirationDate = new Date();
var myValue;
var path = "/";

expirationDate.setDate(expirationDate.getDate() + 30);
document.cookie = "MyToken" + "=" + myValue + "; path=" + path + "; expires=" + expirationDate.toUTCString();

In the example above, the cookie will be applied to all subdirectories within the current domain.  Alternatively, you can specify a subdirectory to apply the cookie to by altering the “path” variable.

Applying security to WebAPI controllers

When using the Reurgency.Common framework, every REST service method requires security permissions to be applied via an attribute on either the method or the class.  This blog post describes how to do that.

First add some USING statements.

using Reurgency.Foundation.WebApi;
using Reurgency.Foundation.WebApi.Filters;

Then add the attribute HandleSecurityTokenRequest to either the class or individual methods

Here is an example of using the attribute on a class. ALL methods in the class will inherit this setting.

[HandleSecurityTokenRequest(AllowAnonymous = false)]
public class EmployeesController : <Employee>
{

That’s it.  You are done.

Read on to understand a little more how this works.

Here is an example of a using the attribute on a method. This is useful when you want to set different security on each method within a class.

[HandleSecurityTokenRequest(AllowAnonymous = true)]
[HttpPost]
public HttpResponseMessage Login(Credential credential)
{
BusinessCommandRepository biz = new BusinessCommandRepository(this.securityTokenId, "Login");

As you can see the attribute takes in one parameter called AllowAnonymous.  When set to false the system expects that a valid security token is passed in via headers or cookies.  If a valid security token is not passed in an HTTP Status code of 401 is returned to the client.   When AllowAnonymous is set to true, then the system will first look for a valid security token in the header or cookies and use that, else it will use the constant defined in Reurgency.Common.Model.Entities.SecurityToken.ANONYMOUSSECURITYTOKEN.

Each WebAPI method is responsible for instantiating the BusinessCommandRepository.  The constructor for that class requires a security token.  Simply use this.securityTokenId.

BusinessCommandRepository biz = new BusinessCommandRepository(this.securityTokenId, "Login");

The securityTokenId property is part of Reurgency.Foundation.WebApi.WebApiController.  Every one of your WebAPI controllers should inherit from this class.

It is the responsibility of the HandleSecurityTokenRequest filter attribute to populate this.securityTokenId from either header, cookies, or ANONYMOUSSECURITYTOKEN.  Because the filters are processed PRIOR to the WebAPI method’s execution, you are guaranteed that this.securityTokenId will be populated or a 401 error will be thrown.

Get the Android SDK & Phonegap to work

Getting the create Command to Work on PhoneGap 2.x Android. Huge thanks to Simon MacDonald

Start with the PhoneGap setup documentation here:

http://docs.phonegap.com/en/2.7.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android

Then fix it here:

http://simonmacdonald.blogspot.ca/2012/11/getting-create-command-to-work-on.html

If I only knew this sooner

Things that it would have been nice to know:

  1. Android package names can only contain letters & periods. NO NUMBERS or SPECIAL CHARACTERS
  2. PhoneGapBuild Keys cannot be edited or deleted, so be precise and descriptive in your naming conventions
  3. It is important for us to decide on a good structure for application versions/environments. Managing multiple installs on multiple devices, pointed at multiple server environments

Creating your .keystore file to sign your Android APK

The APK signing process for android, although much simpler than iOS IPA signing, can still be another challenge for first time app developers. Again, it’s all about finding the right starting point, and syntax.

To Create our keystore We will use the keytool.exe included in the Java JDK. Open a command-line and navigate to your Java bin directory. For Windows 7, mine is located at
C:Program Files (x86)Javajre7bin
Next, run the following command. Be sure to replace the NAME & ALIAS with your values.
keytool -genkey -v -keystore [NAME HERE].keystore -alias [ALIAS NAME HERE] -keyalg RSA -keysize 2048 -validity 10000
The keytool will prompt you for the other required information for the keystore, Like Name, location, and password, but it’s all very basic.

That’s it. The .keystore file will be placed in your java bin directory, and you’re ready to go.

WebAPI Routing and Custom Get Methods

The default structure of the routing we are using for our Web API service layer is set up to take an integer or a guid as the id for GET requests. This is done because it is a best practice when creating a database to have the primary key as an integer or guid. In our routing this is implemented with this default route:

config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"^{?[dA-Fa-f]{8}-[dA-Fa-f]{4}-[dA-Fa-f]{4}-[dA-Fa-f]{4}-[dA-Fa-f]{12}}?$|d+" });

If an id is specified then the route uses a regular expression to allow only an integer or guid as the id parameter. This is important not only because it is a best practice but also because it allows us to create custom methods by using this route:

config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });

This Web API route takes an action in the URI via the {action} placeholder. The action placeholder is a string that will match the method name that is specified in the Web API controller. This is possible because we are not allowing strings in the “DefaultApiWithId” route that we mentioned previously.

A problem that was encountered on the Youngevity project was that the Ids that were used from a third party api included numbers and letters. So if an id with both integers and letters was passed in the URI like:

api/customers/RA1234

then the route would match the DefaultApiWithAction route and would attempt to find a Web API controller method called RA1234. This problem will most likely be encountered again in the future on projects.

So what are the possible options for routing to allow a string as an id?

1) Pass the id in the querystring to bypass routing alltogether and let the controller parse the id out of the querystring
2) Reconfigure the routing that we already have in place and specify a route that accepts an id as a string
3) Create a custom GET method that takes in a string as an id parameter

The method we have chosen to use is the third. When I first looked at the problem I thought “I don’t want to create a custom method to do a normal GET method” but after thinking about the problem and talking to Ty realized that Ids should be created as integers or guids and that a string as an Id is actually an abnormal situation that should be handled via a custom method.

The simple solution:
1) Create a custom method like GetCustomerByString and decorate with the HttpGet attribute
2) Call the method via a URI like: api/customers/GetCustomerByString/RA1234

Sign iOS apps on a PC

The following information can be used to create profiles and certificates on a PC to sign a iOS app. Info in this post was taken from a great playlist of video instructions found at http://www.youtube.com/playlist?list=PL57C122F59F8F1A43

These operations require OpenSSL Fow Windows. You can get this at http://slproweb.com/products/Win32OpenSSL.html Download & install the Win32 or Win64 OpenSSL Light Client.

VARIABLES TO FIND/REPLACE
##PATH_TO_OPEN_SSL_BIN## - Ex: C:OpenSSL-Win64bin
##KEY_NAME## - Ex: reUrgencyMobileApp
##CONTACT_EMAIL## - Ex: apps@reUrgency.com
##CONTACT_NAME## - Ex: John Doe
##ENVIRONMENT## - Ex: Dev

Open a Command Prompt & cd to your OpenSSL bin directory

Run the following command to set your OpenSSL config path:

set OPENSSL_CONF=##PATH_TO_OPEN_SSL_BIN##openssl.cfg

Run the following command to create your Application Key

openssl genrsa -out ##KEY_NAME##.key 2048

Run the following command to create your Certificate Signing Requuest

openssl req -new -key ##KEY_NAME##.key -out ##KEY_NAME##_CSR.certSigningReq­uest -subj "/emailAddress=##CONTACT_EMAIL##, CN=##CONTACT_NAME##, C=US"

Run the following command to create your Signing Profile

openssl x509 -in ##KEY_NAME##_##ENVIRONMENT##.cer -inform DER -out ##KEY_NAME##_##ENVIRONMENT##.pem -outform PEM

Run the following command to create your .p12 signing certificate

openssl pkcs12 -export -inkey ##KEY_NAME##.key -in ##KEY_NAME##_##ENVIRONMENT##.pem -out ##KEY_NAME##_##ENVIRONMENT##.p12

Custom Exceptions and Angular Error Handling

This blog covers a straight forward example of handling errors via custom exceptions from the server and displaying the exception message on the client using an angular service.

Server:

Step 1:

Create Custom Exceptions

namespace Business.Exceptions
{
  public class ProblematicWebServiceException : Exception
  {
   public ProblematicWebServiceException()
   : base()
   {

   }
   public ProblematicWebServiceException(string message)
   : base(message)
   {

   }
   public ProblematicWebServiceException(string message, Exception innerException)
   : base(message, innerException)
   {

   }
  }
}

Step 2:

Wrap code that has the potential to fail in try/catch blocks and throw custom exception with a helpful error message. This is probably going to be in the Business layer depending on the architecture of the application.

try
{
   problematicService.GetSomeStuff();
}
catch (Exception)
{
   throw new Business.Exceptions.ProblematicWebServiceException("The Problematic Web Service is temporarily down.");
}

 

Step 3:

Catch exceptions as they bubble up to the application’s service layer and return appropriate Http Status Code(Service Unavailable 503 in this case):

catch (Business.Exceptions.ProblematicWebServiceException ex)
            {
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
                {
                    Content = new StringContent(ex.Message)
                };
                throw new HttpResponseException(response);
            }

Client:

Step 4:

Create Shared Service to handle errors:


angular.module('Shared.Services.SharedDataService', [])
    .service('sharedData', ['$rootScope', '$cookies', '$http', '$location',  function ($rootScope, $cookies, $http, $location) {
   var handleFault = function (context,error) {

   if (error.status === 503 && error.data) {
                errorMessage = error.data;
            }

   return {message:errorMessage,details:errorDetails}
        };
}

Step 5:

Handle error using $resource’s error callback to display the error message to the user:

MyResource.get({ 'id': customerId },
        function (response) {
            $location.path('/customerDetails/' + customerId);
        },
        function (error) {
            $scope.isError = true;
            $scope.errorMessage = sharedData.handleFault("gettingProblematicServiceCustomer", error).message;
        });