Web Optimization conditional for browsers

If you have a look into the default format System.Web.Optimization.Scripts.DefaultTagFormat, you will find that you have something like:

<script src='{0}'></script>

So, the only thing you have to do is define a new format. You can do this using the “RenderFormat” method, like:

<%: System.Web.Optimization.Scripts.RenderFormat("<!--[if lt IE 9]><script src='{0}'></script><![endif]-->", "~/bundles/IE9js") %>

 @Scripts.RenderFormat("<!--[if IE 6]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie6js")
 @Scripts.RenderFormat("<!--[if IE 7]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie7js")
 @Scripts.RenderFormat("<!--[if IE 8]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie8js")

Protection against SQL injection

Protection against SQL injection needs to take place on server side, regardless where the incoming call comes from.

Javascript-based sanitation methods are always useless because Javascript runs on client side, and therefore can be forged.

This also applies for AJAX calls: The client doesn’t need to turn JavaScript off; they just need to manipulate the Javascript code they download from your site to fake validation.

CDN in ASP.NET MVC bundling

Once you create ASP.NET MVC project and you looked into the App_start folder BundleConfig.cs file you will fine following code for jQuery bundle.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
        "~/Scripts/jquery-{version}.js"));

Here you can see that there is a ScriptBundle object created with new. This ScriptBundle object also contains another constructor which also take path of cdn as parameter.

Now let’s first run application without adding CDN and see how its works.

bundle-without-cdn-asp-net-mvc

You can see its loaded from bundle not using any CDN there. So Let’s see how we are going to use CDN there. There are lots of CDNs are available there but I’m going to use Microsoft Hosted CDN file in our sample application.

You can find all CDN hosted file on following location.

http://www.asp.net/ajaxlibrary/cdn.ashx

and here all the jQuery CDN listing for all the versions.

http://www.asp.net/ajaxlibrary/cdn.ashx#jQuery_Releases_on_the_CDN_0

I’m going to use jQuery 1.10.2 version as ASP.NET MVC application by default comes with that version only. Following is a code for that.

bundles.UseCdn = true;
   bundles.Add(new ScriptBundle("~/bundles/jquery",
   @"//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.10.2.js"
   ).Include(
    "~/Scripts/jquery-{version}.js"));

Here you can see that I have used path without http so that whether you use https or http it will work on both side. Also you can see that I have enabled UseCdn proper to true that will tell bundle to use CDN whenever its available.

As CDN is used in release version, to test application we need to set Debug=”False” in our web.config check that in local machine. So once you are done with that and run in browser you can see in below image its using CDN instead of local file.

cdn-for-bundling-asp-net-mvc-browser-demo

bundle files in specific order

 

internal class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}

internal static class BundleExtensions
{
    public static Bundle ForceOrdered(this Bundle sb)
    {
        sb.Orderer = new AsIsBundleOrderer();
        return sb;
    }
}

Usage:

    bundles.Add(new ScriptBundle("~/content/js/site")
        .Include("~/content/scripts/jquery-{version}.js")
        .Include("~/content/scripts/bootstrap-{version}.js")
        .Include("~/content/scripts/jquery.validate-{version}")
        .ForceOrdered());

I like using fluent syntax but it also works with a single method call and all the scripts passed as parameters.

Allow only alpha numeric and space keys

Table. Here are the first 128 characters. Some of the characters are escaped on the ASCII column. Many of the characters are control characters, which are not widely used. They are not easy to display.

ASCII table

Decimal   ASCII     Hex
0         control   00
1         control   01
2         control   02
3         control   03
4         control   04
5         control   05
6         control   06
7         control   07
8         control   08
9         \t        09
10        \n        0A
11        \v        0B
12        \f        0C
13        \r        0D
14        control   0E
15        control   0F
16        control   10
17        control   11
18        control   12
19        control   13
20        control   14
21        control   15
22        control   16
23        control   17
24        control   18
25        control   19
26        control   1A
27        control   1B
28        control   1C
29        control   1D
30        control   1E
31        control   1F
32        space     20
33        !         21
34        "         22
35        #         23
36        $         24
37        %         25
38        &         26
39        '         27
40        (         28
41        )         29
42        *         2A
43        +         2B
44        ,         2C
45        -         2D
46        .         2E
47        /         2F
48        0         30
49        1         31
50        2         32
51        3         33
52        4         34
53        5         35
54        6         36
55        7         37
56        8         38
57        9         39
58        :         3A
59        ;         3B
60        <         3C
61        =         3D
62        >         3E
63        ?         3F
64        @         40
65        A         41
66        B         42
67        C         43
68        D         44
69        E         45
70        F         46
71        G         47
72        H         48
73        I         49
74        J         4A
75        K         4B
76        L         4C
77        M         4D
78        N         4E
79        O         4F
80        P         50
81        Q         51
82        R         52
83        S         53
84        T         54
85        U         55
86        V         56
87        W         57
88        X         58
89        Y         59
90        Z         5A
91        [         5B
92        \         5C
93        ]         5D
94        ^         5E
95        _         5F
96        `         60
97        a         61
98        b         62
99        c         63
100       d         64
101       e         65
102       f         66
103       g         67
104       h         68
105       i         69
106       j         6A
107       k         6B
108       l         6C
109       m         6D
110       n         6E
111       o         6F
112       p         70
113       q         71
114       r         72
115       s         73
116       t         74
117       u         75
118       v         76
119       w         77
120       x         78
121       y         79
122       z         7A
123       {         7B
124       |         7C
125       }         7D
126       ~         7E
127       control   7F

private string RemoveNonAlphanumeric(string text)
 {
 StringBuilder sb = new StringBuilder(text.Length);

 for (int i = 0; i < text.Length; i++)
 {
 char c = text[i];
 if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == 32)
 sb.Append(text[i]);
 }

 return sb.ToString();
 }

Performance Test between SortedList vs. SortedDictionary vs. Dictionary vs. Hashtable

Please note that the advantage of Hashtable over generic Dictionary for insert and search operations demonstrated here is actually because the tests are based on NON generic IDictionary interface, so each insert or search action is accompanied with check for the key type. For more information see the Sean’s comment below. (Thanks Sean!) Without that Dictionary seem to perform better than the Hashtable. The rest of the test conclusions will not be affected. So to summarize, generic Dictionary is the absolute winner for insert and search operations if used with generic dictionary interface or directly.

This is a sequence of tests comparing the performance results for four different implementations of IDictionary and in particular generic Dictionary, generic SortedDictionary, the old non-generic Hashtable and generic SortedList.

I performed several tests, comparing the following parameters: memory used in bytes, time for the insertion in ticks, time for the item search in ticks, and the time for looping with foreach in ticks. The test was performed 8000 times for all the four implementation, and the order was random so each implementation has been tested at least 1000 times.

I performed the tests in five stages, to observe the relationship between the number of entries and the performance. In the first stage the collections had 50 items, in the second 500, in the third 5,000 in the fourth 50,000 items.

In this particular test, lower numbers of memory usage or time taken for the execution means better performance. So if we want to present visually a performance chart for each of the parameters we have to deduce a performance coefficient from the raw data. I have used the following code to calculate the performance coefficient:

Performance Coefficient for value x = min(value 1, value 2, … value n) / value x

This way, because the best performing value is the lowest one it will be transformed as value 1 of the performance coefficient and any other value will be a fraction of that value.

This is the chart of the memory usage:

Memory Allocation

The results stay consistent with the increase of the number of items in collections. Best memory footprint we see in the SortedList, followed by Hashtable, SortedDictionary and the Dictionary has highest memory usage. Despite all that, we have to note, that the differences are not significant and unless your solution requires extreme sensitivity about the memory usage you should consider the other two parameters: time taken for the insert operations and time taken for searching a key as more important. It is important to note that this test does not take into consideration the effects of garbage collection and thus can only be taken in a very general way.

This is the chart for the time taken for insert operations:

Insertion

When the number of records is small the differences between all four implementations are not significant but with the increase of items in the collection the performance of the SortedList drops dramatically, SortedDictionaryis better but still taking significantly more time for inserts than the other two implementations. Hashtable is the next in the list and the ultimate leader is the generic Dictionary.

This is the chart for the time taken for search operations:

Searching

The absolute leader is Hashtable, but the test does not consider the type of item being stored. That could be a possibility for a future test. The next best performer is the generic Dictionary followed by the other two implementations. The differences here between SortedList and SortedDictionary are not significant.

This is the chart for the time taken for for-each collection loop operations:

For Each

Here the leader is SortedList then Dictionary consistantly better than Hashtable and the words performer isSortedDictionary

Here you can see the task manager during the test it shows us a picture of the memory usage. Area A is during the insertion phase when more and more memory has been allocating. Area B is from the end of the insertion until the garbage collection of the object.

Memory - Task Manager

This is the code I used for this test. The variable NumberInsertedKeys was changed to 50, 500, 5000, 50000, or 10000 for the different stages.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
/*
to compile enter in the command prompt:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc IDictTest.cs
to run enter in the command prompt:
IDictTest
*/
namespace IDictTest{

    public class RunResult{
        public decimal MemoryUsed;
        public decimal InsertTicks;
        public decimal SearchTicks;
        public decimal ForEachTicks;
    }

    public class Program
    {

        private static int SearchIndex = 27;
        //private const int NumberInsertedKeys = 50;
        //private const int NumberInsertedKeys = 500;
        //private const int NumberInsertedKeys = 5000;
        private const int NumberInsertedKeys = 50000;
        //private const int NumberInsertedKeys = 100000;
        private const int NumberTests = 8000;

        private static readonly string[] Letters = 
                {"A","B","C","D","E","F","G","H","I","J"};

        public static void Main(string[] args)  {
            try{
            // TRY STARTS HERE ----------

                List<RunResult> listDictionary = new List<RunResult>();
                List<RunResult> listSortedDictionary = new List<RunResult>();
                List<RunResult> listHashtable = new List<RunResult>();
                List<RunResult> listSorderList = new List<RunResult>();
                Stopwatch watch = Stopwatch.StartNew();

                for(int i = 0; i < NumberTests; i++){
                    SearchIndex += 1;
                    Random rand = new Random();
                    int randInt = rand.Next(0, 4);
                    if(randInt == 0){
                      listDictionary.Add(
                          Test("Dictionary", new Dictionary<string, string>(), i));
                    }else if(randInt == 1){
                      listSortedDictionary.Add(
                          Test("SortedDictionary", 
                              new SortedDictionary<string, string>(), i));
                    }else if(randInt == 2){
                      listHashtable.Add(
                          Test("Hashtable", new Hashtable(), i));
                    }else if(randInt == 3){
                      listSorderList.Add(
                          Test("SortedList", new SortedList(), i));
                    }
                }

                Console.Clear();
                Msg("Time taken (minutes): {0} or about {1} minutes and {2} seconds", 
                    watch.Elapsed.TotalMinutes,
                    watch.Elapsed.Minutes,
                    watch.Elapsed.Seconds);
                
                RunResult resultDict = CalculateAvg(listDictionary);
                RunResult resultSortDict = CalculateAvg(listSortedDictionary);
                RunResult resultHash = CalculateAvg(listHashtable);
                RunResult resultSortList = CalculateAvg(listSorderList);
                
                RunResult min = 
                    new RunResult{
                        MemoryUsed = Math.Min(Math.Min(Math.Min(resultDict.MemoryUsed, resultSortDict.MemoryUsed),resultHash.MemoryUsed),resultSortList.MemoryUsed), 
                        InsertTicks = Math.Min(Math.Min(Math.Min(resultDict.InsertTicks, resultSortDict.InsertTicks), resultHash.InsertTicks), resultSortList.InsertTicks), 
                        SearchTicks = Math.Min(Math.Min(Math.Min(resultDict.SearchTicks, resultSortDict.SearchTicks), resultHash.SearchTicks), resultSortList.SearchTicks),
                        ForEachTicks = Math.Min(Math.Min(Math.Min(resultDict.ForEachTicks, resultSortDict.ForEachTicks), resultHash.ForEachTicks), resultSortList.ForEachTicks)
                    }; 
                
                // print the results
                PrintResults(resultDict, listDictionary.Count, min, "Dictionary");
                PrintResults(resultSortDict, listDictionary.Count, min, "SortedDictionary");
                PrintResults(resultHash, listDictionary.Count, min, "Hashtable");
                PrintResults(resultSortList, listDictionary.Count, min, "SortedList");

            // TRY ENDS HERE ----------

            }catch(Exception ex){
                Msg("{0}", ex);
            }
        }
        
        private static RunResult CalculateAvg(List<RunResult> list){
            decimal sumMemory = 0;
            decimal sumInsert = 0;
            decimal sumSearch = 0;
            decimal sumForEach = 0;
            for(int i = 0; i < list.Count; i++){
                RunResult curr = list[i];
                sumMemory += curr.MemoryUsed;
                sumInsert += curr.InsertTicks;
                sumSearch += curr.SearchTicks;
                sumForEach += curr.ForEachTicks;
                // uncomment to print each line
                //Msg("{0,11} {1,13} {2,14}", 
                    //curr.MemoryUsed, curr.InsertTicks, curr.SearchTicks);
            }
            return new RunResult{
                      MemoryUsed = sumMemory / list.Count, 
                      InsertTicks = sumInsert / list.Count, 
                      SearchTicks = sumSearch / list.Count,
                      ForEachTicks = sumForEach / list.Count,
                    };
        }

        private static void PrintResults(RunResult result, int count, RunResult min, string name){
            Msg("--------- Results for {0}", name);
            Msg("# Tests {0}", count);
            Msg("Memory Used    Insert Ticks    Search Ticks    ForEach Ticks");
            Msg("Average Values:");
            Msg("{0,11:N} {1,13:N} {2,14:N} {3,14:N}", 
                result.MemoryUsed, 
                result.InsertTicks, 
                result.SearchTicks, 
                result.ForEachTicks);
            Msg("Performance Coefficient:");
            Msg("{0,11:N} {1,13:N} {2,14:N} {3,14:N}", 
                min.MemoryUsed/result.MemoryUsed, 
                min.InsertTicks/result.InsertTicks, 
                min.SearchTicks/result.SearchTicks, 
                min.ForEachTicks/result.ForEachTicks);
            Msg("");
        }

        private static void Msg(string name, params object[] args){
            Console.WriteLine(name, args);
        }

        private static RunResult Test(string name, IDictionary dict, int n){
            Console.Clear();
            Msg("Currently executing test {1} of {2} for {0} object", 
                name, n + 1, NumberTests);
            RunResult rr = new RunResult();
            Stopwatch watch;
            Random rand = new Random( );
            long memoryStart = System.GC.GetTotalMemory(true);
            long insertTicksSum = 0;
            for(int i = 0; i < NumberInsertedKeys; i++){
                string key = GetRandomLetter(rand, i)+"_key"+i;
                string value = "value"+i;
                
                watch = Stopwatch.StartNew();
                dict.Add(key, value);
                watch.Stop();
                
                insertTicksSum += watch.ElapsedTicks;                
            }
            rr.MemoryUsed = System.GC.GetTotalMemory(true) - memoryStart;
            

            rr.InsertTicks = insertTicksSum;

            watch = Stopwatch.StartNew();
            object searchResult = dict["C_key"+SearchIndex];
            watch.Stop();
            
            rr.SearchTicks = watch.ElapsedTicks;
            
            watch = Stopwatch.StartNew();
            foreach(var curr in dict){}
            watch.Stop();

            rr.ForEachTicks = watch.ElapsedTicks;

            return rr;
        }

        private static string GetRandomLetter(Random rand, int i){
            if(i == SearchIndex){
                return "C";
            }
            return Letters[rand.Next(0, 10)];
        }

    }

}

The computer used for the test has the following characteristics:

Processor: Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz 2.GHz
Memory (RAM): 2.00 GB
System type: 32-bit Operating System
Windows Vista

These is the raw data. Memory Used is in bytes and the insert, search and looping time in ticks:

Time taken (minutes): 0.324318411666667 or about 0 minutes and 19 seconds
--------- Results for Dictionary
# Tests 2063
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
   4,748.48      3,019.60         126.40         198.21
Performance Coefficient:
       0.73          0.92           0.83           0.80

--------- Results for SortedDictionary
# Tests 2063
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
   4,345.04      5,000.54         193.05         377.99
Performance Coefficient:
       0.80          0.55           0.55           0.42

--------- Results for Hashtable
# Tests 2063
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
   4,096.38      2,775.27         105.36         209.91
Performance Coefficient:
       0.85          1.00           1.00           0.75

--------- Results for SortedList
# Tests 2063
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
   3,488.50      4,350.48         167.89         158.41
Performance Coefficient:
       1.00          0.64           0.63           1.00

8000 tests 500 collection entries
Time taken (minutes): 1.26410570333333 or about 1 minutes and 15 seconds
--------- Results for Dictionary
# Tests 2158
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
  53,353.52     28,345.86         123.94       1,051.16
Performance Coefficient:
       0.73          0.96           0.92           0.71

--------- Results for SortedDictionary
# Tests 2158
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
  48,949.40     67,007.68         232.22       2,562.93
Performance Coefficient:
       0.80          0.41           0.49           0.29

--------- Results for Hashtable
# Tests 2158
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
  48,053.46     27,341.10         114.07       1,303.74
Performance Coefficient:
       0.81          1.00           1.00           0.57

--------- Results for SortedList
# Tests 2158
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
  39,077.27     54,255.06         209.31         744.81
Performance Coefficient:
       1.00          0.50           0.54           1.00

8000 tests 5000 collection entries
Time taken (minutes): 11.14550681 or about 11 minutes and 8 seconds
--------- Results for Dictionary
# Tests 1578
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
 527,352.00    274,339.83         171.81       9,724.85
Performance Coefficient:
       0.80          0.98           0.85           0.72

--------- Results for SortedDictionary
# Tests 1578
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
 498,944.56    853,251.69         288.00      22,777.03
Performance Coefficient:
       0.85          0.32           0.50           0.31

--------- Results for Hashtable
# Tests 1578
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
 480,048.17    268,945.01         145.19      11,911.69
Performance Coefficient:
       0.88          1.00           1.00           0.59

--------- Results for SortedList
# Tests 1578
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
 424,512.12    913,408.34         247.98       7,011.65
Performance Coefficient:
       1.00          0.29           0.59           1.00

8000 tests 50000 collection entries
Time taken (minutes): 299.723793791667 or about 4 hours, 59 minutes and 43 seconds
--------- Results for Dictionary
# Tests 1574
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
5,427,604.19  2,818,130.50         302.05     100,556.45
Performance Coefficient:
       0.82          1.00           0.87           0.73

--------- Results for SortedDictionary
# Tests 1574
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
5,318,944.00 10,506,892.94         525.14     294,219.13
Performance Coefficient:
       0.84          0.27           0.50           0.25

--------- Results for Hashtable
# Tests 1574
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
5,005,100.00  2,867,786.62         263.39     111,733.71
Performance Coefficient:
       0.89          0.98           1.00           0.66

--------- Results for SortedList
# Tests 1574
Memory Used    Insert Ticks    Search Ticks    ForEach Ticks
Average Values:
4,443,275.91 82,146,134.48         493.06      73,798.76
Performance Coefficient:
       1.00          0.03           0.53           1.00

 

Differences between Hashtable and Dictionary

Dictionary:

  • Dictionary returns error if we try to find a key which does not exist.
  • Dictionary faster than a Hashtable because there is no boxing and unboxing.
  • Dictionary is a generic type which means we can use it with any data type.

Hashtable:

  • Hashtable returns null if we try to find a key which does not exist.
  • Hashtable slower than dictionary because it requires boxing and unboxing.
  • Hashtable is not a generic type,

If you care about reading that will always return the objects in the order they are inserted in a Dictionary, you may have a look at

OrderedDictionary – values can be accessed via an integer index (by order in which items were added) SortedDictionary – items are automatically sorted

MSDN Article: “The Dictionary class has the same functionality as the Hashtable class. A Dictionary of a specific type (other than Object) has better performance than a Hashtable for value types because the elements of Hashtable are of type Object and, therefore, boxing and unboxing typically occur if storing or retrieving a value type”. Link: http://msdn.microsoft.com/en-us/library/4yh14awz(v=vs.90).aspx

Dictionary is faster than hashtable as dictionary is a generic strong type. Hashtable is slower as it takes object as data type which leads to boxing and unboxing.

 

Bundling and Minification

The CSS and Script bundling should work regardless if .NET is running 4.0 or 4.5. I am running .NET 4.0 and it works fine for me. However in order to get the minification and bundling behavior to work your web.config must be set to not be running in debug mode.

<compilation debug="false" targetFramework="4.0">

Take this bundle for jQuery UI example in the _Layout.cshtml file.

@Styles.Render("~/Content/themes/base/css")

If I run with debug="true" I get the following HTML.

<link href="/Content/themes/base/jquery.ui.core.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.resizable.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.selectable.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.accordion.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.autocomplete.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.button.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.dialog.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.slider.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.tabs.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.datepicker.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.progressbar.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.theme.css" rel="stylesheet"/>

But if I run with debug="false". I’ll get this instead.

<link href="/Content/themes/base/css?v=myqT7npwmF2ABsuSaHqt8SCvK8UFWpRv7T4M8r3kiK01" rel="stylesheet"/>

I've found that what you need to have is the Nuget package Microsoft.AspNet.Web.Optimization installed in your project. It's included by default in an MVC4 RTM app regardless if you specify the target framework as 4.5 or 4.0. This is the namespace that the bundling classes are included in, and doesn't appear to be dependent on the framework. I've deployed to a server that does not have 4.5 installed and it still works as expected for me. Just make sure the DLL gets deployed with the rest of your app.

public static void RegisterBundles(BundleCollection bundles)
{
  bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
             "~/Scripts/jquery-{version}.js"));

   // Code removed for clarity.
   BundleTable.EnableOptimizations = true;
}

3. make sure to add debug false in web.config (when you start local debuging VS2013 will give you a popup saying that you need to make sure to putting it back before deploying into prod. that itself explains much.

<system.web>
  <compilation debug="true" />
  <!-- Lines removed for clarity. -->
</system.web>

Controlling Bundling and Minification

Bundling and minification is enabled or disabled by setting the value of the debug attribute in the compilation Element  in the Web.config file. In the following XML, debug is set to true so bundling and minification is disabled.

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

To enable bundling and minification, set the debug value to “false”. You can override the Web.config setting with theEnableOptimizations property on the BundleTable class. The following code enables bundling and minification and overrides any setting in the Web.config file.

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
    BundleTable.EnableOptimizations = true;
}
Note: Unless EnableOptimizations is true or the debug attribute in the compilation Element  in the Web.config file is set to false, files will not be bundled or minified. Additionally, the .min version of files will not be used,  the full debug versions will be selected.EnableOptimizations  overrides the debug attribute in the compilation Element  in theWeb.config file

I had successfully been able to bund my JS script and CSS style sheet on one file each using the bundling functionally offered by “system.web.optimization”

public static void RegisterBundler(BundleCollection bundles)
        {
            bundles.Add(new StyleBundle("~/CDN/Content/_LayoutNotAuth").Include("~/CDN/Content/style.css", "~/CDN/Content/select2.css", "~/CDN/Content/StyleUpdates.css", "~/CDN/Content/jquery-ui-1.8.21.custom.css", "~/CDN/Content/jquery.qtip.min.css", "~/CDN/Content/htmlfeedback.css", "~/CDN/Content/facebookInputToken.css", "~/CDN/content/notifications/jquery.gritter.css"));
            bundles.Add(new ScriptBundle("~/CDN/Scripts/_LayoutNotAuth").Include("~/CDN/Scripts/jquery-1.7.1.min.js", "~/CDN/Scripts/modernizr-1.7.min.js", "~/CDN/Scripts/notifications.js", "~/CDN/Scripts/jquery.unobtrusive-ajax.min.js", "~/CDN/Scripts/menu.js", "~/CDN/Scripts/jquery-ui-1.8.23.custom.min.js", "~/CDN/Scripts/Notifications/jquery.gritter.js", "~/CDN/Scripts/jquery.qtip.min.js", "~/CDN/Scripts/json2.min.js", "~/CDN/Scripts/jquery.signalR.min.js", "~/CDN/Scripts/jquery.validate.js", "~/CDN/Scripts/jquery.validate.unobtrusive.min.js", "~/CDN/Scripts/inputs.js", "~/CDN/Scripts/select2.js", "~/CDN/Scripts/jquery.simplemodal.1.4.2.min.js", "~/CDN/Scripts/htmlfeedback/html2canvas.js", "~/CDN/Scripts/htmlfeedback/jquery.htmlfeedback.js", "~/CDN/Scripts/jquery.blockUI.js", "~/CDN/Scripts/jquery.tokeninput.js", "~/CDN/Scripts/RechercheProjet/ProjectSearch.js", "~/CDN/Scripts/jquery.address-1.5.min.js", "~/CDN/Scripts/RechercheProjet/ContractorSearch.js", "~/CDN/Scripts/Contact/ProfileContact.js", "~/CDN/Scripts/RechercheProjet/resultats_recherche.js"));

        }
 

To disable bundling and minification use this (this will disable optimization even if debug=true in web.config)

System.Web.Optimization.BundleTable.EnableOptimizations = false;

If you put EnableOptimizations = true this will bundle and minify even if debug=true in web.config

By default all files included in the Bundle would indeed be minified as well, but only in Release mode.

If you want to enable it in Debug mode as well, try adding this to your RegisterBundle method:

BundleTable.EnableOptimizations = true;

ANGULARJS AND/VS JQUERY

Basically, jQuery is a great tool for you to manipulate and control DOM elements. If you only focus on DOM elements and no Data CRUD, like building a website not web application, jQuery is the one of the top tools. (You can use AngularJS for this purpose as well.)

AngularJS is a framework. It has following features

  1. Two way data binding
  2. MVW pattern (MVC-ish)
  3. Template
  4. Custom-directive (reusable components, custom markup)
  5. REST-friendly
  6. Deep Linking (set up a link for any dynamic page)
  7. Form Validation
  8. Server Communication
  9. Localization
  10. Dependency injection
  11. Full testing environment (both unit, e2e)

    AngularJS : AngularJS is for developing heavy web applications. AngularJS can use jQuery if it’s present in the web-app when the application is being bootstrapped. If it’s not present in the script path, then AngularJS falls back to its own implementation of the subset of jQuery.

    JQuery : jQuery is a small, fast, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler. jQuery simplifies a lot of the complicated things from JavaScript, like AJAX calls and DOM manipulation.

@@TRANCOUNT

PRINT @@TRANCOUNT
— The BEGIN TRAN statement will increment the
— transaction count by 1.
BEGIN TRAN
PRINT @@TRANCOUNT
BEGIN TRAN
PRINT @@TRANCOUNT
— The COMMIT statement will decrement the transaction count by 1.
COMMIT
PRINT @@TRANCOUNT
COMMIT
PRINT @@TRANCOUNT
–Results
–0
–1
–2
–1
–0