Full Trust European Hosting

BLOG about Full Trust Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European Blazor Hosting - HostForLIFE :: Blazor - JavaScript Isolation (ES6 Modules & Blazor)

clock November 16, 2021 07:16 by author Peter

When using JavaScript in Blazor, we typically add the reference to our JavaScript files in _Host.cshtml. This allows us to access our JavaScript from anywhere in our Blazor application.

Since Blazor apps are SPAs (Single-Page Applications), it makes sense why it works this way. But, we often don’t want to pollute the global JavaScript namespace with every function and variable. Often, an individual component will need its own JavaScript to work correctly. How can we isolate JavaScript code to a single component?
Objects As Namespaces

One solution you might find online is to wrap all JavaScript code in objects, effectively making namespaces for each component:
window.MyNamespace = {
    MyFunction: function() {
        ...
    },
};


This works, but it is cumbersome to work with and all of these objects are still globally visible. We still don’t have true isolation.

Luckily, JSInterop in Blazor supports ES6 Modules.

Using ES6 Modules in Blazor
Modules in JavaScript allow us to completely isolate scripts from the global namespace. With a module, only the components that import it can access it, and only code that is explicitly exported within the module can be accessed. This allows us to tightly control access to our code and removes namespace pollution in large projects.

Let’s say we have a component that displays the start time of an event. This start time is stored in our system and displayed as UTC, but when the user clicks a button, we want the displayed time converted to their local timezone. We can do this with the help of JavaScript, since the browser has access to the user's timezone.

First let's create a Blazor Component called TimeDisplay.
[TimeDisplay.razor]

<p>Event starts at: @displayTime.ToString("g")</p>
<button class="btn btn-primary" @onclick="OnClick">Click me</button>
@code {
    private DateTime displayTime = DateTime.UtcNow;
    private void OnClick() {}
}


For this example, we need to utilize JavaScript to get the user’s local timezone. The rest of the web app doesn’t care about this timezone logic, so we want to isolate it to our TimeDisplay component.

Within the project’s wwwroot folder, we can create a folder called scripts then create a subfolder called components

Then, we add our .js file in this folder,

 

Let’s write some JavaScript. We want a JavaScript function we can call from C# that lets us pass in a DateTime string in UTC, and it’ll return to us converted into the user’s timezone.

function ConvertStartTimeToLocal(utcDateTime) {
    const utcString = new Date(`${utcDateTime} UTC`);
    return utcString.toLocaleString();
}

Now, typically we would add the reference to this script in _Host.cshtml (In Blazor Server) so that we can access it via the JSInterop features.

But since this JavaScript only corresponds to an individual component, it would be ideal if the component itself could load this JavaScript file.
Loading the script in our Component

To begin, we will still need to [Inject] an IJSRuntime instance like normal so that we can do JS Interop.

The difference is that instead of calling JavaScript functions with the IJSRuntime instance directly, we will use it to import our module and store it as an IJSObjectReference instance.
// TimeDisplay.razor
@code {
[Inject] IJSRuntime JSRuntime { get; set; }
IJSObjectReference module;


JavaScript won’t be usable in a component until after the component is rendered to the client, so we must initialize it within the OnAfterRenderAsync method.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./scripts/components/TimeDisplay.js");
}


With this code, instead of calling the JavaScript function directly using the IJSRuntime, we are instead using the import feature of ES6 to import our module. This module is stored as an IJSObjectReference instance, which we can use to communicate with our module directly.

Now let’s implement the button’s OnClick method.
private async Task OnClick()
{
    var converted = await module.InvokeAsync<string>("ConvertStartTimeToLocal",
    displayTime.ToString("g"));
    displayTime = DateTime.Parse(converted);
}


Note carefully, we are using module.InvokeVoidAsync instead of JSRuntime.InvokeVoidAsync. This is the key difference here. We are not calling code from the global JS runtime, we are only accessing code from within our module. Everything else you know about how to use JS Interop stays exactly the same.

Finally, let's go to Index.razor and add our component
<TimeDisplay />

There's a slight catch
If we are using a module, we need to make sure we explicitly dispose of it for garbage collection. If we don't, the JSRuntime will continue holding a reference to our module for the lifetime of the application.

To do this, our component must implement IAsyncDisposable, then we can dispose of our module in the DisposeAsync method.
Here's the completed TimeDisplay component:
@implements IAsyncDisposable
<p>Event starts at: @displayTime.ToString("g")</p>
<button class="btn btn-primary" @onclick="OnClick">Click me</button>
@code {
    [Inject] IJSRuntime JSRuntime {
        get;
        set;
    }
    IJSObjectReference module;
    private DateTime displayTime = DateTime.UtcNow;
    protected override async Task OnAfterRenderAsync(bool firstRender) {
        module = await JSRuntime.InvokeAsync < IJSObjectReference > ("import", "./scripts/components/TimeDisplay.js");
    }
    private async Task OnClick() {
        var converted = await module.InvokeAsync < string > ("ConvertStartTimeToLocal", displayTime.ToString("g"));
        displayTime = DateTime.Parse(converted);
    }
    async ValueTask IAsyncDisposable.DisposeAsync() {
        if (module is not null) {
            await module.DisposeAsync();
        }
    }
}


Let’s run the app. Once the page loads, click on the button and see the result

Woops! We are seeing this error because with ES6 modules, only code that is marked with export can be seen from outside the module. There are a couple of ways to do this, and I’ll show both, but I prefer one over the other and I’ll explain why later.

The change we need to make is very simple, and we don’t need to stop or restart the app.

Note
In Blazor, you don’t need to restart the app after changing JavaScript code. You can just refresh the page after saving the file to see the changes in action.

We will just add the export keyword in front of the function declaration:
export function ConvertStartTimeToLocal(utcDateTime) {
    const utcTimeString = new Date(`${utcDateTime} UTC`);
    return utcTimeString.toLocaleString();
}

Save the file, then refresh the page and try again. You should see the time converted to your local time when the button is clicked.

On the topic of export
Now, as was mentioned previously there is another way to export code out of a JS module, and it’s done like so:
function ConvertStartTimeToLocal(utcDateTime) {
    const utcTimeString = new Date(`${utcDateTime} UTC`);
    return utcTimeString.toLocaleString();
}
export { ConvertStartTimeToLocal };


Both ways of exporting are acceptable. But, I personally prefer putting export before the function/variable declaration. Here’s why: When marking a function or variable explicitly as export function or export const, you can immediately tell just by reading the function declaration that the code is intended to be called from a Blazor component.

Functions and variables declared with export are clearly being used from C# with JSInterop

Functions and variables declared without export are local to the module and won’t be used by C# code

A list of exports at the bottom of the code file makes this far less obvious, in my opinion.

This module feature is, in my opinion, a hidden gem in Blazor. It allows you to write JavaScript files as if everything were global—not worrying about namespacing. The file itself is the namespace!

Stay safe everyone and happy coding!



European Visual Studio 2022 Hosting - HostForLIFE.eu :: What Is New In Visual Studio 2022

clock November 10, 2021 07:00 by author Peter

Microsoft’s Visual Studio is one of the most popular developer IDEs in the world. Not only is Visual Studio modern, feature-rich, and advanced, but it also gets more frequent updates than any other IDE out there. The next version of Visual Studio is going to be Visual Studio 2022. The Visual Studio team just released the first public preview of Visual Studio 2022.

I am sure one of the first questions you probably have is, "What is new in Visual Studio 2022?" In this article, we will learn about the key new features in Visual Studio 2022.
Visual Studio 2022 is modern, faster, intelligent and lightweight

Visual Studio 2022 is much faster and more lightweight compared to the current version. The Visual Studio team has focused on making IDE more user-friendly by enhancing the overall user experience. It looks cleaner.

Visual Studio 2022 also has intelligent features that include recommendations around code cleanness, quality, standards, and best practices.

Let’s look at some of the key updates in Visual Studio by installing the Visual Studio 2022 Community Edition.
Installing Visual Studio 2022

The current version of Visual Studio 2022 is Preview 1 that you can download it from Visual Studio 2022 preview page here.

I selected ASP.NET, Azure, Windows, and UWP workloads and the space required for the installation is close to 20GB.

The good news is, VS 2022 keeps your current login from VS 2019.

Create a new project and the initial screens look similar.

The next screen is a little cleaner.

The current version supports .NET 6.0 (Preview only). I am sure the next upgrades will have more options here.


Key changes and updates in Visual Studio 2022
The first thing I noticed right after the installation was a little cleaner UI and minor color changes of icons. It makes them stand out a little and it's easier to find them in the UI.

 

Here is a list of some of the key changes in Visual Studio 2022.

Visual Studio 2022 (devenv.exe) is now 64-bit only.

IntelliCode now can complete the whole line auto-complete.

As we saw earlier, Visual Studio 2022 supports .NET 6 SDK (preview for now). .NET 6 also supports .NET MAUI project but you will have to download .NET MAUI workload template direct from Github.

The XAML Designer for .NET Framework has been upgraded in this release.
Git Tooling

Removed the ability to revert back to the Team Explorer Git UI, making the new Git experience the only available built-in tooling.

Removed the option to install the GitHub extension from the Visual Studio Installer.

New versions of the test platform will not be able to run Generic tests and Ordered tests.
Web Tools

The Publish summary page now has actions to start/stop remote debugging and profiling under the '...' menu on the top right corner of the 'Hosting' section

The Connected Services page now has an action to launch Storage Explorer

The "ASP.NET Core Empty" template that comes with .NET 6 is using the new 'minimal APIs' paradigm for which we have started to add support.

Some of the feature that has not implemented yet but is coming in the next releases.

  • Web Live Preview
  • Instrumentation profiler
  • Azure Cloud Service project support
  • T-SQL debugger
  • Web Load Test and TestController/TestAgent
  • Azure DataLake
  • Coded UI Test
  • DotFuscator
  • Incredibuild IDE integration
  • IntelliCode find and replace by example


AngularJS Hosting Europe - HostForLIFE :: Implementing NgRx - Understand And Add Actions In Our Application

clock November 3, 2021 07:27 by author Peter

We have to add some more codes to make NgRx work.

So, the next step is to add the action.

Create a typescript file ‘user-list.action.ts ’ inside the Store folder

In this new file, we will define our action class.
Here, we need to send the action type and payload (user's name in our case) to the reducer.

But the angular Action interface doesn’t have the payload property. It has the type property only.
Since we need to pass a payload to the reducer, we will create a new class ‘UserListAction’ by implementing the Action interface. Action interface has only one property ‘type‘ so, we should implement it in our class.

Please refer to the screenshot below.

To minimize typo errors, it is better to avoid hard-coded strings in our codes. So, I just created a constant for the action type and used the export keyword to make it reusable in the reducer file.

Please refer to the code changes below.


I have changed the type property to read-only. This will ensure that its value never changes from outside.
Next, we should add another property ‘payload’ to pass the user name to the reducer function.
Please refer to the screenshot below.

Here, we imported the UserListAction class and ADD_USER constant from the user-list.action.ts file. And, we used the value of the payload property of UserListAction class to generate the new state. Done!

We have successfully added the action to our application.



AngularJS Hosting Europe - HostForLIFE :: Create an Angular Application and Implement NgRx Reducer

clock October 28, 2021 10:09 by author Peter

In my previous article, I've tried to explain the basics of NgRx framework. In this article, we are going to implement the NgRx in an Angular application. Let's create a simple angular application first. I have created a simple angular application with a text box to enter username and a button to add the entered name to an array.


An ordered list is created to display the users by looping through the contents of the array.

Please refer to the screenshots below.

The content of the App.component.html file is shown in the below screenshot.

The content of the App.component.ts file is shown in the below screenshot.


We can create an angular service to perform all the user related activities like adding user and keeping user list etc.
But for now, we have created a simple string array to keep the user list.

If we enter anything in the textbox on the screen and click Add User button, it will get inserted into the userList string array and immediately displayed on screen.
But our aim is to store and display the user list data from an NgRx Store.

Let's do it next!
First of all, we should install the ngrx library. We can use the below command to install ngrx library.
npm install –save @ngrx/store

BASIC
Once the installation completes, we can start implementing the NgRx in our application for state management.

Since the Store and reducers are tightly coupled together, we can create the reducer first.

Create Reducer
Please follow the below steps to create the reducer method.

  • Create a new folder under app.component folder and name it as ‘Store’
  • Inside new folder, create a typescript file and name it as ‘user-list- reducer.ts’

Please see the screenshot below.




The NgRx reduces is just a function with 2 arguments.

    Current state
    Action

We should export a function with any name we wish.

export function userListReducer(state, action:Action)
{
}

Action interface is imported from @ngrx/store
Please refer to the screenshot below.



We can use the action.type to identify the type of action such as add, update, delete, etc.

Let’s create an initial state as simple object
const intialState={
userList : [“David”, “Aleena”]
}


Then, in the reducer function, I added the initialState as the default value for the state variable

Please refer to the code snippet below
export function userListReducer(state=initialState, action:Action)
{
}


The action argument would have 2 properties.Type and payload(optional)

Based on the type, we can execute different logic inside reducer.

We can use multiple if statements or a switch statement in reducer function to accomplish this.

In this article, we are going to create add user action.

We cannot use the statement ‘initialState.userList.push(newUser)’.

Because, in ngrx, the state should be immutable - ie, we cannot change the current or previous state.

So, in ngrx,  we will copy the previous state and add the new change in copied state then return as new state.

In short, we should never touch the existing state.

Please refer to the code snippet below.
export function userListReducer(state = intialState, action: Action) {
  switch (action.type) {

    case 'ADD_USER':

      return { ...state, userList: [...state.userList, action] };

  }
}

Please refer to the screenshot below for better clarity.

Here we are using the spread (…) operator to copy the current state.

Spread operator is a new addition to the set of operators in JavaScript ES6. This operator is used to make shallow copies of javascript objects.

Let’s understand the above return statement first.

…state will copy all the properties of current state.

Then, we need to update its userList property.(here, we have one property only, but in real app, there might be multiple properties for a state and we might need to update any specific property only).

Since the userList is an array, we should copy all of its current elements using spread operator and then add the new user.

…state.userList pull-out all elements from the array and create a new array by adding a new user to it.

Finally, the reducer function will return the new state which is created immutably from the old state.

Now, at the first time when our application starts up and NgRx loads our reducer, it would initialize our state with the initial state.

To use that initial state and return it unchanged, we need to add a default case to our switch statement to handle any cases we're not explicitly handling.

NgRx will dispatch it automatically when it starts.

In default case, we simply want to return the unchanged state - initial state.

Please refer to the screenshot below.

Great!

We have created our reducer method successfully!



Node.js Hosting - HostForLIFE :: Invoke REST APIs In Express JS

clock October 5, 2021 07:03 by author Peter

This article will explain the steps involved in invoking APIs from the Express JS framework. The code below will assume the REST APIs are already developed and available for consumption.

Create a simple Express application
Use the below lines of code to create an Express app.

const express =require(‘express’);
const app = express();
app.get('/', function (req, res) {
  res.send('Hello World!')
})
app.listen(3000);

The app will respond with a Hello World message when a GET request is initiated (http://localhost:3000)

Invoke REST APIs

GET method,

const request = require('request');
//define http request implementation in a separate file to handle request input and output //parameters
async function getEmployee(req, res) {
    let body = req.body;
    let options = {
        hostname: ‘http: //sampleservice.com/’,
            path: '/api/Employee'
        method: ‘GET’
    }
    let result = await request(options);
    res.send(); // or return specific parameter value in JSON format
}


Invoke POST method,
async function UpdateEmployee(req, res) {
    let body = req.body;
    let details = {
        name: body.name,
        id: body.id,
        title: body.title
    };
    let options = {
        hostname: http: //sampleservice.com/,
            path: '/api/employee?' + new params({
                name,
                id,
                title
            }),
        method: 'POST'
    }
    let result = await request(options, details);
    res.json({
        body.id,
        body.name,
        body.title
    });
}


API calls also can be made using fetch command with minimal code, it requires at least Node.js 12.20 version.



AngularJS Hosting Europe - HostForLIFE :: Angular Components Communication

clock September 28, 2021 08:48 by author Peter

In the real-time project, we won't get the chance to work with only this type of component communication, we will come across scenarios where we will have to transfer the data between the components where there won't be any relationship.

The question is how to do that?
And the answer is the Subject or the BehaviourSubject.

The Subject and the BehaviourSubject
The Subject and the BehaviourSubject are the types of Observables that are provided by the RxJS library, this library is basically the one that provides us the ability to work asynchronously in the application.

This statement might not be clear at the moment but don't worry we will be discussing everything in detail.

There are a lot of features provide by this library but those are not in focus at the moment, so we are skipping that for now.

Implementation

Let's do a simple activity to understand the Subject and the BehaviourSubject.
Let's create a fresh/simple Angular application, we just need the basic structure in place that's it. I already have one created with a navigation menu which can be ignored for now.

Now I want to place two independent components on the UI and transfer data between those, so I created two simple components and placed those side by side in appComponent.html file.

The first component is having the textbox and the button and the second is having the label with default value as "nothing".

What I am looking for is to transfer the textbox value from component1 to the label of component2.

Above is the code of the appComponent.html file. I have used a few of the bootstrap classes for a better look and feel which can be ignored for now.
Now, in order to link these two components, I need to have something in common, for that, I have created a common service with the below code.

private subject = new Subject < any > ();
sendMessage(message: string) {
    this.subject.next({
        text: message
    });
}
getMessage(): Observable < any > {
    return this.subject.asObservable();
}

Let's understand this line by line.
First, I created an instance of a Subject of type any, then used that Subject as per the requirement.

The method sendMessage is used to populate the Subject.
The method getMessage is used to fetch the populated values from the Subject.

There is a method next available to the Subject which is used to populate the data in it and as we discussed earlier that it is a type of Observable so the return type of getMessage method will be Observable.

Now, how to use the Subject in the component classes?

The above screenshot shows the code written in component1 and in its code-behind file. We are just passing the value entered in the textbox to the common service to populate the Subject on the click event of the button. Notice that in this component we have the click event from where we can populate the data in the Subject.

 

Above is the code of component2 and its code-behind. In this, we are subscribing to the data which was populated in the Subject, and initializing its value to a class level property whose default value is "nothing", and ultimately binding it to the UI.

As Subject is a type of Observable, so whenever there is a change in its value the subscribe method gets invoked and subscribes to the latest value.

This is how a Subject or the BehaviourSubect is implemented.

Conclusion

The Subject or the BehaviourSubject is a type of Observable provided by the RxJS library.
These are used at the global level and can be subscribed from any component.

Note
The only difference between the Subject and the BehaviourSubject is that the BehaviourSubject needs some default value at the time of instance creation however it is not required for a Subject. The rest of the things are the same for both.



Windows Server 2016 SSD Hosting - HostForLIFE :: Automating Database And Folder Backups On Windows Server

clock September 20, 2021 07:34 by author Peter

It is unnecessary to state the importance of having an automated backup strategy for your servers.
Every server administrator has to go through the tiring job of setting up backups which include writing scripts, scheduling tasks, setting up alerts, and so on.

To simplify this task, I have designed a simple utility to help server administrators and database administrators automate backups. This utility can automate MSSQL, MySQL, and Folder backups.
 
This an open-source project hosted at GitHub.
 
You are welcome to suggest new features or contribute your own.
 
Part 1 - Installing the utility

 

  • Download the setup file from the GitHub repository (Installer\bin folder)
  • Install on the server where you need to set up backups

After you run the application, you will see the following screen:

Part 2 - Defining Backup Jobs
Click on the 'Settings' button on the bottom right to configure backup jobs.
On the first tab, 'MSSQL Server', click on the 'Add' button to add a new MSSQL backup.
 
Define the server details as shown below. Check 'Enable Backup' and specify the backup time


After entering the details, click on 'Validate and Save'.
The utility will try to connect with the MSSQL Server using the given credentials.
If the connection is successful, the entry will be saved and you will see it in the list as shown below,

Similarly, go to the second tab 'MySQL Server', and click on the 'Add' button to add a MySQL backup.


You can also backup specific server folders by using the 'Folder Backup' tab.


Part 3 - Specifying Local Storage Location
After defining the backup jobs, go to the 'Local Storage' tab and designate a folder on your server where you wish to store the backups.
Be careful that this folder should not be one of the backup folders, otherwise the program may behave unexpectedly.

Since all backups will be stored in this folder, it is recommended to set an auto-delete policy as shown above.
 
You can set a longer duration like 15 days or so as per your convenience.
 
Part 4 - Remote Storage

After backing up files locally on the server itself, we need to move them to remote storage.
Currently, the utility supports Amazon S3 backups. Go to the 'Remote Storage' tab and define your AWS credentials to automatically move files from 'Local Storage' to 'Remote Storage'.

You can also select the option to auto-delete files immediately after they are uploaded to AWS S3.
Click on 'Validate and Save' to check if the credentials entered by you are valid to write to the AWS S3 bucket.
 
Part 5 - E-Mail Alerts
You can easily set e-mail alerts to notify you of successful/failed backup jobs (both local and remote backups)
Click on the 'E-Mail Settings' tab and define your SMTP credentials as shown below.


There are four types of alerts available:

  • Send mail on failed local backup
  • Send mail on failed remote backup
  • Send mail on successful local backup
  • Send mail on successful remote backup

Click on 'Validate and Save' to check your e-mail credentials. This will send a test mail to the 'Recipient E-Mail' address. Click 'Close' to go back to the main screen.

The number of backups defined will appear here. It will also show the status of AWS S3 settings and E-Mail settings. Click on the 'Install' button to install a backup service to process your jobs in the background. This may take a couple of seconds. The status will change, as shown below:


To view logs, click on the 'Logs' button. Here you can find the logs of backup jobs and results for troubleshooting purposes. After this, you can click on 'Exit' to close the User Interface. The backup service will keep running in the background and will take care of defined backup jobs. To verify the backup service status, open 'services.msc' and check for service name 'Runtime Backup Service'

Here is a sample e-mail sent by the utility:


I hope this will help your business and save you lots of time in managing multiple backup scripts and configuring alerts. Using this unified interface, you can automate your backup jobs easily.


AngularJS Hosting Europe - HostForLIFE :: How Components Communicate With Each Other In Angular?

clock September 14, 2021 09:33 by author Peter

For better understanding, you should have a basic knowledge about what are components and how to build an application using that.

Components are the building blocks of Angular. So we need to understand how components communicate with each other.

There are three ways:
    parent to child - sharing data via input
    child to parent - sharing data via viewChild with AfterViewInit
    child to parent - sharing data via output and EventEmitter

Parent to child - sharing data via input
To share data from parent component to child component we use@input decorator.
Let’s configure the parent component and child component,
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: ` <app-child [childMessage]="message"></app-child> `,
  styleUrls: ['./parent.component.css']
})

export class ParentComponent {
  message = “I am a parent"
  constructor() { }
}

If you see the above code, <app-child> is used as a directive in the parent component. we are using property binding to bind the properties between child and parent, Binding child’s childMessage property with message property from the parent component.
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: ` {{ message }}  `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Input() childMessage: string;
  constructor() { }
}

To use@input decorative, we have to first import it from @angular/core . Next will decorate childMessage with @input decorative with type string. Lastly, display the message from the parent into the child template using string interpolation.

Child to parent - sharing data via ViewChild and AfterViewInit

It allows the child component to be injected into parent competent so that the parent component gets access to its child’s attributes and functions. We must note that parents will get access only after the view is initialized.

Let’s configure the parent component and child component
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";

@Component({
  selector: 'app-parent',
  template: `
    Message: {{ message }}
    <app-child></app-child>
  `,
  styleUrls: ['./parent.component.css']
})


export class ParentComponent implements AfterViewInit {

  @ViewChild(ChildComponent) child;
  constructor() { }

  Message:string;

  ngAfterViewInit() {
    this.message = this.child.message
  }
}

import { Component} from '@angular/core';

@Component({
  selector: 'app-child',
  template: `  `,
  styleUrls: ['./child.component.css']
})

export class ChildComponent {
  message = 'Hello Angular!';
  constructor() { }
}


We have to import ViewChild,AfterViewInit from angular/core, and the child component and use AfterViewInit life cycle hook so that we get access to the attributes in the child component. In the child component, we are passing the value for the message.

Child to parent - sharing data via output and EventEmitter
You use this approach when you want to share the data on button clicks or other events. The child component uses @output to send the data to the parent by creating an event with the help of an EventEmitter which is imported from @angular/core.

Let’s configure the parent component and child component
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
      <button (click)="message()">Send Message</button>
 `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  message: string = "Hey I am child !"
  @Output() messageEvent = new EventEmitter<string>();
 constructor() { }
  sendMessage() {
    this.messageEvent.emit(this.message)
  }
}

import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    Message: {{message}}
    <app-child (messageEvent)="receiveMessage($event)"></app-child>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
    constructor() { }
    Message:string;
    receiveMessage($event) {
        this.message = $event
    }
}

First, we have to import output and EventEmitter from the @anguar/core , then we are creating an event messageEvent using EventEmitter . when the button is clicked it calls the function sendMessage and calls the emit with the message. we are using event binding property with the child selector . The parent can now subscribe to this messageEvent that’s outputted by the child component, then run the receive message function whenever this event occurs.

I hope you understand how to pass data between the parent and child components.



Windows Server SSD Hosting - HostForLIFE :: Set Default Browser To Microsoft Edge Using PowerShell

clock September 13, 2021 09:51 by author Peter

This article will cover the steps to set the Microsoft EDGE as Default Browser using PowerShell if the current browser is Internet Explorer.

Need for the change

In 2021, Microsoft stops support for Internet Explorer for most Azure and Office 365 applications, forcing all the windows customers to use other Browsers or Microsoft EDGE as the Default browser to get web application support.

Microsoft also provided the documentation to set Microsoft EDGE as default using GPO by configuring DefaultAssociationsConfiguration. Here is the link to change the default browser for all users.

I thought of a solution that only changes the default browser if the current default is Internet Explorer, not changing anything for the user with Chrome or Firefox. I use simple PowerShell If condition to achieve the solution.

It's a simple three-step process.

    First, create the default associations configuration file as per the Microsoft document and store that to Network Share with access to all users.
    Second, use the PowerShell command to capture the current default browser.
    Third, use the if condition in PowerShell to match & create the registry key for DefaultAssociationsConfiguration.

I use the Microsoft document from the link to create an XML file that sets Microsoft Edge as the default application for specific protocols.
<?xml version="1.0" encoding="UTF-8"?>
<DefaultAssociations>
  <Association ApplicationName="Microsoft Edge" ProgId="MSEdgeHTM" Identifier=".html"/>
  <Association ApplicationName="Microsoft Edge" ProgId="MSEdgeHTM" Identifier=".htm"/>
  <Association ApplicationName="Microsoft Edge" ProgId="MSEdgeHTM" Identifier="http"/>
  <Association ApplicationName="Microsoft Edge" ProgId="MSEdgeHTM" Identifier="https"/>
</DefaultAssociations>

Store the XML to Network Share e.g. \\NetworkShare\EDGE\defaultapplication.XML

The next step is to capture the default browser details from the system using PowerShell.

To do that, we will check the registry value of ProgId at HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice.

$Path = (Get-ItemProperty HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice -Name ProgId).ProgId
$Path


The table shows the meaning of each value,

Value Data Browser
IE.HTTP Internet Explorer
ChromeHTML Chrome
MSEdgeHTM EDGE
FirefoxHTML-308046B0AF4A39CB Firefox

 

The next step is to create registry value DefaultAssociationsConfiguration at HKLM:\SOFTWARE\Policies\Microsoft\Windows\System and set the value data to the XML file on Network Share (\\NetworkShare\EDGE\defaultapplication.XML) using PowerShell.

$RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System'
$Name = "DefaultAssociationsConfiguration"
$value = '\\NetworkShare\EDGE\defaultapplication.XML'

New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType String -Force | Out-Null

Now merge both the PowerShell command and use the IF condition to match the value to IE.HTTP. This way, the script will only create the Registry value if the condition match else it exits the script.
$Path = (Get-ItemProperty HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice -Name ProgId).ProgId
$RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System'
$Name = "DefaultAssociationsConfiguration"
$value = '\\NetworkShare\EDGE\defaultapplication.XML'
$result = "IE.HTTP"
IF($Path - eq $result) {
    New - ItemProperty - Path $registryPath - Name $name - Value $value - PropertyType String - Force | Out - Null
}
ELSE {
    Exit
}


At the next reboot, the system will update Microsoft EDGE as a default browser.

This small PowerShell script will allow the System admins to change the default browser from Internet Explorer to Microsoft Edge without bothering Chrome and Firefox users.

Feel free to change the $result value in the command to use this script with any browser.

The administrator can use this script as a Logon script using GPO or Task Sequence in SCCM to push this configuration.

We have used the Basic PowerShell command to verify the default browser and change to Microsoft EDGE if the current default is Internet Explorer.



Crystal Report 2013 Hosting France - HostForLIFE :: How to pass Crystal Report Parameters Programmatically?

clock September 10, 2021 08:16 by author Peter

You can pass parameter values to a crystal report programmatically using ReportDocument.DataDefinition.ParameterFields member, which represents a collection of parameters associated with a report.

 
Before you use ParameterFields, you must import CrystalReport.Engine namespace by adding the following line to your code:
    Imports CrystalDecisions.CrystalReports.Engine

In my report, I have two parameters called ParameterName1 and ParameterName2 and I want to pass values as "Parameter1Value" and "Parameter2Value" respectively. If you have more than 2 parameters, just repeat the same steps between "START" and "END" commented lines. Also, read the comments in the code carefully.
' Create a report instance. This is the class added to your project  
' when you added the report to the project  
Dim report As MyReport = New MyReport  
   
' Fill data in DataSet here. Skip this step if your report is calling  
' a stored procedure direct  
Dim ds As DataSet = New DataSet  
' ds = GetDataFromDatabase()  
   
Dim crParameterDiscreteValue As ParameterDiscreteValue  
Dim crParameterFieldDefinitions As ParameterFieldDefinitions  
Dim crParameterFieldLocation As ParameterFieldDefinition  
Dim crParameterValues As ParameterValues  
         
'  
' Get the report parameters collection.  
'  
crParameterFieldDefinitions = report.DataDefinition.ParameterFields  
   
' Add a parameter value - START  
crParameterFieldLocation = crParameterFieldDefinitions.Item("@ParameterName1")  
crParameterValues = crParameterFieldLocation.CurrentValues  
crParameterDiscreteValue = New CrystalDecisions.Shared.ParameterDiscreteValue  
crParameterDiscreteValue.Value = "Parameter1Value"  
crParameterValues.Add(crParameterDiscreteValue)  
crParameterFieldLocation.ApplyCurrentValues(crParameterValues)  
' Add a parameter value - END  
   
crParameterFieldLocation = crParameterFieldDefinitions.Item("@ParameterName2")  
crParameterValues = crParameterFieldLocation.CurrentValues  
crParameterDiscreteValue = New CrystalDecisions.Shared.ParameterDiscreteValue  
crParameterDiscreteValue.Value = "Parameter2Value"  
crParameterValues.Add(crParameterDiscreteValue)  
crParameterFieldLocation.ApplyCurrentValues(crParameterValues)  
   
'  
' Set report's DataSource. Skip this step if your report is calling a   
' stored procedure direct in the report.  
'  
report.SetDataSource(ds)  
   
'  
' Set CrystalReportViewer.ReportSource  
'  
   
CrystalReportViewer1.ReportSource = report



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in