ASP.NET WebForm 2.0 work in Windows Server 2012 R2 again

There is a medium web application in the company that is in use since 2006 to now (2016). This web application is developed with ASP.NET Webform and .Net 2.0 in days of AjaxControlToolkit. For those unfamiliar with that, AjaxControlToolkit and UpdatePanel was an easy way for ASP.NET developers to make use Ajax, the hot technology of the day, in their web applications. Our company web application is hosted in a MS Windows 2003 and now must be hosted to a recent Windows version happened to be MS Windows 2012 R2. This story is about how we manage the application work again in new environment.

The application files copied to a folder in inetpub\wwwroot then an application created for it in IIS. Application was not working with .Net 2.0 App pool because of error “HTTP Error 404.17 – Not Found”. We decided to make it work with a .Net 4.0 App pool. The first error dumped was easy to handle. ASP.Net 4 has some entries of old web.config files into itself so was throwing error duplicate entries. This problem solved by removing those entries from web.config. After it the application get up correctly.

After some usage of the application we explored that some internal tabs are not opening after clicking. Guessing started here. The first guess was that IIS is not serving some file like a .js or a .css file correctly. It was no true because IIS logs and browser profilers did not record any relevant 404 error. Second guess was that something is wrong with AjaxControlToolkit. Our guess was that panels are changed with help of AjaxControlToolkit and UpdatePanel. I checked with Chrome's developer tool. No related console error existed. In another try I changed versions of System.Web.Extensions and AjaxControlToolkit to 3.5.0.0 but didn't helped. Next time added assemblyBinding to web.config but this does not helped too. Event logs of Windows showed no suspicious item too. Several searches in Google neither helped too.

Being hopeless decided to debug client side code of the application in the Chrome developer tool despite of its 4.5K lines of code of legacy ASP.NET WebForm 2.0 application. Started my work by examining JavaScript function that was called by tab headers. javascript:__ShowTAB('ctl00_ContentPlaceHolder1_Panel3',3) was one of those functions. Tracing function calls showed that in an “if comparison” client Ids are not equal. I found it! Client Id generating was changed from .Net 2.0 to .Net 4.0. New one was shorter and didn't had prefix “ctl00_” in beginning of it. A StackOverflow question had same problem. A 2010 post of Scott Gu was showing the complete cause of the problem. ASP.NET 4 WebForm has been moved along a way to generate a cleaner client id. This behavior could be controlled via ClientIDMode. Unfortunately default value of this property was not AutoID while ASP.NET 2.0 behavior was as same as AutoID. I added ClientIDMode = AutoID to the directive of the master page and the problem solved peacefully.

Data history tracking

One of common features in information systems especially in enterprise systems and in systems that has important auditing is history tracking. System operators want to know each data change in the system is done by who in what time. This is true in financial and health information systems.

 

Versioning

Different software use different approaches. Web content editing software like Wikipedia and WordPress use versioning mechanism while editing content of an entry. They keep every changes made to an item. So all modifications during several years exists and can be reverted to. This approach usually is good when one or two database tables are tracked this way. Also one or two fields of them are tracked. Otherwise database volume growth will be very huge after a while. Old day developer used to use WORM storage medias so forced to use versioning approach by nature. They were not able to change saved records, instead inserted new records with increased version number.

 

Full History

Some software solutions use full history strategy. They blindly log every record change automatically. For example consider you modify and Order info and its OrderItems. This translates to multiple record update in database level. A History table will be populated with same count of records indicating old value and current value of modified records (serialized value of all the row), time and person who triggered the change. Utilizing this approach helps finding every tiny information change but also will create large amounts of redundant data that large percent of them will never be used. It's triggering nature may cause cycling problem in addition to performance overhead. Event sourcing technique can reduce performance and storage usage footprints of full history approach.

 

Process Level Log

Referential integrity, performance overhead, redundancy and data storage waste are obvious weaknesses of versioning and full history approaches. There is another approach that can not be automated like them and does not have high level of accuracy but instead does not suffer from mentioned weaknesses. This approach is done via manual call of logging utility in each high level entry of the system. Process refer to use case scenarios of system usage in the view of end user. Each process begins in high level entries of the system. Developer will fill a brief description of data change, purpose of it and the user or system that triggered it. It can include some detailed information of record changes for advanced auditing usages. A sample class diagram would be like following.

AuditHistory

Custom authentication in Asp.Net Core

ASP.NET Core does not have built-in membership for Active Directory. Developers can use Azure Active Directory or external membership services like Facebook and Linkedin or standard ASP.NET Identity mechanism, but are not able to use Active Directory directly. Visual Studio 2015 has removed Active Directory authentication from its web application template:

asp-net-core-authentication-active-directory

 

ASP.NET Core does not have web.config so old school ActiveDirectoryMembershipProvider does not help. ASP.NET Core use middleware mecahnism for handling requests. Settings cookies and checking it back in the server has been changed.

 

In order to do authentication in ASP.NET Core with Active Directory or any other resource like your own database back end you can take a look at following code.


 

This code must be put in Configure method of Startup class of the project. This tells application to use cookie for authentication. Every information is put in cookie, attached to response and sent back to the user. User attaches this cookie to all his/her requests and sent to the server again. This cookie is encrypted and contains Username, Role and other claims added by server code.

 


 

This code in used in sign in page. This is the place that you validate user entered credentials against a database or resource like Active Directory. For more information see here and here. Also I found a library for the whole process but was not successful to use it.