Showing posts with label Visual Studio 2013. Show all posts
Showing posts with label Visual Studio 2013. Show all posts

Sunday, November 2, 2014

How To Deploy Multiple Version of Component In GAC?

Scenario

I believe many programmers like to create shared component or common library in their work. When you see the code can be reusable and it is common for multiple different application, I am sure you will convert it into a framework and then apply them into your projects, so that you can save time from rewriting the same code for the same functionality again and again.

The most common way to deploy the shared component is to put the assembly into your application sub directory (the bin folder) and set the assembly reference in your application. The bad thing is it require you to do a lot of manual work by replicating and deploying the same assembly into every application sub directory.

Solution

We can deploy the shared component to Global Assembly Cache (GAC). Then, make your application reference the assembly from GAC.

Pre-requisite

Before you can deploy your assembly into GAC, you need to sign your assembly first. Just open up Visual Studio, go to your assembly project properties, then at the Signing page, check the "Sign the assembly" box.


Choose <New> from the drop down list to create a new strong name key file.


Simply put a key file name, and protect it with password (optional).

For testing, I have created a simple HelloWorld library to show the assembly version, and it will be used by multiple different application.


Folder Preparation

Create folders for your compiled assemblies for different versions.



Assembly Info

Set the assembly info in the project, and then compile it, finally put into the setup folder as above.


Set the AssemblyVersion and AssemblyFileVersion value for 1.0.0.0 and compile it and keep it into the folder for 1.0.0.0.

Now, make some code changes, then change the version value for 2.0.0.0, compile it and make sure not to overwrite the version 1.0.0.0 assembly file by placing them into different folder.

I changed the code to make it tells me its version is 2.0.0.0.


Installation

Open up Visual Studio Command Prompt. Change directory to where you keep the assembly files.

Run the gacutil.exe command with /i argument to install the assembly to GAC.



Verification

After the installation, you can check your assembly in GAC by running the following command:

gacutil /l HelloWorld


Add Reference

Now, change the assembly reference in your application from bin folder to GAC.

From the Add Reference dialog, you will not find your assembly from there. You have to click the Browse button and locate it from GAC assembly folder which is located at C:\Windows\Microsoft.NET\assembly\GAC_MSIL.


The assemblies in different version are being separated into different folder. The folder name convention is <.net version>_<assembly version>_<public key token>



Deployment

The assemblies installation to GAC is expected be done in both development and production environment. When the application reference the assembly from GAC in the development environment, it will do the same when it is deployed to production server.

Advantage

It is going to save time in deploying the same assembly file to every application and reduce human error. Sometimes developers forget to deploy the required assembly which is used by the application. They will notice it only when they failed to run the application.

Another reason is to save disk space. Instead of duplicating the same assembly into multiple different application sub directory (bin folder), you just have one copy from GAC and every application reference the same file.

Hmm, I find the above 2 advantages are just lame. :)

The good thing that I can think of is when all application are reference one same shared assembly source from GAC, when there is a bug fix for that assembly, you do not need to copy and replace the assembly in every application folder one by one. You can do a "on the fly update" by replacing the assembly in GAC, it will automatically apply the fix to all application which is using it.

The other good thing is side by side versioning. Sometime, you may encounter a situation when there are only a few application require the patch, the rest remain referencing version 1.0.0.0 assembly, those require patch will reference the new version 2.0.0.0 assembly. You can change the affected application assembly reference by using <codeBase> element in config file.


Will write more about using <codeBase> element in config file in my next post if I have time.

Monday, June 16, 2014

Remote Debugging with Visual Studio

Problem

In a normal software development process, when we are done with our software development, we deploy our application to the test environment for system integration testing (SIT) and then user acceptance testing (UAT). Sometime tester found a bug in the SIT or UAT environment, but the bug does not happen in our local machine. And then we would give a typical developer response: "I don't know, it works on my machine.".

The challenge here is due to the environment difference, it is difficult to trace the bug root cause. We can either guess or use trial and error method to fix the bug, otherwise, install Visual Studio into the server and then step into the code. But, we should not install any IDE tool or copy the source code to the server for debug.

Solution

So, today topic is how to remote debugging with Visual Studio. By using remote debugger, developer can remote attach the process in the SIT server and then step into the code from the Visual Studio in local machine.

Tool Setup

Remote Debugger exist since Visual Studio 2003. First, you need to download the Remote Debugger installer base on your Visual Studio version. For my case, I am using Visual Studio 2013, so I need to download Remote Debugger for Visual Studio 2013 from HERE. And then, install it on the server.

Application Deployment

First, compile your source code in Debug mode. Deploy all the compiled assemblies and generated symbol files to the server. The symbol files are those with .pdb extension, it also known as program database, those file contains the debug information that you need to step in to code. These files are normally generated at the same "bin" folder with your dlls.

Server Side Setup

Remote Debugger can be run as a program or windows service. If you prefer to turn on the remote debugger whenever you need it only, then run the Remote Debugger like running a normal program. Otherwise, run Remote Debugger Configuration Wizard to install the Remote Debugger as a windows service.


In today topic, I only cover about running Remote Debugger as a program. So, for the first time, when you run the Remote Debugger, you will be prompted for unblocking some firewall to allow remote debugging.


Just click the Configure remote debugging button to proceed.


The Visual Studio Remote Debugging Monitor must be running all time whenever you need to do remote debugging. Take a look at the description, it actually tells you the port number that it used to listen. You need to connect to that server name and port from Visual Studio.

You can change the port if the default port 4018 is being used by other program by opening the Options from the Tools menu.


And then, by default, Remote Debugger uses Windows Authentication mode. Make sure you have given permission to the account that you use to run Visual Studio. Click the Permissions button and then give the Debug privilege to the account that you want.

Local Machine Setup

Now, open Visual Studio and then open your project, then put some breakpoints in your code. Click the Debug menu, then open the Attach to Process window.



At the Qualifier field, enter the server IP address and port, then click the Find button.


A list of processes on the server will be populated. Now, you can find your process and then click the Attach button.

If you are running a windows application, windows service or console application on your server, you can straight away look for the executable to attach. If you are hosting an ASP.NET application or WCF web service, then you should look for IIS worker process (w3wp.exe) to attach. For IIS worker process, it is recommended to configure running under an application pool identity. So that it is easier to detect and attach the correct IIS worker process.

Once you click the Attach button, the Remote Debugger will show you or someone has connected to it.


Now, you can start playing with your application to purposely reproduce the bug. The breakpoint that you put in your code in Visual Studio will be hit. From there you can debug your code base on the assemblies that running on your server.



Happy debugging!


Friday, March 7, 2014

VS2013: BrowserLink Cause Javascript or jQuery Perform Very Slowly

Today one of the developers came to me asking for help regarding his web page performance is very bad. His web page contain less than 50 lines of javascript code and using latest version of jQuery. What actually happen is after the page load, it binds a jQuery change event to a dropdown list control, but it takes a few seconds time to complete. We know that by simply clicking the dropdown control, the browser is not responding.

Environment

Project Type: ASP.NET Web Form
IDE Tool: Visual Studio 2013
Browser version: IE11
CPU: i7-3720QM
Memory: 16GB

With the above hardware spec, the browser should not perform badly with a simple javascript. We have tested with IE6 and IE11, we experience the same behavior for both browsers. From the task manager, we realize that the browser process actually spike up the CPU and memory usage for few seconds after the page load.

Profiler

In order to further investigate, I turn on the profiler from my IE11. In case you are not aware of IE actually has a built-in profiler, just press the F12 key, then look for Profiler, click the Play button to start profiling your web page.

Note: Start profiling only when you are ready to load the problematic page. If you start profiling at the starting page, the profiler results are accumulating and you will find too much data and difficult in tracing the actual problem.


So, after loading the problematic web page, I stop the profiler, and to my surprise there are a lot of functions call from a unknown script.


Notice the URL? The browserLink look fishy to me. After some searching, I realize this is a new feature from Visual Studio 2013 which is used to create communication channel between browsers. This article actually recommend you to turn off the BrowserLink before you publish your application.

My developer tested the web page with IE6, his profiler result is slight different from mine, there are a lot of anonymous function call to a URL that contain "poll" keyword. At first thought he may have implemented SignalR in his project that causing the problem, but he is 100% sure no SignalR was developed in his project.

After further explore and understanding how Browser Link work, it actually use SignalR and it explain the result of IE6 profiler show the "poll" keyword because IE6 do not support web socket, SignalR internal change the communication method with polling. Here is the quote from the ASP.NET site article:

"Browser Link uses SignalR to create a communication channel between Visual Studio and the browser. When Browser Link is enabled, Visual Studio acts as a SignalR server that multiple clients (browsers) can connect to. Browser Link also registers an HTTP module with ASP.NET. This module injects special <script> references into every page request from the server."

Solutions

The problem should not happen if you are aware of purpose the debug mode in your config file and you always turn it off while publishing your application to production environment. 

<system.web>
  <compilation debug="true" targetFramework="4.5" />
</system.web>

But, we tested out that turning off debug mode only is not enough, we have to disable the Browser Link from the Visual Studio 2013 before publishing your project, then only you will see the performance improve and no more SignalR stuffs flooding from your profiler.


Alternatively, add the following AppSetting to your config file.

<appSettings>
  <add key="vs:EnableBrowserLink" value="false"/>
</appSettings>



Sunday, January 12, 2014

SSDT : External Database Reference Error

Today I face a challenge with SSDT (SQL Server Data Tools). I encounter some errors when I have multiple database references in my SQL Server Database Project in Visual Studio 2013.

The errors that I am facing now:

SQL71561: View: [dbo].[View_1] has an unresolved reference to object [DatabaseB].[dbo].[Table_1].
SQL71501: View: [dbo].[View_1] contains an unresolved reference to an object. Either the object does not exist or the reference is ambiguous because it could refer to any of the following objects: [DatabaseB].[dbo].[Table_1].[Column1] or [dbo].[Table_1].[t2]::[Column1].

After googling around, the suggested cause of the errors is I am using 3 part name for the same database and then using the table which comes from different database in my query without having database reference in my project. The actual root cause is the database project itself perform database object validation at the background, and it cannot find the other database.

SELECT t1.*
FROM Database1.dbo.Table_1 AS t1
LEFT JOIN Database2.dbo.Table_1 AS t2
ON t1.Column1 = t2.Column1

Therefore, I have added other database projects that I need into my solution like the following screenshot.


Then, add the required database reference. Note that I do not need database variable, so I left the field empty. The example usage is correctly showing how I should and would use the database reference.


After that, I rebuild my project but I am still getting the same error. I have no choice but to remove the 3 part name for current database and remain the 2 part name as highlighted red in above query.

Finally, no more error has occur and my project is able to be built. Happy! But, later discover that there are more challenges await me.

See my solutions explorer screenshot above, I have more than two databases. I have a lot more complicated queries that need to deal with multiple databases. For example:

In Database1:

SELECT t1.*
FROM dbo.Table_1 AS t1
LEFT JOIN Database2.dbo.Table_1 AS t2
ON t1.Column1 = t2.Column1

In Database2:

SELECT bla bla bla
FROM dbo.Table_1
UNION ALL
SELECT bla bla bla
Database1.dbo.Table_2

So, as you can see Database1 need to add Database2 as database reference and then Database2 need to add Database1 as database reference too. If you go and do that in Visual Studio, you will get the following error:


A reference to library 'Database' cannot be added. 
Adding this project as a reference would cause a circular dependency.

It seem like Visual Studio treat the database reference as assembly reference. Having both database projects referred to each other is considered as circular reference. So, how am I suppose to do now?

I found a workaround but not everyone may accept it. I realize that by adding Data-tier Application Package (*.dacpac) as database reference, Visual Studio will not complain about circular dependency. Therefore, I try to extract dacpac for all the related databases by using SQL Server Management Studio (SSMS).



Just click Next button all the way until the Finish. By default, the Data-tier Application is extracted and stored at C:\Users\[UserName]\Documents\SQL Server Management Studio\DAC Packages\[DBName].dacpac. I would recommend to extract the DAC package files to a centralized location, so that it is easier to retrieve, track and manage the packages later.

While extracting the DAC package file, you may encounter the same error SQL71561 and SQL71501 again.


You have to extract the package manually by using SQLPackage.exe.

The location of the SQLPackage.exe is C:\Program Files (x86)\Microsoft SQL Server\[version]\DAC\bin

Below is the command line that I use to extract dacpac:

sqlpackage.exe /Action:Extract /ssn:. /sdn:Database1 /tf:"E:\DAC Packages\Database1.dacpac"

/ssn = Source server name
/sdn = Database name
/tf = Target file

More parameters info can be found HERE.



After you have all the DAC packages ready in one centralized location, now back to Visual Studio to add them as database reference.



My current setup is:
Database1 has Database2 as reference.
Database2 has Database1 as reference.

No more circular dependency complaint and no more database reference not found error. Also, another advantage of using DAC package as database reference is you need not to create or add other database project which is not developed by you to be included into the solution.




Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...