Getting the IP Address of the client in a Windows Azure Role

Are que getting null or empty with some Request.ServerVariables

When you convert your ASP application to run on Windows Azure it is a good
to put attention to the methods that are used to get the user IP Address.
Normally the recommendation will be to use Request.UserHostAddress however
our friend Alex has found that this property can return null or empty.

After some research Alex found that there are several scenarios under which
you must check both the REMOTE_ADDR and the HTTP_X_FORWARD_FOR server variables:

More info:
http://forums.asp.net/t/1138908.aspx and
http://meatballwiki.org/wiki/AnonymousProxy

A possible code snipped that can provide a value for the client address can be:

public static string ReturnIP()
        {
            var request = System.Web.HttpContext.Current.Request;
            var ServerVariables_HTTP_X_FORWARDED_FOR = (String)request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            var ServerVariables_REMOTE_ADDR = (String)request.ServerVariables["REMOTE_ADDR"];
            string ip = "127.0.0.1";
            if (!string.IsNullOrEmpty(ServerVariables_HTTP_X_FORWARDED_FOR) && 
                !ServerVariables_HTTP_X_FORWARDED_FOR.ToLower().Contains("unknown"))
            {
                ServerVariables_HTTP_X_FORWARDED_FOR = ServerVariables_HTTP_X_FORWARDED_FOR.Trim();
                string[] ipRange = ServerVariables_HTTP_X_FORWARDED_FOR.Split(',');
                ip = ipRange[0];
            }
            else if (!string.IsNullOrEmpty(ServerVariables_REMOTE_ADDR))
            {
                ServerVariables_REMOTE_ADDR = ServerVariables_REMOTE_ADDR.Trim();
                ip = ServerVariables_REMOTE_ADDR;
            }
            return ip;
       }

In the previous code the HTTP_X_FORWARDED_FOR value is examined first and if it is not null or unknown then ip address of the client
is gotten from there.

Windows Azure and Websites in a Flux

1. May 2011 07:47 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

Windows Azure is a great platform and the escalatity oportunities are great,
and deployment time is also great.
You can have all your website up and running in just 10-15minutes.

But… and yes there is always a but.

Sometimes you can have a WebSite that is not that static, that as a matter of fact
you are changing its views constantly. Specially if some ideas are not finished.
And yes you can test locally, but there is also a situation where you might want to have that flexibility.

Well looking around I found a very interesting solution by
Maatern Balliauw. http://blog.maartenballiauw.be/post/2009/06/09/A-view-from-the-cloud-(or-locate-your-ASPNET-MVC-views-on-Windows-Azure-Blob-Storage).aspx

What he proposes is to use windows azure storage as a virtual file system, so you can with simple tools
like the Windows Azure Explorer modify your web pages without the need of going through a lengthy republish process.

So go ahead and keep enyoing Azure

ASP Migration COM+ and security

18. February 2011 02:53 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

Typical ASP applications were built as a layer of simple ASP with some
COM+ components that did the heavy lifting.

Now, when you migrate your ASP application to ASP.NET and you also migrate your
COM+ components to .NET then you might encounter some issues with security.

One common issue is impersonation.

Sometimes the COM+ were created to use the current user account.

clip_image002

 

clip_image002[6]

And there is a slight 
difference between ASP and ASP.NET:

“Impersonation is when ASP.NET executes code in the context of an authenticated and authorized client. By default, ASP.NET does not use impersonation and instead executes all code using the same user account as the ASP.NET process, which is typically the ASPNET account. This is contrary to the default behavior of ASP, which uses impersonation by default. In Internet Information Services (IIS) 6, the default identity is the NetworkService account.”

That will cause errors in your ASP.NET application like:

 

clip_image002[8]

To solve this issue you must use ASP.NET Impersonation, and to enable impersonation go to the web.config file and add:

<identity impersonate=”true”/>

For more info on impersonation see: http://msdn.microsoft.com/en-us/library/aa292118(v=vs.71).aspx

IIS targetFramework not supported

31. January 2011 10:55 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

 

I had a situation where the IIS reported that the targetFramework=4.0 attribute
was not supported.

I’m not sure why it started reporting it, but I fixed it with this:

%windir%\Microsoft.NET\Framework\v4.0.21006\aspnet_regiis.exe -i

ASP to ASP.Net Migration: Fixing Includes

24. January 2011 08:43 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

During a migration from ASP to ASP.NET one of the biggest hurdles is finding a way to deal with the include files.

ASP was a interpreted environment whether ASP.NET is compiled and this difference is very important because you need to find ways more natural in .NET to do some things you used to do in ASP.

For example in ASP you used to have a set of common functionality that was included in your files. What will you do with that?

For ASP ASP.NET in VB.NET is a lot easier. One of the things you can do is move all those common subs and functions to a Module.

Now if what you have is a ASP.NET Web Site, then just your new modules to the App_Code folder and voila your pages are now able to see that code.

For a ASP.NET Web Application is just a little differente. What you have to do is move your common variables, constants, subs and functions to a Module, but that is not enough to make that code reachable from your mark up, so you have two alternatives:

1. Add an %@import Namespace=”QualfiedNamespaces.Module1”  statement for each of your modules.

2. Modify your web.config file and add under system.web something like:

<system.web>
              <pages>
                     <namespaces>
                           <add namespace="WebApplication1.Module1"/>
                     </namespaces>
                     
              </pages>

That will add an implicit import for all your pages.

For C# it can be a little more complicated. Because you do not have modules like in VB.NET, what you can do is use extension methods, to have a similiar syntax.

Migrate JSP to ASP.NET MVC

14. December 2010 06:19 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

ASP.NET has gone a long way. And it might be the right time to start moving your sites to ASP.NET.

But what happens if you have a big investment in JSP. Will I lose all my JSP skills?

Well ASP.NET is not the same as JSP but the MVC view engine concept can help you retain some of the JSP flavor.

A good MVC View Engine project is SharpTiles this project provides a partial implementation of JSTL and Tiles.

Just take a look at the the SharpTiles. Just as they say SharpTiles if for you if “You are a Java Developer and you don’t like .aspx”

Continuous Migration VBUC-MS Team System 2005:Upload an initial version of your VB6 code

22. September 2009 09:34 by Mrojas in   //  Tags: , , , , ,   //   Comments (0)

Now all we need to do is setup the VB6 code that we will use for migration. To do that follow these steps:

1. On the Source Code Explorer toolback click on the Add Files button:

image

 

 

2. Click the Add Folder button and select the folder with your VB6 files

image

3. After you select the folder, a list of files found will be shown. Just remove any unneccesary files. For example files like MSSCCPRJ.SCC should be removed. And press OK

image

Now you have to commit your code the Source Code Repository

4. On the Source code Explorer Right click on Source Control Folder (for this example is MergeExample) and select Check In Pending Changes..

image

5. Write an apropiate comment and press Check In

Bittable What????

As vb6 migration experts in our company we deal everyday with a lot of issues around Interop and serialization.

One important thing to note is the concept of “Bittable Types”. I’m not making up terms. Those terms actually exist. Just see this link in MSDN.

In a few words, a bittable type is a type that has the same representation in managed and unmanaged code.

Why in earth is that important at all?

Because if you are calling that great C++ DLL implemented some years ago that just works ok, you won’t be able to pass a NON-Bittable type because that DLL will expect a binary representation different from that in the .NET virtual machine.

This is also an issue in other scenarios like:

  • Serializing content to files
  • Sending messages through messaging mechanisms like named-pipes or sockets.

Well, we have just introduced the problem so now let’s think on a nice solution for this problem.

Well Bittable Types are:

The following types from the System namespace are blittable types:

 

So now let’s look at a couple of non-BITTABLE types

DateTime

To test this differences let’s make a small test in VB6 and write a Date value to a file:

 

Private Sub SaveDateToFile()
    Open "C:\test1.bin" For Binary Access Write As #1
    Dim d1 As Date
    d1 = "1/1/2009"
    Put #1, , d1
    Close #1
End Sub

Now let’s make a quick program in Vb.NET

 

Sub Main()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test2.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        Dim val As Long = d.ToBinary()
        fw.Write(val)
        fw.Close()
        Main2()
    End Sub

 

If we compare these files we will have:

image

So the values are obviously different. This is because VB6 Date are stores with the OLE Automation DateFormat

So let’s change the C# code for something like:

 

    Sub Main2()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test3.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        fw.Write(d.ToOADate())
        fw.Close()
    End Sub

And now when we compare the files we will have:

image

 

So to make your Date values compatible with VB6 format you must user the DateTime method .ToOADate. Now if you are calling a DLL that expects a Date value in the same format used by VB6 then you will have to do this:

 

        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        Dim handle As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(d.ToOADate(), Runtime.InteropServices.GCHandleType.Pinned)
        Dim memory_address As IntPtr = handle.AddrOfPinnedObject()
        Try
            APICall(memory_address)
        Finally
            d = DateTime.FromOADate(System.Runtime.InteropServices.Marshal.ReadInt64(memory_address))
            handle.Free()
        End Try  

 

String

Most of the time you wont have to deal with String marshalling because adding marshaling tags to your API call solves most of the problems, but if you arent that luckyly then you might do something like:

IntPtr ptrToStringVar = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(strVar);
try
{
   APICall(ptrToStringVar);
}
finally
{
strVar = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrToStringVar);
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptrToStringVar);
}

NOTE: if you have an API that might return an string with /0 characters you must call the API with System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrToStringVar,size), if you do that the Framework will take in consideration the size bytes at the ptrToStringVar memory address.

 

Double and Singles

At least between VB6 and VB.NET the double and single types follows the same format. Well, at least, that is the result of my tests.

Try it yourself, the following shows a simple test for double variables:

VB6

Private Sub SaveDoubleToFile()
    Open "C:\test1.bin" For Binary Access Write As #1
    Dim d1 As Double
    d1 = 1.123
    Put #1, , d1
    Close #1
End Sub

Sub Main()
    SaveDoubleToFile
End Sub

 

.NET

Module Module1

    Sub Main()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test2.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Double
        d = 1.123
        fw.Write(d)
        fw.Close()
    End Sub


End Module
 

So you could make an api call in those cases with something like:

Dim handle As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(d, System.Runtime.InteropServices.GCHandleType.Pinned)
Dim ptr As System.IntPtr = handle.AddrOfPinnedObject()
Try
    APICall(ptr)
Finally
    handle.Free()
End Try

Change CreateObject during Migration

One of our clients wanted to change the CreateObject function migration for a function of their own. So they wanted all cases like:

Dim x As Object
Set x = CreateObject("Excel.Application")

 

To be migrated to something like:

Excel.Application x = (Excel.Application) Utils.MyCreateObject("Excel.Application", "");

Our migratio vb6migration tool provides a new cool feature called CustomMaps. This feature allows you to provide some simple but useful changes to the way things get migrated.

For this case follow these steps:

1. Open the Visual Basic Upgrade Companion.

2. In the Tools Menu choose:

image

3. Create a new CustomMaps File and an an entry like the following:

 

image

Notice the Source name is VBA.Interaction.CreateObject. To find out this name you can look in your VB6 IDE, right click on the CreateObject and select goto Definition.
image 
 
image 
and for the target name just put the implementation that you what, for example you can write a function like:
class Utils
        {
            public static object MyCreateObject(string className,params object[] ignoreRestParams)
            {
                return Activator.CreateInstance(Type.GetType(className));
            }
        }

and set the SourceName to Utils.MyCreateObject (or NameSpace.Utils.MyCreateObject to use the fully qualified name). You just need to set the New Reference Name column because we will not change the definition of the function.

Get path of ASP.NET web application that is running

If you have your ASP.NET application for example in c:\inetpub\wwwroot\WebApplication1 and you want to programmatically get that path just use something like:

 

string AppPath = Request.PhysicalApplicationPath;

ADODB RecordSet Save in C# ASP.NET

9. October 2008 04:10 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

I saw this with Francisco and this is one possible solution:

ASP Source

rs.Save Response, adPersistXML

rs is an ADODB.RecordSet variable, and its result is being written to the ASP Response

Wrong Migration

rs.Save(Response <-- The ASP.NET Response is not COM, ADODB.Recordset is a COM object, ADODB.PersistFormatEnum.adPersistXML);  

 So we cannot write directly to the ASP.NET response. We need a COM Stream object

Solution

ADODB.Stream s = new ADODB.Stream();

rs.Save(s, ADODB.PersistFormatEnum.adPersistXML);               

Response.Write(s.ReadText(-1));

In this example an ADODB.Stream object is created, data is written into it and the it is flushed to the ASP.NET response

Vb Migration (not for the weak of mind) Post 2

14. August 2008 05:50 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

When people decide to migrate their VB6 applications they eventually end up questioning where they should go. Is VB.NET or C# a good choice?

I have my personal preference, but my emphasis is in developing the technology to take where YOU want to go.

VB.NET is a VB dialect very similar to VB6. It supports several constructs and it makes the changes easier.
C# has several differences from VB6, but it has it a growing language with lots of enthusiasts in its community.
Obviously migrating VB6 to VB dialect is a task far more easier than migrating to a different language.
However we are a research company with years of work in this area and challenges is just what we love.

Let's use a methaphor here.

My beautiful wife, was born in Moscow, Russia. Like her, I really enjoy reading a good book. Some of my favorite authors are
russian authors like Dostoievsky, Tolstoi and Chejov. However I still do not speak russian. I have tried, and I will keep trying but
I still don't know russian. I have read only translations of their books, and I really enjoy them.
As a native speaker my wife always tells me, that it is not the same to read those books in another language besides russian.
And they are phrases (specially in Chejov books that I might not completely understand) but I really got the author
message and enjoyed it.
Translating a book from russian to a more similar language like Ucranian is easier than translating it to English or Spanish.
But I think everybody agrees that is a task than can be done.

You can use terrible works case scenarios, but these scenarios must be analized.
Let see (I took these example from the link in that Francesco put in my previous post http://blogs.artinsoft.net/mrojas/archive/2008/08/07/vb-migration-not-for-the-weak-of-mind.aspx)

If you have code like this:

Sub CopyFiles(ByVal throwIfError As Boolean)
    If Not throwIfError Then On Error Resume Next
    Dim fso As New FileSystemObject
    fso.CopyFile "sourcefile1", "destfile1"
    fso.CopyFile "sourcefile2", "destfile2"
    fso.CopyFile "sourcefile3", "destfile3"
    ' seven more CopyFile method calls …
End Sub


and you translate it to:

void CopyFiles(bool throwIfError)
{
    Scripting.FileSystemObject fso = new Scripting.FileSystemObjectClass();
    try
    {
        fso.CopyFile("sourcefile1", "destfile1", true);
    }
    catch
    {
        if (throwIfError)
        {
            throw;
        }
    }
    try
    {
        fso.CopyFile("sourcefile1", "destfile1", true);
    }
    catch
    {
        if (throwIfError)
        {
            throw;
        }
    }
    try
    {
        fso.CopyFile("sourcefile1", "destfile1", true);
    }
    catch
    {
        if (throwIfError)
        {
            throw;
        }
    }
    // seven more try-catch blocks
}

I think that the russian is really keep in this translation.

First of all. When you do a translation, you should try to make it as native as possible. So why will you keep using a COM function when there is an
equivalent in .NET. So why not use System.IO.File.CopyFile("sourcefile1", "destfile1", true); instead?

Second of all. The On Error Resume Next, I agree is a not a natural statement in C#. I really think that using it could provide results that are less predictable.
Why? Becuase after executing it, are you sure that all the CopyFile occurred successfully? I would prefer wrapping the whole code inside a try-catch instead of trying
to provide an implementation that is not natural in C#, will Aspect Oriented programming provide a clean solution for this cases. Maybe?

RPG and COBOL to Object Oriented Programming, PowerBuilder to C#, Hierarquical Databases to Relational Databases are just the kind of challenges we have faced in our research project.
Not everything is easy, and we might not be able to automate all the tasks (commonly due to the cost of implementing the automation not becuase of feasability).

But at the end Could you understand the whole novel?, even if you didn't understand the joke in the one of the paragraphs in the page?

My years of reading make be belive that you can.


 

VB Migration (not for the weak of mind)

7. August 2008 05:14 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

Motivation: 

I hate to be disappointed. Specially if it is by a person you had respect for. And that's exactly what Francisco Balena from VB Migration Partner, has done. I have respected him for his books and all his VB6 experience. In terms of legacy VB6 code he is a monster. He is the man.

But in terms of code migration...

I'm not saying this because I work on code migration or maybe I'm biased a little by the fact that I work almost 10 years with a company that has done source code migration research on a big number of legacy languages such as COBOL, RPG, PL\1, Algol, Progress, PowerBuilder and also VB6.

I can tell the difference between a "compiler" and a system that rewrites a expression to the closest equivalent in the target language. We are aware of limitations. We are aware of paradigm differences and functional equivalence, but we talk from experience. We talk about our results. And we have proven those things we talk about.

 Let's says you create a Cobol Library with a "MOVE" function, and a COBOLPicture Type and add minus, divide, and add operators. And I write something like:

CobolPicture x = new CobolPicture("XXXX");

x.move(10);

x.add(10);

We have things like that, and it works. It's feasible and maybe there are cases where that is a solution. But we are also proud of have researchers that have been able to detect pattern to rewrite something like that like:

int x = 0;

x = 10;

x+=10;

And saying, that something is not possible just because you can't or you dont like it, just seem uneducated to me.

 All of this has motivated me to start a series of chapters I for a small blog book I will call VB Migration (not for the weak of mind).

For those of you, who really are tecnology savvy and are in the process of a VB Migration, this is YOUR book.

Debugging AJAX

12. December 2007 05:00 by Mrojas in General  //  Tags: , , ,   //   Comments (0)
AJAX applications are great
Their coolness factor is high, and your clients
will be trilled by the new interactivity of your pages
But as a developer when you have a problem with
AJAX it could be hard to track. Because there is
a lot going on behind the scenes
Some of our costumers migrate their ASP applications to
to ASP.NET and it's natural that they want
some AJAX in it.
So I found a GREAT GREAT application for AJAX debugging
It's called fiddler. I cannot describe it all for you so go its site and watch the videos
The tool is just amazing :)
It really can see everything that the browser
receives and sends and more.
A definitive must Fiddler

Localize your VB apps

28. May 2007 06:45 by Mrojas in General  //  Tags: , , ,   //   Comments (0)
Localize a VB6 application can be cumbersome, specially if it was not even originally planned to be localized.
Nowadays is common that you're clients might demand support for different languages.
While a localization task is still difficult, we have found excellent results performing it during a VB Migration.
Our tools allow us to easily externalize all your strings. After that the traslation task becomes easy, and you can even use the help
of nice projets like Automatically Translate your .NET resource files with Google Translate

ASP to ASP.NET: File exists

31. December 2006 07:30 by Mrojas in General  //  Tags:   //   Comments (0)


This is the migration of a snippet of ASP classic to ASP.Net

 

Checking that a File Exists ASP Classic

<%
Dim strExists  
Dim strNotExists 
Dim objFileSystemObjectVar
``
strExists    = "exists.txt"
strNotExists = "error.txt"
 
Set objFileSystemObjectVar = Server.CreateObject("Scripting.FileSystemObject")
 
' The FileExists method expects a fully qualified path and
' use Server.MapPath 
%>
<p>
&quot;<%= strExists %>&quot; exists:
<b><%=objFileSystemObjectVar.FileExists(Server.MapPath(strExists)) %></b>
</p>
<p>
&quot;<%= strNotExists %>&quot; exists:
<b><%= objFileSystemObjectVar.FileExists(Server.MapPath(strNotExists)) %></b>
</p>

 

Checking that a file exists ASP.NET

 

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<script language="VB" runat="server">
        Dim strExists As String = "exists.txt"
        Dim strNotExists As String = "error.txt"
</script>
<p>
&quot;<%= strExists %>&quot; exists:
<b><%=File.Exists(Server.MapPath(strExists))%></b>
</p>
<p>
&quot;<%= strNotExists %>&quot; exists:
<b><%= File.Exists(Server.MapPath(strNotExists))%></b>
</p>
 

 

 

Categories