Çarşamba, 22 Mart 2017 / Published in Uncategorized

Introduction

This is a note on how to bootstrap multiple apps in a single HTML page.

Background

The Angular’s website has examples on how to bootstrap an Angular application, but the examples only bootstrap a single application in an HTML page. It is not absolutely necessary, but you may find the need to bootstrap multiple applications in your page.

  • Structural reason – In an ASP.NET MVC application, you typically put the components common to all the pages into the layout page. You may want to bootstrap these components separately from the page specific components;
  • Performance reason – By default, Angular’s change detection runs on the whole component tree in the application. If you know that the actions (DOM events, and callbacks) in certain components have no impact on the states of the other components, you may want to bootstrap them separately, so the change detection runs on smaller trees.

The attached example is an ASP.NET MVC application in Visual Studio 2015 Update 3. If you want to run it, I strongly recommend you to take a look at my early posting, because it is not a trivial task to compile and run a Typescript Angular 2 application.

The example bootstraps two angular applications in a single HTML page.

  • The components for each Angular application are in the "app1" and "app2" folders;
  • The "shared-sub-component" and the "math-service" are shared in both Angular applications to demonstrate that different bootstraps can share common code;
  • Both Angular applications will be bootstrapped in the "Index.cshtml" page.

The following sections are a little verbose just for completeness. If you are interested in bootstrapping multiple Angular applications only, you can skip most of them.

The Shared Service and the Shared Component

In order to demonstrate that different bootstraps can share common code, I created a simple service and a simple component.

import { Injectable } from '@angular/core';
    
@Injectable()
export class MathService {
    public AddOne(n) {
        return n + 1;
    }
}

The "math-service.ts" performs a simple math operation. It will be used in all the components to demonstrate that the code of an Angular service can be shared among components bootstrapped separately.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'shared-sub-component',
    template: '
' + '

Shared Component

' + '
' + ' - {{Count}}
' + '</div>' }) export class SharedSubComponent implements DoCheck { public Count = 0; constructor(private math: MathService) { } public ngDoCheck() { console.log('Shared Change detection!') } public Add() { this.Count = this.math.AddOne(this.Count); } }

The "shared-sub-component.ts" implements an Angular component. It will be used as a sub-component by the other components to demonstrate that an Angular component can be shared among components bootstrapped separately.

The Angular App No.1

In this note, I will bootstrap two Angular applications in the same web page. The first application is implemented in the "app1" folder.

The "component-1.ts" implements the application’s only component.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'component-1',
    template: '
' + '

Component-1

' + '
' + ' - {{Count}}
' + '<shared-sub-component></shared-sub-component>' + '</div>' }) export class Component1 implements DoCheck { public Count = 0; constructor(private math: MathService) { } public ngDoCheck() { console.log('component-1 Change detection!') } public Add() { this.Count = this.math.AddOne(this.Count); } }

The "component-1" components uses the "MathService" to make a simple math operation. It also uses the "shared-sub-component" as a sub-component. The "component-1" is packaged in the "app.module.ts" file.

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Component1 } from './components/component-1';
import { SharedSubComponent } from '../common/components/shared-sub-component';
    
import { MathService } from '../services/math-service';
    
@NgModule({
    imports: [BrowserModule],
    providers: [
        MathService
    ],
    declarations: [
        Component1,
        SharedSubComponent
    ],
    bootstrap: [
        Component1
    ]
})
    
export class AppModule { }

The "AppModule" will be bootstrapped through the "app1.ts" file.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
    
try { enableProdMode(); } catch(e) { }
const platform = platformBrowserDynamic();
    
platform.bootstrapModule(AppModule);

The Angular App No.2

The second Angular application is implemented in the "app2" folder. It is virtually the same as the first application. You do not need to spend time to look at it. It is listed here just for completeness.

The "component-2.ts" component.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'component-2',
    providers: [
        MathService
    ],
    template: '
' + '

Component-2

' + '
' + ' - {{Count}}
' + '<shared-sub-component></shared-sub-component>' + '</div>' }) export class Component2 implements DoCheck { public Count = 0; constructor(private math: MathService) { } public ngDoCheck() { console.log('component-2 Change detection!') } public Add() { this.Count = this.math.AddOne(this.Count); } }

The "app.module.ts" module.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Component2 } from './components/component-2';
import { SharedSubComponent } from '../common/components/shared-sub-component';
    
@NgModule({
    imports: [BrowserModule],
    declarations: [
        Component2,
        SharedSubComponent
    ],
    bootstrap: [
        Component2
    ]
})
    
export class AppModule { }

The "app2.ts" application.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
    
try { enableProdMode(); } catch (e) { }
const platform = platformBrowserDynamic();
    
platform.bootstrapModule(AppModule);

The "systemjs.config.js" File

In order to bootstrap multiple Angular applications in a single web page, I made some change to the "systemjs.config.js" file from the Angular official web page.

// http://plnkr.co/edit/aZqdJe3OZ8K2odHioWkB?p=info
    
let ng2_getstarter = function (option) {
    let configuration = {
        paths: { 'npm:': option.npm },
        map: {
            app: option.appPath,
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser':
                'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic':
                'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    
            // other libraries
            'rxjs': 'npm:rxjs'
        },
        packages: {
            rxjs: {
                defaultExtension: 'js'
            },
            app: {
                defaultExtension: 'js'
            }
        }
    }
    
    System.config(configuration);
    
    return {
        bootstrap: function (appFile) {
            System.import(appFile).catch(function (err) { console.error(err);});
        }
    };
};
  • The "ng2_getstarter" function take a JSON "option" object and returns an object to bootstrap the Angular applications;
  • The "option" object needs to provide the path to the "npm" folder and the path to the root folder of the angular applications;

Boostrap the Applications

With the help of the "systemjs.config.js" file, bootstrapping multiple Angular applications in the same page is very simple. The "Index.cshtml" file shows how to use the "ng2_getstarter" function.

<body>
    <component-1></component-1>
    <component-2></component-2>
</body>

In the HTML section, we want to bootstrap both "component-1" and "component-2". The "component-1" is bundled in the "app1.ts" file and the "component-2" is bundled in the "app2.ts" file.

let ng_starter = ng2_getstarter({
    npm: '@Url.Content("~/node_modules/")',
    appPath: '@Url.Content("~/ngApp/")'
});
    
ng_starter.bootstrap('@Url.Content("~/ngApp/app1/app1.js")');
ng_starter.bootstrap('@Url.Content("~/ngApp/app2/app2.js")');
  • We can obtain a "ng_starter" object by passing the path to the "npm" folder and the path to the root of the Angular applications to the "ng2_getstarter" function;
  • To bootstrap the applications, we can simply call the "boostrap()" function on the "ng_starter" object by passing the path to each of the Angular application files.

The "TSC" Error

Depending on the Typescript compiler installed in your Visual Studio, you may encounter a problem to build the application. If you encounter the above error, it is very likely that you have a mis-matched version of Typescript compiler. You can take a look at my early post to figure out the solutions.

Build and Load the Web Page

If everything goes well, you can compile and load the web page into the browser.

You can see both Angular applications bootstrapped well in the same page. You can click on the buttons to check if they function well.

If you open the developer tool and take a look at the console, you can see that the button clicks in each application only trigger change detections within the same application. It should provide some performance advantages if you have no intention to allow the actions in one application to update the state of the other applications.

Points of Interest

  • This is a note on how to bootstrap multiple apps in a single HTML page;
  • It is not always necessary to bootstrap multiple applications in the same page, but it may be of some advantages under certain conditions;
  • I hope you like my postings and I hope this note can help you one way or the other.

History

First Revision – 3/5/2017.

Çarşamba, 22 Mart 2017 / Published in Uncategorized

Introduction

I recently had the need to test Multicast IP network traffic passing through the firewall between the computers that are in different IP subnets. Because administration and configuration of the firewall devices not under my control and these jobs are delegated to others, I needed a simple tool with which I can test this kind of network traffic, between the above computers.

I made a search on the site codeproject.com and found interesting article on this topic: "IP Multicasting in C #" (https://www.codeproject.com/Articles/1705/IP-Multicasting-in-C) author: Gary Brewer from the 10 Jan 2002. In the aforementioned article (thanks’ to Gary) is explained basics Multicast IP traffic theory and is supplied with source code functions written in C# to test multicast IP traffic. I took the aforementioned code and created new project using Visual Studio 2015 and add new functionality to mentioned code, which I needed for testing. The project was designed for .NET 4.6 version and tested on computers with operating systems w2k12R2, windows7, w2k16 and windows 10. In the this code I use external libraries Costura.Fody and CommandLineParser.

Explanation of used External Libraries

Costura.Fody – (Embeds dependencies as resources.) https://github.com/Fody/Costura Costura.Fody allows creating executable code (.exe) file with all the necessary files (.dll) imported into executable file. When you the delivery executable code, you does not have to deliver a referenced external .dll files that were used to compile the program.

CommandLineParser – https://github.com/gsscoder/commandline/tree/stable-1.9.71.2 Library CommandLineParser was used to validate and parse the parameters that are submitted to programs from the command line.

How to use

The program consists of two executable (.exe) programs. One executable program need to be started on computer where we will test acceptance of multicast IP packets that are sent from the network (MulticastReceive.exe) and the other executable program need to be started to generate multicast IP traffic (MulticastSend.exe).

If MulticastReceive.exe starts without any parameters, the program by default listens for incoming multicast traffic on the IP address 238.0.0.1 and port 5050. Possible parameters and values that can be use when starting the program, can be get if you start the program with the command line parameter "-h":

// MulticastReceive.exe -h
// MulticastReceive 1.0.0.0
// Copyright c 2017
// 
// -a, --multicastip (Default: 238.0.0.1) multicast IP address to send data
// 
// -p, --port (Default: 5050) Port to send data
// 
// --help Display this help screen.

If, for example, you want to start listening for incoming multicast traffic on a multicast IP address 224.0.1 and port 5000, it is necessary to start the program as follows: MulticastReceive.exe 224.0.01 -a -p 5000.

Another program required for testing, need to be start on the computer that will generate and send the network multicast traffic (MulticastSend.exe). If you start the program without any command line parameters, by default program will send multicast IP traffic to the IP address 238.0.0.1, port 5050, with default value of 3 for the limitation of the jump (TTL – eng. Time To Live or Hop Limit), 5 data packets with a length of 30 characters per package. Possible parameters and values that can be use when you start the program, you can see if you start program from command line with "-h" parameter:

// MulticastSend.exe -h
// MulticastTest 1.0.0.0
// Copyright c 2017
// 
// -a, --multicastip (Default: 238.0.0.1) multicast IP address to send
// data
// 
// -p, --port (Default: 5050) Port to send data
// 
// -t, --ttl (Default: 3) The Time To Live (TTL - Hop Limit)
// 
// -n, --numberofpacket (Default: 5) Number of packet sent to
// 
// -s, --size (Default: 30) UDP packet size in bytes (1 byte = 1
// character)
// 
// --help Display this help screen.

If, for example, you want to start sending the multicast IP traffic to IP address 224.0.1, port 5000, with TTL 5, 10 packages with packet size of 1KB (1024 characters), it is necessary to start the program as follows: MulticastReceive.exe 224.0.01 -a -p 5000 -t 10 -s 5 -n 1024.

How to start multicast IP test

When testing the functionality of the program due to the presence of firewall devices, you necessary to test three different scenarios:

1. When both programs start on the same machine, to verify that the programs properly functioning, to generate and accept the generated multicast ip traffic

2. when the programs start on different computers that are located in the same IP subnet, i.e. when not in use default gateway for sending IP traffic between computers

3. When the programs start on different computers that are located in different IP subnets, i.e. when using the default gateway for sending IP traffic between computers

Source code project

Complete source code project you can find on GitHub https://github.com/vladano/MulticastTest/

Additional Resources

Wikipedia https://en.wikipedia.org/wiki/Multicast

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Çarşamba, 22 Mart 2017 / Published in Uncategorized

After a long time dealing with that particular problem…I find a very simple solution just check it out…

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">     <title>Untitled Page</title>     <style type="text/css">         #form1         {             width: 800px;             margin: 0px auto 0px auto;         }     </style> </head> <body>          <form id="form1" runat="server"     style="background-color: #000000; height: 361px;">               </form>      </body> </html>

Çarşamba, 22 Mart 2017 / Published in Uncategorized

Visual Studio 2017 has a new feature called Live Unit Testing. It’s currently not available for .NET Core projects, but you should see it as an option in your standard .NET projects. Live Unit Testing is currently only available in the Enterprise SKU (see feature comparison) – click here to grab a free trial if you want to check it out.

For this example, I simply created a new C# .NET test project in VS 2017 Enterprise, and added the start of the String Calculator kata (which you can find in this kata catalog repository on GitHub). Once you have a project set up with some tests, and you want to see the tests run live as you implement new functionality, enable Live Unit Testing with the Test > Live Unit Testing > Start menu, as shown:

With Live Unit Testing running, this menu will change so that you can Pause, Stop, or Restart Live Unit Testing (which you might want to do because running the tests utilizes some of your system’s resources):

Notice in the screen capture above there are green checkmarks on lines 5 and 7 of the StringCalculator class. These represent lines of code that have been covered (called) by tests that have run most recently via Live Unit Testing. At this point there is just one test, and it expects zero to be returned to the trivial implementation of the Add method passes all tests. Thus, the green checkmarks.

Now you would write another test, perhaps verifying that passing in “1” to Add results in an integer 1 being returned:

Notice now that the first passing test still shows as green checks, but the second test is failing with red X icons. The right-hand StringCalculator class is also showing red X icons now, because the failing test ran against this method. There are a couple of subtle things to notice in this screenshot.

First, the StringCalculatorAdd.cs file on the left hasn’t even been saved, but Live Unit Testing is running. That allows it to provide extremely rapid feedback as you work. It’s especially nice for practicing katas like this one, but you’ll find it worthwhile for production code, too. (By the way, if this test naming convention is new to you, learn more here)

Second, so far the green and red icons aren’t providing that much more value than simply showing whether a test passed or failed – and we already had CodeLens to do that. But notice that the Add method’s CodeLens says “0/1 passing”. Live Unit Testing was smart enough to know that when I added a new test on the left, but didn’t change anything on the right, it didn’t need to re-run the first (passing) test. CodeLens is only showing the most recent test run, which in this case was just the last (failing) test. This is important to note because Live Unit Testing needs to be smart about when and which tests it runs. It wouldn’t be very useful if it tried to run every test in the solution on each keypress, for instance. So instead, it has logic that allows it to run only a subset of tests based on what has changed in your code.

Of course, Live Unit Testing becomes more valuable when your system under test (SUT) code becomes more complex, since it can show you exactly which parts of the SUT have failing tests. For instance, adding some conditional logic (poorly) to the SUT might result in the following output:

Here you can see that the Add method has failing tests, but beyond that, you can also see that the sequence of statements on line 9 and 11 both have a test failure. However, all tests that execute line 13 succeed. So you can be pretty certain that the bug you’re looking for is somewhere between lines 9-11, in this case (and in this case, that 2 should be a zero).

I think Live Unit Testing will be a popular VS2017 feature. I’ve already shown it at the Hudson Software Craftsmanship user group that meets at the Tech Hub Hudson coworking office space each month, to much excitement, as well as for clients. Now that Visual Studio 2017 has shipped, I expect to use it even more often. I can’t wait for it to be supported for .NET Core projects, too, since a lot of my work these days targets .NET Core and ASP.NET Core.



Çarşamba, 22 Mart 2017 / Published in Uncategorized

Introduction

While developing an ASP.NET Webforms application, I’ve found that I couldn’t use JQuery alongside UpdatePanel ! I’ve looked deeply into it and found that the partial PostBack of UpdatePanel was removing the JQuery Events. Then I’ve made numerous attempts to make it working the UpdatePanel alongside JQuery ! I’ve googled a lot and reviewed a lot’s of blog post but was unable to find the exact output from there !! 

Lastly I’ve found a solution to it by myself!

To illustrate the procedure, I’ve made a demo project which has two fully functional pages. In Page1.aspx I’ve tried to add two numbers using JQuery and server side events. On the button ‘+’ I’ve added two numbers from JQuery and on the button ‘+(*)’ I’ve added two numbers from server side event. While the page1.aspx is loading, the JQuery event binding was occurred in document.Ready.

The partial postback prevents the jquery to work. In this solution I’ve overcome the problem. I’ve solved it by the endRequest event which is raised after an asynchronous postback is finished and control has been returned to the browser.  

Project Source Code:

Using the code  

In the project you will have two pages one is for jQuery not Working in Update Panel (Page1.aspx) and another is jQuery Working in Update Panel (Page2.aspx). In Page1.aspx jquery doesn’t work.

In the + button will add two numbers using jquery and +(*) button will add two numbers using client side method. Here is the Page1.aspx code : 

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="Page1.aspx.cs" Inherits="jQuerywithinUpdatePanel.Page1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Page-1</title>

    http://js/jquery-1.7.2.min.js

    
        //
        function IsValidNumber() {
            if ($(this).val() == "") {
                //$(this).val("0");
                alert("Please enter valid value!");
                $(this).focus();
            }
            else if ($.isNumeric($(this).val()) == false) {
                alert("Please enter valid value!");
                $(this).focus();
            }
        }

        function Add() {
            var Num1 = parseInt($('#txtNum1').val());
            var Num2 = parseInt($('#txtNum2').val());
            var Result = Num1 + Num2;
            $('#txtResult').val(Result);
        }

        $(document).ready(function() {
            $('#txtNum1').change(IsValidNumber);
            $('#txtNum2').change(IsValidNumber);
            $('#btnClientAdd').click(Add);
        });
    

</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="SM" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="upMain" runat="server" UpdateMode="Conditional">
        <ContentTemplate>
            
+ =
</ContentTemplate> </asp:UpdatePanel> </form> </body> </html>

 and Page1.aspx.cs code:  

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace jQuerywithinUpdatePanel
{
    public partial class Page1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnServerAdd_Click(object sender, EventArgs e)
        {
            int Num1 = Convert.ToInt16(txtNum1.Text);
            int Num2 = Convert.ToInt16(txtNum2.Text);
            int Result = Num1 + Num2;
            txtResult.Text = Result.ToString();
        }
    }
} 

Here, the two numbers are being added from JQuery every time I click on button ‘+’. But after clicking on server side event on button ‘+(*)’ once, the JQuery event doesn’t fire ! That was the problem to me ! The solution I’ve shown in Page2.aspx.

In Page2.aspx, I’ve used one more function to complete the JQuery event binding which works after the partial PostBack is occurred and binds the JQuery events on the document.Ready on pageEndRequest

Here is the Page2.aspx code:

<%@ Page Language="C#" AutoEventWireup="true" 
      CodeBehind="Page2.aspx.cs" Inherits="jQuerywithinUpdatePanel.Page2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Page-2</title>

    http://js/jquery-1.7.2.min.js

    
        //
        function IsValidNumber() {
            if ($(this).val() == "") {
                //$(this).val("0");
                alert("Please enter valid value!");
                $(this).focus();
            }
            else if ($.isNumeric($(this).val()) == false) {
                alert("Please enter valid value!");
                $(this).focus();
            }
        }

        function Add() {
            var Num1 = parseInt($('#txtNum1').val());
            var Num2 = parseInt($('#txtNum2').val());
            var Result = Num1 + Num2;
            $('#txtResult').val(Result);
        }

        function InIEvent() {
            $('#txtNum1').change(IsValidNumber);
            $('#txtNum2').change(IsValidNumber);
            $('#btnClientAdd').click(Add);
        }

        $(document).ready(InIEvent);
    

</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="SM" runat="server">
    </asp:ScriptManager>

    
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(InIEvent);
    

    <asp:UpdatePanel ID="upMain" 
           runat="server" UpdateMode="Conditional">
        <ContentTemplate>
            
+ =
</ContentTemplate> </asp:UpdatePanel> </form> </body> </html>

and Page2.aspx.cs code: 

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace jQuerywithinUpdatePanel
{
    public partial class Page2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnServerAdd_Click(object sender, EventArgs e)
        {
            int Num1 = Convert.ToInt16(txtNum1.Text);
            int Num2 = Convert.ToInt16(txtNum2.Text);
            int Result = Num1 + Num2;
            txtResult.Text = Result.ToString();
        }
    }
}

Here, the pageEndRequest binds the JQuery events after the partial PostBack of UpdatePanel is occurred. Then the JQuery and server side both events are working perfectly !!

The PageRequestManager adds an endRequest for the document.Ready which enables the jQuery binding after partial postback and Jquery keeps still enabled. Please make sure to add those lines in aspx file  to enable jquery event binding which will do the trick for you ! 

    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(InIEvent);

Hope it will save your time! 

Points of Interest   

jQuery is always interesting to work with but I’ve faced some critical problem while using UpdatePanel along with jQuery ASP.NET 3.5. After goggling so many times and going through so many articles I’ve come to this solution !

Reference 

I’ve found some help from here. You can check also this link.

TOP