Thursday, June 30, 2016

Beginners guide to Umbraco 7: A guide for developers Part 1

Introduction

Some months ago, I've started to work with Umbraco. First I've tried to understand how it works and what do I need to know in order to implement good code with Umbraco, but actually it took more time than I've imagined.
The reason is Umbraco is very flexible which makes it easy to work for content managers, front-enders, and us (C# developers, back-enders, full-stack developers). You can easily implement lots of stuff inside Umbraco without needing any IDE and there is no need to implement a controller, service or anything. So if you are using it to implement a simple website that doesn't need that much code implementation or software structure, there is no need to read my post :)

As a developer why do I need Umbraco (or any CMS)?
If you want to develop some code on Umbraco, you probably have some user specific scenarios that you need to implement in your code and at the same time, you want to give some flexibility to the editors to use your structure and their creativity to make good content. For instance, recently I needed to create a rule engine in a project. It took me only a couple of hours to implement 4 different rule type, setting the consumers up and adding them to my pages. only 2 hours from A to Z :)

Where to start?
There are some videos in http://umbraco.tv/. Start from there and learn the structure of Umbraco and how it works. It is  Then come back and continue this post :)
You will learn:
*What is Umbraco's back office
*How to create content types
*How to create templates
*How to create content like pages
*How to set up surface controller ( a controller with access to Umbraco Stuff)
*How to set up a service

You will not learn:
*What is going on in Umbraco
*The project structures for different kind of projects
*Relating different stuff
*Working with Strongly Typed items! Yeap,

Beginners stuff in short
Installing
Creaete a new visual studio empty asp.net solution. Then go to  nuget package manager and add UmbracoCms.

This will add the Umbraco files. Now click F5 to run the project and then continue the wizard to create your stuff inside your DB. for the matter of your test project, you can go on with the DB file and when you want to publish your solution on test/production environment, you can easily set up the SQL server to use the DB like any other ASP.net project.

Umbraco Back office: 
The place that you can go and change stuff, create content type, create content and everything that is possible through a CMS.
You can go to your back office by adding an Umbraco to your sites url:
www.yoursitename.com/umbraco

Creating Content Type:
It is obvious from its name :). It is basically your model/class definition. There are 2 different types of content types,:

1- With  template: meaning that you want to show them to people like your pages.
2- Without template: when you don't want to show anything for that single item. like your settings, etc.

You can create content types by going to settings> content types and create your type. Just click on ... in front of the content types and select what you want.


Then add your fields to your type.  and click save.
For instance, let say that you want create a page to read my data from my text box in back office and write it to my start page. I will create a document type, and will call it something like "Test Doc Type".
Pay attention that Umbraco will change the alias of everything by removing the spaces and lower-casing the start character for the name.
Click on add property and then fill its name, then select the type of the box that you want to show to your user in back office (not the viewer!).  for instance you can select a rich text editor.
This will let the user to put some text with good rich text tools (tiny MCE to be more specific). you can select options and then save the form.

Editing the view 
Open your templates and find the template with the same name. (if you cannot see it, right click on the templates and click on reload).

This is your Razor View. You can do what ever you want in this view. You even don't need Visual studio to create/edit templates.

You have different option to working with views. One of them is working with "dynamic" data type in C#. Write this code inside your view and you will be fine:

@using Umbraco.Web 
@using Umbraco.Web.Mvc
@inherits UmbracoTemplatePage
@{
    Layout = null;
}

    < h1 >@(CurrentPage.YourFieldName != null ? CurrentPage.YourFieldName: "")< / h1 >
Easy right?
There is also one other way which is working with properties:
@using Umbraco.Web 
@using Umbraco.Web.Mvc
@inherits UmbracoViewPage
@{
    Layout = null;
}

   < h1 > @(Model.HasValue("YourFieldName") ? Model.GetPropertyValue("YourFieldName") : "")</ h1 >

Both codes work fine. and since there is no compilation, there is nothing that important to differentiate.
In later posts, I will show you how to work with strongly typed models inside Visual Studio (view/controller/services) but for now, set up your first page this way so you can see a sample page in Umbraco.

For additional data, you can take a look at this post by Dave Woestenborghs:
http://24days.in/umbraco/2015/strongly-typed-vs-dynamic-content-access/

Adding page to your site
Go to your content tab right click on "content" and click create to create a new page. Select your type and click create. Now give your page a title, and fill your field, then click save.
Now go to your base address to see your page.
Congratulations,  you've just created your first Umbraco site.


Wednesday, June 8, 2016

Relational Database Design:Simple rules for creating primary key

Introduction

Some years ago, I had some discussions with one of my friends about using defining the primary key. In the old days, as a software developer you had to implement your database first so most people though about how does the database works and how they can implement their solution in a suitable way.
In these days, developers use ORMs most of the time which is very good, but at the same time, they start to ignore how their code will implement inside the DB. So it is important to consider how your data will be translated by ORM and what will you have inside your DB afterwards.


Some Rules 
Well I think most people these rules, but there is no harm in mentioning them.

Primary keys should never change

Your RDBMS, uses keys to manage tables, sort them, find them and make relation between them and the most important key obviously is the primary key. If you ever try to change the value of the primary key, it will affect other related tables.

You cannot use a natural key or a key form other system

It is possible for natural keys to change, so you are obviously violation the first rule. You might say, oh someones ID will not change. But it is possible for the government the change the system of producing the ids then you have to change a lot of stuff.

They cannot have any formula

It is also a violation of rule 1, since you may need to change the formula in the feature.

The uniqueness has to be easy to maintain

Your RDBMS will prevent you from putting a duplicate inside your primary key, so if you are generating your key with a method that can create duplicates, you will have lots of problems that you cannot fix easily.

Use short but suitable key type

All RDBMS' use B+ threes as they index structure. They need to put your keys inside a table and fetch them so if you use a big key, your RDBMS can put less items inside a page and therefore, it has to access the disc more times  which is the bottle neck of every business application.

In SQL Server, number of index rows in each page can be calculated using this formula:
Index_Rows_Per_Page = 8096 / (Index_Row_Size + 2)

Which and size of each row equals:

Index_Row_Size = Fixed_Key_Size + Variable_Key_Size + Index_Null_Bitmap + 1 (for row header overhead of an index row) + 6 (for the child page ID pointer)

Considering the above, size of index row for int is
int (4 bytes): 4+3+1+6=14
Which means you can put 506 rows inside a page


What are choises

Considering the above, I will start with the worst one!

Never use (n)char or (n)varchar!

If you are using (n)char or (n)varchar for your key, I am almost sure that you are violating of all rules above, since no one will store a string key generated by his system :)
You will also need to worry about upper and lower case and the size of the key is also obviously big!

For a varchar(50) you have: (2+1+50)+3+6+1 = 63
Which means you have only 124 keys inside a page which is awful

Even for a varchar(20) you have: (2+1+20)+3+6+1 = 33
Which means you have only 231 keys inside a page which is still awful

And also, when you are creating your key, you will be vulnerable to concurrent requests. Like when 2 threads ask for a new key inside your application 


Less than 1% of the times use GUID

GUIDs are good data structure that can help you make sure that your key is unique. But at the same time, they are very big and they cannot be stored as a cluster index because there is no order in generating them.
The good fact about them is that they are easy to move because there would be no conflict. Also, some times, you have to create the key inside a code, then it is of course better to use a GUID to reduce the chance of generating the same key, but I would say, try avoiding them as you can.
For a GUID you have: (2+1+16)+3+6+1 = 29

Which means you have only 261 keys inside a page which is still bad


99% percent of the times use int with identity 

Int with the option of identity will help you to keep everything simple. It is very small and will take not much space. Use it with identity so you can make sure that the code will not generate a duplicate because of concurrent process. And it can also contain more than 2 billion different keys which is enough for most business systems.

Don't use small int or tiny int
Tiny int and small int are too small but their size doesn't have that much effect in comparison with integer.

For smallint (2 bytes): 2+3+1+6=12
which means you can put 578 rows inside a page which is 14% improvement but it can contain only 32,000 different values which is not that much

For tiny int(1 bytes): 1+3+1+6=11
which means you can put 622 rows inside a page which seems to be 7% improvement but since it can contain only 256 values :| you cannot use the other 366! :) 

Less than 1% of the times use Bigint
Ok! In very special projects, you might have a table that can contain more than 2 Billion rows! Like you are working for Amazon :) Then use bigint which I don't think happens for most developers in their professional life time :)

References:
Please find the formula for calculating size of rows, etc here in MSDN
And for size of variables for to this page also in MSDN

Monday, June 6, 2016

EpiServer for beginners: How to add custom fields to Order (eCommerce) programatically

Introduction

Some times ago, I had a post about adding a custom field to eCommerce from the user interface. That post got very popular and some folks like Khurram Khan and Steve C. mentioned that it is possible to add fields to eCommerce pragmatically. So in this post I will describe how to do it:

Steps
1- Create an initialization class

Create a class, inherit from IInitializableModule, add InitializableModule and ModuleDependency attribute to your class and you are almost there.

 [InitializableModule]

    [ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]

    public class Initialization : IInitializableModule


* You will need to add "EPiServer.Commerce.Initialization" to have InitializationModule, "EPiServer.Framework" to have InitializableModuleAttribute and "Mediachase.MetaDataPlus.Configurator" to have MetaField methods but of course VS will add them for you when you write the names correctly


2-  Create the constructor and get the context
  public void Initialize(InitializationEngine context)

        {
        var mdContext = CatalogContext.MetaDataContext;

3- Use MetaField.Load to load your field from EPiServer.
        MetaField.Load(mdContext, name)


4- If the result was empty, create the field using MetaField.Create
The structure of the method is like this:

MetaField Create(MetaDataContext context, string metaNamespace, string name, string friendlyName, string description, MetaDataType dataType, int length, bool allowNulls, bool multiLanguageValue, bool allowSearch, bool isEncrypted);


* just to mention, length is the size of your data, so for example bool is 1, or DateTime is 8

5- Load the class that you want to add the field to it using  MetaClass.Load
  var mtClass = MetaClass.Load(mdContext, metaClassName);


6- Check if the meta field already exists in the meta class by checking its fields
  cls.MetaFields.Contains(field);


7- If the meta class doesn't have the class, add it using AddField
mtClass.AddField(field);


8- Smile :)

--------
It is very good idea to have simpler methods for adding fields and joining them to the meta class.

    private MetaField GetOrCreateMetaField(MetaDataContext mdContext, string metaDataNamespace, string name, MetaDataType type, int length, bool allowNulls, bool cultureSpecific)

        {

            var f = MetaField.Load(mdContext, name) ??

                    MetaField.Create(mdContext, metaDataNamespace, name, name, string.Empty, type, length, allowNulls, cultureSpecific, false, false);

            return f;

        }



        private void JoinField(MetaDataContext mdContext, MetaField field, string metaClassName)

        {

            var mtClass = MetaClass.Load(mdContext, metaClassName);



            if (MetaFieldIsNotConnected(field, mtClass ))

            {

                cls.AddField(field);

            }

        }



* And just to say: it is a good practice to have your strings inside enum classes. If you have a project, but you don't have any place for your enums and constants, you have to reconsider some of the stuff in your code :)

The whole code look like this:

 [InitializableModule]

    [ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]

    public class Initialization : IInitializableModule

    {

  public void Initialize(InitializationEngine context)

        {



            MetaDataContext mdContext = CatalogContext.MetaDataContext;



            var myField = GetOrCreateMetaField(mdContext, Constants.Metadata.Namespace.Order,

          Extensions.PurchaseOrderExtensions.myFieldName, MetaDataType.DateTime, 8, true, false);

            JoinField(mdContext, myField, Constants.Metadata.OrderForm.ClassName);

        }



      private MetaField GetOrCreateMetaField(MetaDataContext mdContext, string metaDataNamespace, string name, MetaDataType type, int length, bool allowNulls, bool cultureSpecific)

        {

            var f = MetaField.Load(mdContext, name) ??

                    MetaField.Create(mdContext, metaDataNamespace, name, name, string.Empty, type, length, allowNulls, cultureSpecific, false, false);

            return f;

        }



        private void JoinField(MetaDataContext mdContext, MetaField field, string metaClassName)

        {

            var mtClass = MetaClass.Load(mdContext, metaClassName);



            if (MetaFieldIsNotConnected(field, mtClass ))

            {

                cls.AddField(field);

            }

        }



        private static bool MetaFieldIsNotConnected(MetaField field, MetaClass mtClass )

        {

            return mtClass != null && !cls.MetaFields.Contains(field);

        }

}

A Sample in a project
You can look at Steves  CommerceStarterKit and to be more specific, this page :) 

Acknowledgment
My gratitude to Steve Celius  for sharing his code with us.